Merge pull request #9062 from tom-daubney-arm/crypto_config-tls1_2_default_stream_cipher_only_use_psa

Make TLS 1.2 components work with PSA_CRYPTO_CONFIG set
diff --git a/.gitignore b/.gitignore
index 4f29d5b..12c775d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -67,3 +67,6 @@
 compile_commands.json
 # clangd index files
 /.cache/clangd/index/
+
+# VScode folder to store local debug files and configurations
+.vscode
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fb9e1c3..e476675 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -315,6 +315,37 @@
          ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/*.c
          ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/drivers/*.c)
     add_library(mbedtls_test OBJECT ${MBEDTLS_TEST_FILES})
+    if(GEN_FILES)
+        add_custom_command(
+            OUTPUT
+                ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/test_keys.h
+            WORKING_DIRECTORY
+                ${CMAKE_CURRENT_SOURCE_DIR}/tests
+            COMMAND
+                "${MBEDTLS_PYTHON_EXECUTABLE}"
+                "${CMAKE_CURRENT_SOURCE_DIR}/framework/scripts/generate_test_keys.py"
+                "--output"
+                "${CMAKE_CURRENT_SOURCE_DIR}/tests/src/test_keys.h"
+            DEPENDS
+                ${CMAKE_CURRENT_SOURCE_DIR}/framework/scripts/generate_test_keys.py
+        )
+        add_custom_target(test_keys_header DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/test_keys.h)
+        add_custom_command(
+            OUTPUT
+                ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/test_certs.h
+            WORKING_DIRECTORY
+                ${CMAKE_CURRENT_SOURCE_DIR}/tests
+            COMMAND
+                "${MBEDTLS_PYTHON_EXECUTABLE}"
+                "${CMAKE_CURRENT_SOURCE_DIR}/framework/scripts/generate_test_cert_macros.py"
+                "--output"
+                "${CMAKE_CURRENT_SOURCE_DIR}/tests/src/test_certs.h"
+            DEPENDS
+                ${CMAKE_CURRENT_SOURCE_DIR}/framework/scripts/generate_test_cert_macros.py
+        )
+        add_custom_target(test_certs_header DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/test_certs.h)
+        add_dependencies(mbedtls_test test_keys_header test_certs_header)
+    endif()
     target_include_directories(mbedtls_test
         PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests/include
         PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
diff --git a/ChangeLog b/ChangeLog
index eae2a19..b691a0f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -144,6 +144,7 @@
    * Fix a stack buffer overread (less than 256 bytes) when parsing a TLS 1.3
      ClientHello in a TLS 1.3 server supporting some PSK key exchange mode. A
      malicious client could cause information disclosure or a denial of service.
+     Fixes CVE-2024-30166.
    * Passing buffers that are stored in untrusted memory as arguments
      to PSA functions is now secure by default.
      The PSA core now protects against modification of inputs or exposure
diff --git a/ChangeLog.d/check-config.txt b/ChangeLog.d/check-config.txt
new file mode 100644
index 0000000..8570a11
--- /dev/null
+++ b/ChangeLog.d/check-config.txt
@@ -0,0 +1,9 @@
+Changes
+   * Warn if mbedtls/check_config.h is included manually, as this can
+     lead to spurious errors. Error if a *adjust*.h header is included
+     manually, as this can lead to silently inconsistent configurations,
+     potentially resulting in buffer overflows.
+     When migrating from Mbed TLS 2.x, if you had a custom config.h that
+     included check_config.h, remove this inclusion from the Mbed TLS 3.x
+     configuration file (renamed to mbedtls_config.h). This change was made
+     in Mbed TLS 3.0, but was not announced in a changelog entry at the time.
diff --git a/ChangeLog.d/fix-concurrently-loading-non-existent-keys.txt b/ChangeLog.d/fix-concurrently-loading-non-existent-keys.txt
new file mode 100644
index 0000000..8a406a1
--- /dev/null
+++ b/ChangeLog.d/fix-concurrently-loading-non-existent-keys.txt
@@ -0,0 +1,4 @@
+Bugfix
+   * Fix rare concurrent access bug where attempting to operate on a
+     non-existent key while concurrently creating a new key could potentially
+     corrupt the key store.
diff --git a/ChangeLog.d/fix-psa-cmac.txt b/ChangeLog.d/fix-psa-cmac.txt
new file mode 100644
index 0000000..e3c8aec
--- /dev/null
+++ b/ChangeLog.d/fix-psa-cmac.txt
@@ -0,0 +1,4 @@
+Bugfix
+   * Fix the build when MBEDTLS_PSA_CRYPTO_CONFIG is enabled and the built-in
+     CMAC is enabled, but no built-in unauthenticated cipher is enabled.
+     Fixes #9209.
diff --git a/ChangeLog.d/fix-redefination_warning_messages_for_GNU_SOURCE.txt b/ChangeLog.d/fix-redefination_warning_messages_for_GNU_SOURCE.txt
new file mode 100644
index 0000000..b5c2650
--- /dev/null
+++ b/ChangeLog.d/fix-redefination_warning_messages_for_GNU_SOURCE.txt
@@ -0,0 +1,5 @@
+Bugfix
+   * Fix issue of redefinition warning messages for _GNU_SOURCE in
+     entropy_poll.c and sha_256.c. There was a build warning during
+     building for linux platform.
+     Resolves #9026
diff --git a/ChangeLog.d/fix-secure-element-key-creation.txt b/ChangeLog.d/fix-secure-element-key-creation.txt
new file mode 100644
index 0000000..23a46c0
--- /dev/null
+++ b/ChangeLog.d/fix-secure-element-key-creation.txt
@@ -0,0 +1,5 @@
+Bugfix
+   * Fix error handling when creating a key in a dynamic secure element
+     (feature enabled by MBEDTLS_PSA_CRYPTO_SE_C). In a low memory condition,
+     the creation could return PSA_SUCCESS but using or destroying the key
+     would not work. Fixes #8537.
diff --git a/ChangeLog.d/fix_ubsan_mp_aead_gcm.txt b/ChangeLog.d/fix_ubsan_mp_aead_gcm.txt
new file mode 100644
index 0000000..e4726a4
--- /dev/null
+++ b/ChangeLog.d/fix_ubsan_mp_aead_gcm.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix undefined behaviour (incrementing a NULL pointer by zero length) when
+     passing in zero length additional data to multipart AEAD.
diff --git a/ChangeLog.d/pk-norsa-warning.txt b/ChangeLog.d/pk-norsa-warning.txt
new file mode 100644
index 0000000..d00aa8a
--- /dev/null
+++ b/ChangeLog.d/pk-norsa-warning.txt
@@ -0,0 +1,2 @@
+Bugfix
+   * Fix a compilation warning in pk.c when PSA is enabled and RSA is disabled.
diff --git a/configs/config-ccm-psk-dtls1_2.h b/configs/config-ccm-psk-dtls1_2.h
index 19e09d9..be785b7 100644
--- a/configs/config-ccm-psk-dtls1_2.h
+++ b/configs/config-ccm-psk-dtls1_2.h
@@ -23,19 +23,20 @@
  * See README.txt for usage instructions.
  */
 
+#define MBEDTLS_PSA_CRYPTO_CONFIG_FILE "../configs/crypto-config-ccm-psk-tls1_2.h"
+
+#define MBEDTLS_PSA_CRYPTO_C
+#define MBEDTLS_PSA_CRYPTO_CONFIG
+#define MBEDTLS_USE_PSA_CRYPTO
+
 /* System support */
 //#define MBEDTLS_HAVE_TIME /* Optionally used in Hello messages */
 /* Other MBEDTLS_HAVE_XXX flags irrelevant for this configuration */
 
 /* Mbed TLS modules */
-#define MBEDTLS_AES_C
-#define MBEDTLS_CCM_C
-#define MBEDTLS_CIPHER_C
 #define MBEDTLS_CTR_DRBG_C
 #define MBEDTLS_ENTROPY_C
-#define MBEDTLS_MD_C
 #define MBEDTLS_NET_C
-#define MBEDTLS_SHA256_C
 #define MBEDTLS_SSL_CLI_C
 #define MBEDTLS_SSL_COOKIE_C
 #define MBEDTLS_SSL_SRV_C
@@ -81,11 +82,6 @@
  */
 #define MBEDTLS_ENTROPY_MAX_SOURCES 2
 
-/* These defines are present so that the config modifying scripts can enable
- * them during tests/scripts/test-ref-configs.pl */
-//#define MBEDTLS_USE_PSA_CRYPTO
-//#define MBEDTLS_PSA_CRYPTO_C
-
 /* Error messages and TLS debugging traces
  * (huge code size increase, needed for tests/ssl-opt.sh) */
 //#define MBEDTLS_DEBUG_C
diff --git a/configs/config-ccm-psk-tls1_2.h b/configs/config-ccm-psk-tls1_2.h
index d49adfd..d8f4f9c 100644
--- a/configs/config-ccm-psk-tls1_2.h
+++ b/configs/config-ccm-psk-tls1_2.h
@@ -22,19 +22,20 @@
  * See README.txt for usage instructions.
  */
 
+#define MBEDTLS_PSA_CRYPTO_CONFIG_FILE "../configs/crypto-config-ccm-psk-tls1_2.h"
+
+#define MBEDTLS_PSA_CRYPTO_C
+#define MBEDTLS_PSA_CRYPTO_CONFIG
+#define MBEDTLS_USE_PSA_CRYPTO
+
 /* System support */
 //#define MBEDTLS_HAVE_TIME /* Optionally used in Hello messages */
 /* Other MBEDTLS_HAVE_XXX flags irrelevant for this configuration */
 
 /* Mbed TLS modules */
-#define MBEDTLS_AES_C
-#define MBEDTLS_CCM_C
-#define MBEDTLS_CIPHER_C
 #define MBEDTLS_CTR_DRBG_C
 #define MBEDTLS_ENTROPY_C
-#define MBEDTLS_MD_C
 #define MBEDTLS_NET_C
-#define MBEDTLS_SHA256_C
 #define MBEDTLS_SSL_CLI_C
 #define MBEDTLS_SSL_SRV_C
 #define MBEDTLS_SSL_TLS_C
@@ -72,11 +73,6 @@
  */
 #define MBEDTLS_ENTROPY_MAX_SOURCES 2
 
-/* These defines are present so that the config modifying scripts can enable
- * them during tests/scripts/test-ref-configs.pl */
-//#define MBEDTLS_USE_PSA_CRYPTO
-//#define MBEDTLS_PSA_CRYPTO_C
-
 /* Error messages and TLS debugging traces
  * (huge code size increase, needed for tests/ssl-opt.sh) */
 //#define MBEDTLS_DEBUG_C
diff --git a/configs/config-suite-b.h b/configs/config-suite-b.h
index 9bba6e6..cdea16e 100644
--- a/configs/config-suite-b.h
+++ b/configs/config-suite-b.h
@@ -21,36 +21,29 @@
  * See README.txt for usage instructions.
  */
 
+#define MBEDTLS_PSA_CRYPTO_CONFIG_FILE "../configs/crypto-config-suite-b.h"
+
+#define MBEDTLS_PSA_CRYPTO_C
+#define MBEDTLS_PSA_CRYPTO_CONFIG
+#define MBEDTLS_USE_PSA_CRYPTO
+
 /* System support */
 #define MBEDTLS_HAVE_ASM
 #define MBEDTLS_HAVE_TIME
 
 /* Mbed TLS feature support */
-#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
 #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 #define MBEDTLS_SSL_PROTO_TLS1_2
 
 /* Mbed TLS modules */
-#define MBEDTLS_AES_C
 #define MBEDTLS_ASN1_PARSE_C
 #define MBEDTLS_ASN1_WRITE_C
-#define MBEDTLS_BIGNUM_C
-#define MBEDTLS_CIPHER_C
 #define MBEDTLS_CTR_DRBG_C
-#define MBEDTLS_ECDH_C
-#define MBEDTLS_ECDSA_C
-#define MBEDTLS_ECP_C
 #define MBEDTLS_ENTROPY_C
-#define MBEDTLS_GCM_C
-#define MBEDTLS_MD_C
 #define MBEDTLS_NET_C
 #define MBEDTLS_OID_C
 #define MBEDTLS_PK_C
 #define MBEDTLS_PK_PARSE_C
-#define MBEDTLS_SHA256_C
-#define MBEDTLS_SHA384_C
-#define MBEDTLS_SHA512_C
 #define MBEDTLS_SSL_CLI_C
 #define MBEDTLS_SSL_SRV_C
 #define MBEDTLS_SSL_TLS_C
@@ -95,11 +88,6 @@
 #define MBEDTLS_SSL_IN_CONTENT_LEN             1024
 #define MBEDTLS_SSL_OUT_CONTENT_LEN             1024
 
-/* These defines are present so that the config modifying scripts can enable
- * them during tests/scripts/test-ref-configs.pl */
-//#define MBEDTLS_USE_PSA_CRYPTO
-//#define MBEDTLS_PSA_CRYPTO_C
-
 /* Error messages and TLS debugging traces
  * (huge code size increase, needed for tests/ssl-opt.sh) */
 //#define MBEDTLS_DEBUG_C
diff --git a/configs/config-symmetric-only.h b/configs/config-symmetric-only.h
index 512dd76..13e4d26 100644
--- a/configs/config-symmetric-only.h
+++ b/configs/config-symmetric-only.h
@@ -8,70 +8,43 @@
  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
+#define MBEDTLS_PSA_CRYPTO_CONFIG_FILE "../configs/crypto-config-symmetric-only.h"
+
+#define MBEDTLS_PSA_CRYPTO_C
+#define MBEDTLS_PSA_CRYPTO_CONFIG
+#define MBEDTLS_USE_PSA_CRYPTO
+
 /* System support */
 //#define MBEDTLS_HAVE_ASM
 #define MBEDTLS_HAVE_TIME
 #define MBEDTLS_HAVE_TIME_DATE
 
 /* Mbed TLS feature support */
-#define MBEDTLS_CIPHER_MODE_CBC
-#define MBEDTLS_CIPHER_MODE_CFB
-#define MBEDTLS_CIPHER_MODE_CTR
-#define MBEDTLS_CIPHER_MODE_OFB
-#define MBEDTLS_CIPHER_MODE_XTS
-#define MBEDTLS_CIPHER_PADDING_PKCS7
-#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS
-#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
-#define MBEDTLS_CIPHER_PADDING_ZEROS
 #define MBEDTLS_ERROR_STRERROR_DUMMY
 #define MBEDTLS_FS_IO
 #define MBEDTLS_ENTROPY_NV_SEED
 #define MBEDTLS_SELF_TEST
-#define MBEDTLS_USE_PSA_CRYPTO
 #define MBEDTLS_VERSION_FEATURES
 
 /* Mbed TLS modules */
-#define MBEDTLS_AES_C
 #define MBEDTLS_ASN1_PARSE_C
 #define MBEDTLS_ASN1_WRITE_C
 #define MBEDTLS_BASE64_C
-#define MBEDTLS_CAMELLIA_C
-#define MBEDTLS_ARIA_C
-#define MBEDTLS_CCM_C
-#define MBEDTLS_CHACHA20_C
-#define MBEDTLS_CHACHAPOLY_C
-#define MBEDTLS_CIPHER_C
-#define MBEDTLS_CMAC_C
 #define MBEDTLS_CTR_DRBG_C
-#define MBEDTLS_DES_C
 #define MBEDTLS_ENTROPY_C
 #define MBEDTLS_ERROR_C
-#define MBEDTLS_GCM_C
-#define MBEDTLS_HKDF_C
 #define MBEDTLS_HMAC_DRBG_C
 #define MBEDTLS_NIST_KW_C
-#define MBEDTLS_MD_C
-#define MBEDTLS_MD5_C
 #define MBEDTLS_OID_C
 #define MBEDTLS_PEM_PARSE_C
 #define MBEDTLS_PEM_WRITE_C
 #define MBEDTLS_PKCS5_C
 #define MBEDTLS_PKCS12_C
 #define MBEDTLS_PLATFORM_C
-#define MBEDTLS_POLY1305_C
-#define MBEDTLS_PSA_CRYPTO_C
 #define MBEDTLS_PSA_CRYPTO_SE_C
 #define MBEDTLS_PSA_CRYPTO_STORAGE_C
 #define MBEDTLS_PSA_ITS_FILE_C
-#define MBEDTLS_RIPEMD160_C
-#define MBEDTLS_SHA1_C
-/* The library does not currently support enabling SHA-224 without SHA-256.
- * A future version of the library will have this option disabled
- * by default. */
-#define MBEDTLS_SHA224_C
-#define MBEDTLS_SHA256_C
-#define MBEDTLS_SHA384_C
-#define MBEDTLS_SHA512_C
+
 //#define MBEDTLS_THREADING_C
 #define MBEDTLS_TIMING_C
 #define MBEDTLS_VERSION_C
diff --git a/configs/config-thread.h b/configs/config-thread.h
index 2f81f90..160aded 100644
--- a/configs/config-thread.h
+++ b/configs/config-thread.h
@@ -17,15 +17,21 @@
  * - no X.509
  * - support for experimental EC J-PAKE key exchange
  *
+ * To be used in conjunction with configs/crypto-config-thread.h.
  * See README.txt for usage instructions.
  */
 
+#define MBEDTLS_PSA_CRYPTO_CONFIG_FILE "../configs/crypto-config-thread.h"
+
+#define MBEDTLS_PSA_CRYPTO_C
+#define MBEDTLS_PSA_CRYPTO_CONFIG
+#define MBEDTLS_USE_PSA_CRYPTO
+
 /* System support */
 #define MBEDTLS_HAVE_ASM
 
 /* Mbed TLS feature support */
 #define MBEDTLS_AES_ROM_TABLES
-#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
 #define MBEDTLS_ECP_NIST_OPTIM
 #define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
 #define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
@@ -35,23 +41,15 @@
 #define MBEDTLS_SSL_DTLS_HELLO_VERIFY
 
 /* Mbed TLS modules */
-#define MBEDTLS_AES_C
 #define MBEDTLS_ASN1_PARSE_C
 #define MBEDTLS_ASN1_WRITE_C
-#define MBEDTLS_BIGNUM_C
-#define MBEDTLS_CCM_C
-#define MBEDTLS_CIPHER_C
 #define MBEDTLS_CTR_DRBG_C
-#define MBEDTLS_CMAC_C
-#define MBEDTLS_ECJPAKE_C
-#define MBEDTLS_ECP_C
 #define MBEDTLS_ENTROPY_C
 #define MBEDTLS_HMAC_DRBG_C
 #define MBEDTLS_MD_C
 #define MBEDTLS_OID_C
 #define MBEDTLS_PK_C
 #define MBEDTLS_PK_PARSE_C
-#define MBEDTLS_SHA256_C
 #define MBEDTLS_SSL_COOKIE_C
 #define MBEDTLS_SSL_CLI_C
 #define MBEDTLS_SSL_SRV_C
@@ -69,8 +67,3 @@
 
 /* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */
 #define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8
-
-/* These defines are present so that the config modifying scripts can enable
- * them during tests/scripts/test-ref-configs.pl */
-//#define MBEDTLS_USE_PSA_CRYPTO
-//#define MBEDTLS_PSA_CRYPTO_C
diff --git a/configs/crypto-config-ccm-aes-sha256.h b/configs/crypto-config-ccm-aes-sha256.h
index 7f8d587..68a9c0a 100644
--- a/configs/crypto-config-ccm-aes-sha256.h
+++ b/configs/crypto-config-ccm-aes-sha256.h
@@ -2,7 +2,7 @@
  * \file configs/crypto-config-ccm-aes-sha256.h
  *
  * \brief PSA crypto configuration with only symmetric cryptography: CCM-AES,
- *        SHA-256, HMAC and key derivation
+ *        SHA-256 and key derivation (uses HMAC).
  */
 /*
  *  Copyright The Mbed TLS Contributors
@@ -13,12 +13,10 @@
 #define PSA_CRYPTO_CONFIG_H
 
 #define PSA_WANT_ALG_CCM 1
-#define PSA_WANT_ALG_HMAC 1
 #define PSA_WANT_ALG_SHA_256 1
 #define PSA_WANT_ALG_TLS12_PRF 1
 #define PSA_WANT_ALG_TLS12_PSK_TO_MS 1
 #define PSA_WANT_KEY_TYPE_DERIVE 1
-#define PSA_WANT_KEY_TYPE_HMAC 1
 #define PSA_WANT_KEY_TYPE_AES 1
 #define PSA_WANT_KEY_TYPE_RAW_DATA 1
 
diff --git a/configs/crypto-config-ccm-psk-tls1_2.h b/configs/crypto-config-ccm-psk-tls1_2.h
new file mode 100644
index 0000000..f4928e2
--- /dev/null
+++ b/configs/crypto-config-ccm-psk-tls1_2.h
@@ -0,0 +1,25 @@
+/**
+ * \file crypto-config-ccm-psk-tls1_2.h
+ *
+ * \brief Minimal crypto configuration for TLS 1.2 with
+ * PSK and AES-CCM ciphersuites
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+/**
+ * To be used in conjunction with configs/config-ccm-psk-tls1_2.h
+ * or configs/config-ccm-psk-dtls1_2.h. */
+
+#ifndef PSA_CRYPTO_CONFIG_H
+#define PSA_CRYPTO_CONFIG_H
+
+#define PSA_WANT_ALG_CCM                        1
+#define PSA_WANT_ALG_SHA_256                    1
+#define PSA_WANT_ALG_TLS12_PRF                  1
+#define PSA_WANT_ALG_TLS12_PSK_TO_MS            1
+
+#define PSA_WANT_KEY_TYPE_AES                   1
+#endif /* PSA_CRYPTO_CONFIG_H */
diff --git a/configs/crypto-config-suite-b.h b/configs/crypto-config-suite-b.h
new file mode 100644
index 0000000..ec20919
--- /dev/null
+++ b/configs/crypto-config-suite-b.h
@@ -0,0 +1,41 @@
+/**
+ * \file crypto-config-symmetric-only.h
+ *
+ * \brief \brief Minimal crypto configuration for
+ * TLS NSA Suite B Profile (RFC 6460).
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+/**
+ * Minimal crypto configuration for TLS NSA Suite B Profile (RFC 6460)
+ *
+ * Distinguishing features:
+ * - no RSA or classic DH, fully based on ECC
+ * - optimized for low RAM usage
+ *
+ * Possible improvements:
+ * - if 128-bit security is enough, disable secp384r1 and SHA-512
+ *
+ * To be used in conjunction with configs/config-suite-b.h. */
+
+#ifndef PSA_CRYPTO_CONFIG_H
+#define PSA_CRYPTO_CONFIG_H
+
+#define PSA_WANT_ALG_ECDH                        1
+#define PSA_WANT_ALG_ECDSA                       1
+#define PSA_WANT_ALG_GCM                         1
+#define PSA_WANT_ALG_SHA_256                     1
+#define PSA_WANT_ALG_SHA_384                     1
+#define PSA_WANT_ALG_SHA_512                     1
+#define PSA_WANT_ECC_SECP_R1_256                 1
+#define PSA_WANT_ECC_SECP_R1_384                 1
+#define PSA_WANT_ALG_TLS12_PRF                   1
+
+#define PSA_WANT_KEY_TYPE_AES                    1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC     1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT    1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE  1
+#endif /* PSA_CRYPTO_CONFIG_H */
diff --git a/configs/crypto-config-symmetric-only.h b/configs/crypto-config-symmetric-only.h
new file mode 100644
index 0000000..5d6bf85
--- /dev/null
+++ b/configs/crypto-config-symmetric-only.h
@@ -0,0 +1,58 @@
+/**
+ * \file crypto-config-symmetric-only.h
+ *
+ * \brief Crypto configuration without any asymmetric cryptography.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+/**
+ * To be used in conjunction with configs/config-symmetric-only.h. */
+
+#ifndef PSA_CRYPTO_CONFIG_H
+#define PSA_CRYPTO_CONFIG_H
+
+#define PSA_WANT_ALG_CBC_NO_PADDING             1
+#define PSA_WANT_ALG_CBC_PKCS7                  1
+#define PSA_WANT_ALG_CCM                        1
+#define PSA_WANT_ALG_CCM_STAR_NO_TAG            1
+#define PSA_WANT_ALG_CFB                        1
+#define PSA_WANT_ALG_CHACHA20_POLY1305          1
+#define PSA_WANT_ALG_CMAC                       1
+#define PSA_WANT_ALG_CTR                        1
+#define PSA_WANT_ALG_ECB_NO_PADDING             1
+#define PSA_WANT_ALG_GCM                        1
+#define PSA_WANT_ALG_HKDF                       1
+#define PSA_WANT_ALG_HKDF_EXTRACT               1
+#define PSA_WANT_ALG_HKDF_EXPAND                1
+#define PSA_WANT_ALG_HMAC                       1
+#define PSA_WANT_ALG_MD5                        1
+#define PSA_WANT_ALG_OFB                        1
+#define PSA_WANT_ALG_RIPEMD160                  1
+#define PSA_WANT_ALG_SHA_1                      1
+#define PSA_WANT_ALG_STREAM_CIPHER              1
+#define PSA_WANT_ALG_SHA_224                    1
+#define PSA_WANT_ALG_SHA_256                    1
+#define PSA_WANT_ALG_SHA_384                    1
+#define PSA_WANT_ALG_SHA_512                    1
+#define PSA_WANT_ALG_SHA3_224                   1
+#define PSA_WANT_ALG_SHA3_256                   1
+#define PSA_WANT_ALG_SHA3_384                   1
+#define PSA_WANT_ALG_SHA3_512                   1
+#define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS       1
+#define PSA_WANT_ALG_TLS12_PRF                  1
+#define PSA_WANT_ALG_TLS12_PSK_TO_MS            1
+
+/* XTS is not yet supported via the PSA API in Mbed TLS. */
+//#define PSA_WANT_ALG_XTS                        1
+
+#define PSA_WANT_KEY_TYPE_AES                   1
+#define PSA_WANT_KEY_TYPE_ARIA                  1
+#define PSA_WANT_KEY_TYPE_CAMELLIA              1
+#define PSA_WANT_KEY_TYPE_CHACHA20              1
+#define PSA_WANT_KEY_TYPE_DES                   1
+#define PSA_WANT_KEY_TYPE_HMAC                  1
+
+#endif /* PSA_CRYPTO_CONFIG_H */
diff --git a/configs/crypto-config-thread.h b/configs/crypto-config-thread.h
new file mode 100644
index 0000000..3c5fe24
--- /dev/null
+++ b/configs/crypto-config-thread.h
@@ -0,0 +1,47 @@
+/**
+ * \file crypto-config-thread.h
+ *
+ * \brief Minimal crypto configuration for using TLS as part of Thread
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+/**
+ * Minimal crypto configuration for using TLS as part of Thread
+ * http://threadgroup.org/
+ *
+ * Distinguishing features:
+ * - no RSA or classic DH, fully based on ECC
+ * - no X.509
+ * - support for experimental EC J-PAKE key exchange
+ * - support for PBKDF2-AES-CMAC-PRF-128 password-hashing or key-stretching
+ *   algorithm.
+ *
+ * To be used in conjunction with configs/config-thread.h.
+ * See README.txt for usage instructions.
+ */
+
+#ifndef PSA_CRYPTO_CONFIG_H
+#define PSA_CRYPTO_CONFIG_H
+
+#define PSA_WANT_ALG_CCM                        1
+#define PSA_WANT_ALG_ECB_NO_PADDING             1
+#define PSA_WANT_ALG_HMAC                       1
+#define PSA_WANT_ALG_JPAKE                      1
+#define PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128    1
+#define PSA_WANT_ALG_SHA_256                    1
+#define PSA_WANT_ALG_TLS12_PRF                  1
+#define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS       1
+#define PSA_WANT_ECC_SECP_R1_256                1
+
+#define PSA_WANT_KEY_TYPE_AES                   1
+#define PSA_WANT_KEY_TYPE_DERIVE                1
+#define PSA_WANT_KEY_TYPE_HMAC                  1
+#define PSA_WANT_KEY_TYPE_RAW_DATA              1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC    1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT   1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1
+
+#endif /* PSA_CRYPTO_CONFIG_H */
diff --git a/docs/architecture/psa-crypto-implementation-structure.md b/docs/architecture/psa-crypto-implementation-structure.md
index d7e4f9c..0954602 100644
--- a/docs/architecture/psa-crypto-implementation-structure.md
+++ b/docs/architecture/psa-crypto-implementation-structure.md
@@ -86,7 +86,7 @@
 * [ ] `tests/suites/test_suite_psa_crypto_metadata.data` — [New functions and macros](#new-functions-and-macros)
 * (If adding `PSA_IS_xxx`) `tests/suites/test_suite_psa_crypto_metadata.function` — [New functions and macros](#new-functions-and-macros)
 * [ ] `tests/suites/test_suite_psa_crypto*.data`, `tests/suites/test_suite_psa_crypto*.function` — [Unit tests](#unit-tests)
-* [ ] `scripts/mbedtls_dev/crypto_knowledge.py`, `scripts/mbedtls_dev/asymmetric_key_data.py` — [Unit tests](#unit-tests)
+* [ ] `framework/scripts/mbedtls_framework/crypto_knowledge.py`, `framework/scripts/mbedtls_framework/asymmetric_key_data.py` — [Unit tests](#unit-tests)
 * [ ] `ChangeLog.d/*.txt` — changelog entry
 
 Summary of files to modify when adding new API functions:
@@ -153,7 +153,7 @@
 
 ### Unit tests
 
-A number of unit tests are automatically generated by `tests/scripts/generate_psa_tests.py` based on the algorithms and key types declared in `include/psa/crypto_values.h` and `include/psa/crypto_extra.h`:
+A number of unit tests are automatically generated by `framework/scripts/generate_psa_tests.py` based on the algorithms and key types declared in `include/psa/crypto_values.h` and `include/psa/crypto_extra.h`:
 
 * Attempt to create a key with a key type that is not supported.
 * Attempt to perform an operation with a combination of key type and algorithm that is not valid or not supported.
@@ -161,8 +161,8 @@
 
 When adding a new key type or algorithm:
 
-* `scripts/mbedtls_dev/crypto_knowledge.py` contains knowledge about the compatibility of key types, key sizes and algorithms.
-* `scripts/mbedtls_dev/asymmetric_key_data.py` contains valid key data for asymmetric key types.
+* `framework/scripts/mbedtls_framework/crypto_knowledge.py` contains knowledge about the compatibility of key types, key sizes and algorithms.
+* `framework/scripts/mbedtls_framework/asymmetric_key_data.py` contains valid key data for asymmetric key types.
 
 Other things need to be tested manually, either in `tests/suites/test_sutie_psa_crypto.data` or in another file. For example (this is not an exhaustive list):
 
diff --git a/docs/architecture/psa-shared-memory.md b/docs/architecture/psa-shared-memory.md
index ef3a6b0..283ffc6 100644
--- a/docs/architecture/psa-shared-memory.md
+++ b/docs/architecture/psa-shared-memory.md
@@ -663,7 +663,7 @@
 
 There now exists a more generic mechanism for making exactly this kind of transformation - the PSA test wrappers, which exist in the files `tests/include/test/psa_test_wrappers.h` and `tests/src/psa_test_wrappers.c`. These are wrappers around all PSA functions that allow testing code to be inserted at the start and end of a PSA function call.
 
-The test wrappers are generated by a script, although they are not automatically generated as part of the build process. Instead, they are checked into source control and must be manually updated when functions change by running `tests/scripts/generate_psa_wrappers.py`.
+The test wrappers are generated by a script, although they are not automatically generated as part of the build process. Instead, they are checked into source control and must be manually updated when functions change by running `framework/scripts/generate_psa_wrappers.py`.
 
 Poisoning code is added to these test wrappers where relevant in order to pre-poison and post-unpoison the parameters to the functions.
 
diff --git a/docs/driver-only-builds.md b/docs/driver-only-builds.md
index 4095d8e..5d950b0 100644
--- a/docs/driver-only-builds.md
+++ b/docs/driver-only-builds.md
@@ -277,6 +277,11 @@
 `[PSA_WANT|MBEDTLS_PSA_ACCEL]_ALG_FFDH` allow builds accelerating FFDH and
 removing builtin support (i.e. `MBEDTLS_DHM_C`).
 
+Note that the PSA API only supports FFDH with RFC 7919 groups, whereas the
+Mbed TLS legacy API supports custom groups. As a consequence, the TLS layer
+of Mbed TLS only supports DHE cipher suites if built-in FFDH
+(`MBEDTLS_DHM_C`) is present, even when `MBEDTLS_USE_PSA_CRYPTO` is enabled.
+
 RSA
 ---
 
diff --git a/framework b/framework
index 750634d..623c1b4 160000
--- a/framework
+++ b/framework
@@ -1 +1 @@
-Subproject commit 750634d3a51eb9d61b59fd5d801546927c946588
+Subproject commit 623c1b4532e8de64a5d82ea84a7496e64c370d15
diff --git a/include/mbedtls/build_info.h b/include/mbedtls/build_info.h
index eab167f..cf38f90 100644
--- a/include/mbedtls/build_info.h
+++ b/include/mbedtls/build_info.h
@@ -101,6 +101,13 @@
 #define inline __inline
 #endif
 
+#if defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Something went wrong: MBEDTLS_CONFIG_FILES_READ defined before reading the config files!"
+#endif
+#if defined(MBEDTLS_CONFIG_IS_FINALIZED)
+#error "Something went wrong: MBEDTLS_CONFIG_IS_FINALIZED defined before reading the config files!"
+#endif
+
 /* X.509, TLS and non-PSA crypto configuration */
 #if !defined(MBEDTLS_CONFIG_FILE)
 #include "mbedtls/mbedtls_config.h"
@@ -135,6 +142,12 @@
 #endif
 #endif /* defined(MBEDTLS_PSA_CRYPTO_CONFIG) */
 
+/* Indicate that all configuration files have been read.
+ * It is now time to adjust the configuration (follow through on dependencies,
+ * make PSA and legacy crypto consistent, etc.).
+ */
+#define MBEDTLS_CONFIG_FILES_READ
+
 /* Auto-enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY if
  * MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH and MBEDTLS_CTR_DRBG_C defined
  * to ensure a 128-bit key size in CTR_DRBG.
@@ -169,8 +182,13 @@
 
 #include "mbedtls/config_adjust_ssl.h"
 
-/* Make sure all configuration symbols are set before including check_config.h,
- * even the ones that are calculated programmatically. */
+/* Indicate that all configuration symbols are set,
+ * even the ones that are calculated programmatically.
+ * It is now safe to query the configuration (to check it, to size buffers,
+ * etc.).
+ */
+#define MBEDTLS_CONFIG_IS_FINALIZED
+
 #include "mbedtls/check_config.h"
 
 #endif /* MBEDTLS_BUILD_INFO_H */
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index b3c038d..67a05f8 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -2,6 +2,13 @@
  * \file check_config.h
  *
  * \brief Consistency checks for configuration options
+ *
+ * This is an internal header. Do not include it directly.
+ *
+ * This header is included automatically by all public Mbed TLS headers
+ * (via mbedtls/build_info.h). Do not include it directly in a configuration
+ * file such as mbedtls/mbedtls_config.h or #MBEDTLS_USER_CONFIG_FILE!
+ * It would run at the wrong time due to missing derived symbols.
  */
 /*
  *  Copyright The Mbed TLS Contributors
@@ -12,6 +19,13 @@
 #define MBEDTLS_CHECK_CONFIG_H
 
 /* *INDENT-OFF* */
+
+#if !defined(MBEDTLS_CONFIG_IS_FINALIZED)
+#warning "Do not include mbedtls/check_config.h manually! " \
+         "This may cause spurious errors. " \
+         "It is included automatically at the right point since Mbed TLS 3.0."
+#endif /* !MBEDTLS_CONFIG_IS_FINALIZED */
+
 /*
  * We assume CHAR_BIT is 8 in many places. In practice, this is true on our
  * target platforms, so not an issue, but let's just be extra sure.
diff --git a/include/mbedtls/config_adjust_legacy_crypto.h b/include/mbedtls/config_adjust_legacy_crypto.h
index e477c07..7dafbae 100644
--- a/include/mbedtls/config_adjust_legacy_crypto.h
+++ b/include/mbedtls/config_adjust_legacy_crypto.h
@@ -2,6 +2,8 @@
  * \file mbedtls/config_adjust_legacy_crypto.h
  * \brief Adjust legacy configuration configuration
  *
+ * This is an internal header. Do not include it directly.
+ *
  * Automatically enable certain dependencies. Generally, MBEDLTS_xxx
  * configurations need to be explicitly enabled by the user: enabling
  * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a
@@ -22,6 +24,14 @@
 #ifndef MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H
 #define MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H
 
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
 /* Ideally, we'd set those as defaults in mbedtls_config.h, but
  * putting an #ifdef _WIN32 in mbedtls_config.h would confuse config.py.
  *
@@ -48,7 +58,8 @@
     defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \
     defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
     defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG))
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC))
 #define MBEDTLS_CIPHER_C
 #endif
 
diff --git a/include/mbedtls/config_adjust_legacy_from_psa.h b/include/mbedtls/config_adjust_legacy_from_psa.h
index 0091e24..04bdae6 100644
--- a/include/mbedtls/config_adjust_legacy_from_psa.h
+++ b/include/mbedtls/config_adjust_legacy_from_psa.h
@@ -2,6 +2,8 @@
  * \file mbedtls/config_adjust_legacy_from_psa.h
  * \brief Adjust PSA configuration: activate legacy implementations
  *
+ * This is an internal header. Do not include it directly.
+ *
  * When MBEDTLS_PSA_CRYPTO_CONFIG is enabled, activate legacy implementations
  * of cryptographic mechanisms as needed to fulfill the needs of the PSA
  * configuration. Generally speaking, we activate a legacy mechanism if
@@ -16,6 +18,14 @@
 #ifndef MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H
 #define MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H
 
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
 /* Define appropriate ACCEL macros for the p256-m driver.
  * In the future, those should be generated from the drivers JSON description.
  */
@@ -498,7 +508,6 @@
  * The PSA implementation has its own implementation of HKDF, separate from
  * hkdf.c. No need to enable MBEDTLS_HKDF_C here.
  */
-#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
 #define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1
 #endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF */
 #endif /* PSA_WANT_ALG_HKDF */
@@ -509,7 +518,6 @@
  * The PSA implementation has its own implementation of HKDF, separate from
  * hkdf.c. No need to enable MBEDTLS_HKDF_C here.
  */
-#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
 #define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT 1
 #endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT */
 #endif /* PSA_WANT_ALG_HKDF_EXTRACT */
@@ -520,7 +528,6 @@
  * The PSA implementation has its own implementation of HKDF, separate from
  * hkdf.c. No need to enable MBEDTLS_HKDF_C here.
  */
-#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
 #define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND 1
 #endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND */
 #endif /* PSA_WANT_ALG_HKDF_EXPAND */
@@ -630,9 +637,6 @@
 #if !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_HMAC)
 #define MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC 1
 #define PSA_HAVE_SOFT_PBKDF2_HMAC 1
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_HMAC)
-#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_HMAC */
 #endif /* !MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
 #endif /* PSA_WANT_ALG_PBKDF2_HMAC */
 
diff --git a/include/mbedtls/config_adjust_psa_from_legacy.h b/include/mbedtls/config_adjust_psa_from_legacy.h
index 3456615..14ca146 100644
--- a/include/mbedtls/config_adjust_psa_from_legacy.h
+++ b/include/mbedtls/config_adjust_psa_from_legacy.h
@@ -2,6 +2,8 @@
  * \file mbedtls/config_adjust_psa_from_legacy.h
  * \brief Adjust PSA configuration: construct PSA configuration from legacy
  *
+ * This is an internal header. Do not include it directly.
+ *
  * When MBEDTLS_PSA_CRYPTO_CONFIG is disabled, we automatically enable
  * cryptographic mechanisms through the PSA interface when the corresponding
  * legacy mechanism is enabled. In many cases, this just enables the PSA
@@ -18,6 +20,14 @@
 #ifndef MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H
 #define MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H
 
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
 /*
  * Ensure PSA_WANT_* defines are setup properly if MBEDTLS_PSA_CRYPTO_CONFIG
  * is not defined
diff --git a/include/mbedtls/config_adjust_psa_superset_legacy.h b/include/mbedtls/config_adjust_psa_superset_legacy.h
index 3a55c3f..ef65cce 100644
--- a/include/mbedtls/config_adjust_psa_superset_legacy.h
+++ b/include/mbedtls/config_adjust_psa_superset_legacy.h
@@ -2,6 +2,8 @@
  * \file mbedtls/config_adjust_psa_superset_legacy.h
  * \brief Adjust PSA configuration: automatic enablement from legacy
  *
+ * This is an internal header. Do not include it directly.
+ *
  * To simplify some edge cases, we automatically enable certain cryptographic
  * mechanisms in the PSA API if they are enabled in the legacy API. The general
  * idea is that if legacy module M uses mechanism A internally, and A has
@@ -17,6 +19,14 @@
 #ifndef MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H
 #define MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H
 
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
 /****************************************************************/
 /* Hashes that are built in are also enabled in PSA.
  * This simplifies dependency declarations especially
diff --git a/include/mbedtls/config_adjust_ssl.h b/include/mbedtls/config_adjust_ssl.h
index 39c7b3b..309524a 100644
--- a/include/mbedtls/config_adjust_ssl.h
+++ b/include/mbedtls/config_adjust_ssl.h
@@ -2,6 +2,8 @@
  * \file mbedtls/config_adjust_ssl.h
  * \brief Adjust TLS configuration
  *
+ * This is an internal header. Do not include it directly.
+ *
  * Automatically enable certain dependencies. Generally, MBEDLTS_xxx
  * configurations need to be explicitly enabled by the user: enabling
  * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a
@@ -22,6 +24,14 @@
 #ifndef MBEDTLS_CONFIG_ADJUST_SSL_H
 #define MBEDTLS_CONFIG_ADJUST_SSL_H
 
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
 /* The following blocks make it easier to disable all of TLS,
  * or of TLS 1.2 or 1.3 or DTLS, without having to manually disable all
  * key exchanges, options and extensions related to them. */
diff --git a/include/mbedtls/config_adjust_x509.h b/include/mbedtls/config_adjust_x509.h
index 346c8ae..c063251 100644
--- a/include/mbedtls/config_adjust_x509.h
+++ b/include/mbedtls/config_adjust_x509.h
@@ -2,6 +2,8 @@
  * \file mbedtls/config_adjust_x509.h
  * \brief Adjust X.509 configuration
  *
+ * This is an internal header. Do not include it directly.
+ *
  * Automatically enable certain dependencies. Generally, MBEDLTS_xxx
  * configurations need to be explicitly enabled by the user: enabling
  * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a
@@ -22,4 +24,12 @@
 #ifndef MBEDTLS_CONFIG_ADJUST_X509_H
 #define MBEDTLS_CONFIG_ADJUST_X509_H
 
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
 #endif /* MBEDTLS_CONFIG_ADJUST_X509_H */
diff --git a/include/mbedtls/config_psa.h b/include/mbedtls/config_psa.h
index 17da61b..de961ec 100644
--- a/include/mbedtls/config_psa.h
+++ b/include/mbedtls/config_psa.h
@@ -22,6 +22,8 @@
 
 #include "psa/crypto_adjust_config_synonyms.h"
 
+#include "psa/crypto_adjust_config_dependencies.h"
+
 #include "mbedtls/config_adjust_psa_superset_legacy.h"
 
 #if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 7083bd9..f9db4dd 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -871,7 +871,7 @@
  *                          such that #PSA_ALG_IS_HASH(\p alg) is true).
  * \param[in] input         Buffer containing the message to hash.
  * \param input_length      Size of the \p input buffer in bytes.
- * \param[out] hash         Buffer containing the expected hash value.
+ * \param[in] hash          Buffer containing the expected hash value.
  * \param hash_length       Size of the \p hash buffer in bytes.
  *
  * \retval #PSA_SUCCESS
@@ -1224,7 +1224,7 @@
  *                          such that #PSA_ALG_IS_MAC(\p alg) is true).
  * \param[in] input         Buffer containing the input message.
  * \param input_length      Size of the \p input buffer in bytes.
- * \param[out] mac          Buffer containing the expected MAC value.
+ * \param[in] mac           Buffer containing the expected MAC value.
  * \param mac_length        Size of the \p mac buffer in bytes.
  *
  * \retval #PSA_SUCCESS
@@ -2910,7 +2910,7 @@
  *                              \p key.
  * \param[in]  input            The message whose signature is to be verified.
  * \param[in]  input_length     Size of the \p input buffer in bytes.
- * \param[out] signature        Buffer containing the signature to verify.
+ * \param[in] signature         Buffer containing the signature to verify.
  * \param[in]  signature_length Size of the \p signature buffer in bytes.
  *
  * \retval #PSA_SUCCESS \emptydescription
diff --git a/include/psa/crypto_adjust_auto_enabled.h b/include/psa/crypto_adjust_auto_enabled.h
index 63fb29e..3a2af15 100644
--- a/include/psa/crypto_adjust_auto_enabled.h
+++ b/include/psa/crypto_adjust_auto_enabled.h
@@ -2,6 +2,8 @@
  * \file psa/crypto_adjust_auto_enabled.h
  * \brief Adjust PSA configuration: enable always-on features
  *
+ * This is an internal header. Do not include it directly.
+ *
  * Always enable certain features which require a negligible amount of code
  * to implement, to avoid some edge cases in the configuration combinatorics.
  */
@@ -13,6 +15,14 @@
 #ifndef PSA_CRYPTO_ADJUST_AUTO_ENABLED_H
 #define PSA_CRYPTO_ADJUST_AUTO_ENABLED_H
 
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include psa/crypto_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
 #define PSA_WANT_KEY_TYPE_DERIVE 1
 #define PSA_WANT_KEY_TYPE_PASSWORD 1
 #define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1
diff --git a/include/psa/crypto_adjust_config_dependencies.h b/include/psa/crypto_adjust_config_dependencies.h
new file mode 100644
index 0000000..92e9c4d
--- /dev/null
+++ b/include/psa/crypto_adjust_config_dependencies.h
@@ -0,0 +1,51 @@
+/**
+ * \file psa/crypto_adjust_config_dependencies.h
+ * \brief Adjust PSA configuration by resolving some dependencies.
+ *
+ * This is an internal header. Do not include it directly.
+ *
+ * See docs/proposed/psa-conditional-inclusion-c.md.
+ * If the Mbed TLS implementation of a cryptographic mechanism A depends on a
+ * cryptographic mechanism B then if the cryptographic mechanism A is enabled
+ * and not accelerated enable B. Note that if A is enabled and accelerated, it
+ * is not necessary to enable B for A support.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_ADJUST_CONFIG_DEPENDENCIES_H
+#define PSA_CRYPTO_ADJUST_CONFIG_DEPENDENCIES_H
+
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include psa/crypto_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
+#if (defined(PSA_WANT_ALG_TLS12_PRF) && \
+    !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF)) || \
+    (defined(PSA_WANT_ALG_TLS12_PSK_TO_MS) && \
+    !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS)) || \
+    (defined(PSA_WANT_ALG_HKDF) && \
+    !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF)) || \
+    (defined(PSA_WANT_ALG_HKDF_EXTRACT) && \
+    !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT)) || \
+    (defined(PSA_WANT_ALG_HKDF_EXPAND) && \
+    !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND)) || \
+    (defined(PSA_WANT_ALG_PBKDF2_HMAC) && \
+    !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_HMAC))
+#define PSA_WANT_ALG_HMAC 1
+#define PSA_WANT_KEY_TYPE_HMAC 1
+#endif
+
+#if (defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128) && \
+    !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128))
+#define PSA_WANT_KEY_TYPE_AES 1
+#define PSA_WANT_ALG_CMAC 1
+#endif
+
+#endif /* PSA_CRYPTO_ADJUST_CONFIG_DEPENDENCIES_H */
diff --git a/include/psa/crypto_adjust_config_key_pair_types.h b/include/psa/crypto_adjust_config_key_pair_types.h
index 63afc0e..cec39e0 100644
--- a/include/psa/crypto_adjust_config_key_pair_types.h
+++ b/include/psa/crypto_adjust_config_key_pair_types.h
@@ -2,6 +2,8 @@
  * \file psa/crypto_adjust_config_key_pair_types.h
  * \brief Adjust PSA configuration for key pair types.
  *
+ * This is an internal header. Do not include it directly.
+ *
  * See docs/proposed/psa-conditional-inclusion-c.md.
  * - Support non-basic operations in a keypair type implicitly enables basic
  *   support for that keypair type.
@@ -19,6 +21,14 @@
 #ifndef PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H
 #define PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H
 
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include psa/crypto_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
 /*****************************************************************
  * ANYTHING -> BASIC
  ****************************************************************/
diff --git a/include/psa/crypto_adjust_config_synonyms.h b/include/psa/crypto_adjust_config_synonyms.h
index 332b622..54b116f 100644
--- a/include/psa/crypto_adjust_config_synonyms.h
+++ b/include/psa/crypto_adjust_config_synonyms.h
@@ -2,6 +2,8 @@
  * \file psa/crypto_adjust_config_synonyms.h
  * \brief Adjust PSA configuration: enable quasi-synonyms
  *
+ * This is an internal header. Do not include it directly.
+ *
  * When two features require almost the same code, we automatically enable
  * both when either one is requested, to reduce the combinatorics of
  * possible configurations.
@@ -14,6 +16,14 @@
 #ifndef PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H
 #define PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H
 
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include psa/crypto_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
 /****************************************************************/
 /* De facto synonyms */
 /****************************************************************/
diff --git a/library/entropy_poll.c b/library/entropy_poll.c
index 794ee03..611768c 100644
--- a/library/entropy_poll.c
+++ b/library/entropy_poll.c
@@ -5,10 +5,12 @@
  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
-#if defined(__linux__) || defined(__midipix__) && !defined(_GNU_SOURCE)
+#if defined(__linux__) || defined(__midipix__)
 /* Ensure that syscall() is available even when compiling with -std=c99 */
+#if !defined(_GNU_SOURCE)
 #define _GNU_SOURCE
 #endif
+#endif
 
 #include "common.h"
 
diff --git a/library/md.c b/library/md.c
index 12a3ea2..c95846a 100644
--- a/library/md.c
+++ b/library/md.c
@@ -41,7 +41,7 @@
 #include "mbedtls/sha512.h"
 #include "mbedtls/sha3.h"
 
-#if defined(MBEDTLS_PSA_CRYPTO_C)
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
 #include <psa/crypto.h>
 #include "md_psa.h"
 #include "psa_util_internal.h"
@@ -761,13 +761,13 @@
     return md_info->type;
 }
 
-#if defined(MBEDTLS_PSA_CRYPTO_C)
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
 int mbedtls_md_error_from_psa(psa_status_t status)
 {
     return PSA_TO_MBEDTLS_ERR_LIST(status, psa_to_md_errors,
                                    psa_generic_status_to_mbedtls);
 }
-#endif /* MBEDTLS_PSA_CRYPTO_C */
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
 
 
 /************************************************************************
diff --git a/library/pk.c b/library/pk.c
index c29318d..3fe51ea 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -868,7 +868,6 @@
     psa_status_t status;
     psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_type_t key_type;
-    psa_algorithm_t alg_type;
     size_t key_bits;
     /* Use a buffer size large enough to contain either a key pair or public key. */
     unsigned char exp_key[PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE];
@@ -899,7 +898,6 @@
         key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type);
     }
     key_bits = psa_get_key_bits(&key_attr);
-    alg_type = psa_get_key_algorithm(&key_attr);
 
 #if defined(MBEDTLS_RSA_C)
     if ((key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) ||
@@ -919,6 +917,7 @@
             goto exit;
         }
 
+        psa_algorithm_t alg_type = psa_get_key_algorithm(&key_attr);
         mbedtls_md_type_t md_type = MBEDTLS_MD_NONE;
         if (PSA_ALG_GET_HASH(alg_type) != PSA_ALG_ANY_HASH) {
             md_type = mbedtls_md_type_from_psa_alg(alg_type);
@@ -968,6 +967,7 @@
     } else
 #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
     {
+        (void) key_bits;
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
 
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 969c695..02554d1 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -1835,6 +1835,9 @@
 
         status = psa_copy_key_material_into_slot(
             slot, (uint8_t *) (&slot_number), sizeof(slot_number));
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
     }
 
     if (*p_drv == NULL && method == PSA_KEY_CREATION_REGISTER) {
@@ -5194,6 +5197,12 @@
         goto exit;
     }
 
+    /* No input to add (zero length), nothing to do. */
+    if (input_length == 0) {
+        status = PSA_SUCCESS;
+        goto exit;
+    }
+
     if (operation->lengths_set) {
         if (operation->ad_remaining < input_length) {
             status = PSA_ERROR_INVALID_ARGUMENT;
diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c
index b184ed0..9986a44 100644
--- a/library/psa_crypto_slot_management.c
+++ b/library/psa_crypto_slot_management.c
@@ -424,6 +424,8 @@
     if (status != PSA_SUCCESS) {
         psa_wipe_key_slot(*p_slot);
 
+        /* If the key does not exist, we need to return
+         * PSA_ERROR_INVALID_HANDLE. */
         if (status == PSA_ERROR_DOES_NOT_EXIST) {
             status = PSA_ERROR_INVALID_HANDLE;
         }
@@ -440,6 +442,9 @@
     status = PSA_ERROR_INVALID_HANDLE;
 #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
 
+    if (status != PSA_SUCCESS) {
+        *p_slot = NULL;
+    }
 #if defined(MBEDTLS_THREADING_C)
     PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
                               &mbedtls_threading_key_slot_mutex));
diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h
index bcfc9d8..a84be7d 100644
--- a/library/psa_crypto_slot_management.h
+++ b/library/psa_crypto_slot_management.h
@@ -58,6 +58,9 @@
  * It is the responsibility of the caller to call psa_unregister_read(slot)
  * when they have finished reading the contents of the slot.
  *
+ * On failure, `*p_slot` is set to NULL. This ensures that it is always valid
+ * to call psa_unregister_read on the returned slot.
+ *
  * \param key           Key identifier to query.
  * \param[out] p_slot   On success, `*p_slot` contains a pointer to the
  *                      key slot containing the description of the key
diff --git a/library/sha256.c b/library/sha256.c
index 8788981..8b2c345 100644
--- a/library/sha256.c
+++ b/library/sha256.c
@@ -44,7 +44,9 @@
 #endif /* defined(__clang__) &&  (__clang_major__ >= 4) */
 
 /* Ensure that SIG_SETMASK is defined when -std=c99 is used. */
+#if !defined(_GNU_SOURCE)
 #define _GNU_SOURCE
+#endif
 
 #include "common.h"
 
diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c
index b49a8ae..b5b975f 100644
--- a/library/ssl_tls12_server.c
+++ b/library/ssl_tls12_server.c
@@ -2631,13 +2631,8 @@
             ssl->handshake->xxdh_psa_type = psa_get_key_type(&key_attributes);
             ssl->handshake->xxdh_psa_bits = psa_get_key_bits(&key_attributes);
 
-            if (pk_type == MBEDTLS_PK_OPAQUE) {
-                /* Opaque key is created by the user (externally from Mbed TLS)
-                 * so we assume it already has the right algorithm and flags
-                 * set. Just copy its ID as reference. */
-                ssl->handshake->xxdh_psa_privkey = pk->priv_id;
-                ssl->handshake->xxdh_psa_privkey_is_external = 1;
-            } else {
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+            if (pk_type != MBEDTLS_PK_OPAQUE) {
                 /* PK_ECKEY[_DH] and PK_ECDSA instead as parsed from the PK
                  * module and only have ECDSA capabilities. Since we need
                  * them for ECDH later, we export and then re-import them with
@@ -2665,10 +2660,20 @@
                 /* Set this key as owned by the TLS library: it will be its duty
                  * to clear it exit. */
                 ssl->handshake->xxdh_psa_privkey_is_external = 0;
-            }
 
+                ret = 0;
+                break;
+            }
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+
+            /* Opaque key is created by the user (externally from Mbed TLS)
+             * so we assume it already has the right algorithm and flags
+             * set. Just copy its ID as reference. */
+            ssl->handshake->xxdh_psa_privkey = pk->priv_id;
+            ssl->handshake->xxdh_psa_privkey_is_external = 1;
             ret = 0;
             break;
+
 #if !defined(MBEDTLS_PK_USE_PSA_EC_DATA)
         case MBEDTLS_PK_ECKEY:
         case MBEDTLS_PK_ECKEY_DH:
diff --git a/programs/ssl/ssl_mail_client.c b/programs/ssl/ssl_mail_client.c
index febb881..e3ed697 100644
--- a/programs/ssl/ssl_mail_client.c
+++ b/programs/ssl/ssl_mail_client.c
@@ -727,7 +727,11 @@
     mbedtls_printf("  > Write MAIL FROM to server:");
     fflush(stdout);
 
-    len = sprintf((char *) buf, "MAIL FROM:<%s>\r\n", opt.mail_from);
+    len = mbedtls_snprintf((char *) buf, sizeof(buf), "MAIL FROM:<%s>\r\n", opt.mail_from);
+    if (len < 0 || (size_t) len >= sizeof(buf)) {
+        mbedtls_printf(" failed\n  ! mbedtls_snprintf encountered error or truncated output\n\n");
+        goto exit;
+    }
     ret = write_ssl_and_get_response(&ssl, buf, len);
     if (ret < 200 || ret > 299) {
         mbedtls_printf(" failed\n  ! server responded with %d\n\n", ret);
@@ -739,7 +743,11 @@
     mbedtls_printf("  > Write RCPT TO to server:");
     fflush(stdout);
 
-    len = sprintf((char *) buf, "RCPT TO:<%s>\r\n", opt.mail_to);
+    len = mbedtls_snprintf((char *) buf, sizeof(buf), "RCPT TO:<%s>\r\n", opt.mail_to);
+    if (len < 0 || (size_t) len >= sizeof(buf)) {
+        mbedtls_printf(" failed\n  ! mbedtls_snprintf encountered error or truncated output\n\n");
+        goto exit;
+    }
     ret = write_ssl_and_get_response(&ssl, buf, len);
     if (ret < 200 || ret > 299) {
         mbedtls_printf(" failed\n  ! server responded with %d\n\n", ret);
@@ -763,11 +771,16 @@
     mbedtls_printf("  > Write content to server:");
     fflush(stdout);
 
-    len = sprintf((char *) buf, "From: %s\r\nSubject: Mbed TLS Test mail\r\n\r\n"
-                                "This is a simple test mail from the "
-                                "Mbed TLS mail client example.\r\n"
-                                "\r\n"
-                                "Enjoy!", opt.mail_from);
+    len = mbedtls_snprintf((char *) buf, sizeof(buf),
+                           "From: %s\r\nSubject: Mbed TLS Test mail\r\n\r\n"
+                           "This is a simple test mail from the "
+                           "Mbed TLS mail client example.\r\n"
+                           "\r\n"
+                           "Enjoy!", opt.mail_from);
+    if (len < 0 || (size_t) len >= sizeof(buf)) {
+        mbedtls_printf(" failed\n  ! mbedtls_snprintf encountered error or truncated output\n\n");
+        goto exit;
+    }
     ret = write_ssl_data(&ssl, buf, len);
 
     len = sprintf((char *) buf, "\r\n.\r\n");
diff --git a/scripts/abi_check.py b/scripts/abi_check.py
index 8a604c4..f91d80e 100755
--- a/scripts/abi_check.py
+++ b/scripts/abi_check.py
@@ -101,7 +101,8 @@
 
 import xml.etree.ElementTree as ET
 
-from mbedtls_dev import build_tree
+import framework_scripts_path # pylint: disable=unused-import
+from mbedtls_framework import build_tree
 
 
 class AbiChecker:
@@ -325,8 +326,14 @@
     @staticmethod
     def _list_generated_test_data_files(git_worktree_path):
         """List the generated test data files."""
+        generate_psa_tests = 'framework/scripts/generate_psa_tests.py'
+        if not os.path.isfile(git_worktree_path + '/' + generate_psa_tests):
+            # The checked-out revision is from before generate_psa_tests.py
+            # was moved to the framework submodule. Use the old location.
+            generate_psa_tests = 'tests/scripts/generate_psa_tests.py'
+
         output = subprocess.check_output(
-            ['tests/scripts/generate_psa_tests.py', '--list'],
+            [generate_psa_tests, '--list'],
             cwd=git_worktree_path,
         ).decode('ascii')
         return [line for line in output.split('\n') if line]
@@ -352,8 +359,14 @@
             if 'storage_format' in filename:
                 storage_data_files.add(filename)
                 to_be_generated.add(filename)
+
+        generate_psa_tests = 'framework/scripts/generate_psa_tests.py'
+        if not os.path.isfile(git_worktree_path + '/' + generate_psa_tests):
+            # The checked-out revision is from before generate_psa_tests.py
+            # was moved to the framework submodule. Use the old location.
+            generate_psa_tests = 'tests/scripts/generate_psa_tests.py'
         subprocess.check_call(
-            ['tests/scripts/generate_psa_tests.py'] + sorted(to_be_generated),
+            [generate_psa_tests] + sorted(to_be_generated),
             cwd=git_worktree_path,
         )
         for test_file in sorted(storage_data_files):
diff --git a/scripts/code_size_compare.py b/scripts/code_size_compare.py
index abd13df..50749b6 100755
--- a/scripts/code_size_compare.py
+++ b/scripts/code_size_compare.py
@@ -21,9 +21,10 @@
 import typing
 from enum import Enum
 
-from mbedtls_dev import build_tree
-from mbedtls_dev import logging_util
-from mbedtls_dev import typing_util
+import framework_scripts_path # pylint: disable=unused-import
+from mbedtls_framework import build_tree
+from mbedtls_framework import logging_util
+from mbedtls_framework import typing_util
 
 class SupportedArch(Enum):
     """Supported architecture for code size measurement."""
diff --git a/scripts/code_style.py b/scripts/code_style.py
index 07952b6..d3f89d9 100755
--- a/scripts/code_style.py
+++ b/scripts/code_style.py
@@ -75,16 +75,55 @@
     output = subprocess.check_output(["git", "ls-files"] + file_patterns,
                                      universal_newlines=True)
     src_files = output.split()
+
+    # When this script is called from a git hook, some environment variables
+    # are set by default which force all git commands to use the main repository
+    # (i.e. prevent us from performing commands on the framework repo).
+    # Create an environment without these variables for running commands on the
+    # framework repo.
+    framework_env = os.environ.copy()
+    # Get a list of environment vars that git sets
+    git_env_vars = subprocess.check_output(["git", "rev-parse", "--local-env-vars"],
+                                           universal_newlines=True)
+    # Remove the vars from the environment
+    for var in git_env_vars.split():
+        framework_env.pop(var, None)
+
+    output = subprocess.check_output(["git", "-C", "framework", "ls-files"]
+                                     + file_patterns,
+                                     universal_newlines=True,
+                                     env=framework_env)
+    framework_src_files = output.split()
+
     if since:
-        # get all files changed in commits since the starting point
-        cmd = ["git", "log", since + "..HEAD", "--name-only", "--pretty=", "--"] + src_files
+        # get all files changed in commits since the starting point in ...
+        # ... the main repository
+        cmd = ["git", "log", since + "..HEAD", "--ignore-submodules",
+               "--name-only", "--pretty=", "--"] + src_files
         output = subprocess.check_output(cmd, universal_newlines=True)
         committed_changed_files = output.split()
-        # and also get all files with uncommitted changes
+        # ... the framework submodule
+        cmd = ["git", "-C", "framework", "log", since + "..HEAD",
+               "--name-only", "--pretty=", "--"] + framework_src_files
+        output = subprocess.check_output(cmd, universal_newlines=True,
+                                         env=framework_env)
+        committed_changed_files += ["framework/" + s for s in output.split()]
+
+        # and also get all files with uncommitted changes in ...
+        # ... the main repository
         cmd = ["git", "diff", "--name-only", "--"] + src_files
         output = subprocess.check_output(cmd, universal_newlines=True)
         uncommitted_changed_files = output.split()
-        src_files = list(set(committed_changed_files + uncommitted_changed_files))
+        # ... the framework submodule
+        cmd = ["git", "-C", "framework", "diff", "--name-only", "--"] + \
+              framework_src_files
+        output = subprocess.check_output(cmd, universal_newlines=True,
+                                         env=framework_env)
+        uncommitted_changed_files += ["framework/" + s for s in output.split()]
+
+        src_files = committed_changed_files + uncommitted_changed_files
+    else:
+        src_files += ["framework/" + s for s in framework_src_files]
 
     generated_files = list_generated_files()
     # Don't correct style for third-party files (and, for simplicity,
diff --git a/scripts/framework_scripts_path.py b/scripts/framework_scripts_path.py
new file mode 100644
index 0000000..4d4a440
--- /dev/null
+++ b/scripts/framework_scripts_path.py
@@ -0,0 +1,17 @@
+"""Add our Python library directory to the module search path.
+
+Usage:
+
+    import framework_scripts_path # pylint: disable=unused-import
+"""
+
+# Copyright The Mbed TLS Contributors
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+#
+
+import os
+import sys
+
+sys.path.append(os.path.join(os.path.dirname(__file__),
+                             os.path.pardir,
+                             'framework', 'scripts'))
diff --git a/scripts/generate_driver_wrappers.py b/scripts/generate_driver_wrappers.py
index 624ab81..0f0c8c7 100755
--- a/scripts/generate_driver_wrappers.py
+++ b/scripts/generate_driver_wrappers.py
@@ -17,7 +17,9 @@
 import argparse
 import jsonschema
 import jinja2
-from mbedtls_dev import build_tree
+
+import framework_scripts_path # pylint: disable=unused-import
+from mbedtls_framework import build_tree
 
 JSONSchema = NewType('JSONSchema', object)
 # The Driver is an Object, but practically it's indexable and can called a dictionary to
diff --git a/scripts/generate_psa_constants.py b/scripts/generate_psa_constants.py
index f13b507..d57d46a 100755
--- a/scripts/generate_psa_constants.py
+++ b/scripts/generate_psa_constants.py
@@ -17,8 +17,9 @@
 import os
 import sys
 
-from mbedtls_dev import build_tree
-from mbedtls_dev import macro_collector
+import framework_scripts_path # pylint: disable=unused-import
+from mbedtls_framework import build_tree
+from mbedtls_framework import macro_collector
 
 OUTPUT_TEMPLATE = '''\
 /* Automatically generated by generate_psa_constant.py. DO NOT EDIT. */
diff --git a/scripts/generate_ssl_debug_helpers.py b/scripts/generate_ssl_debug_helpers.py
index a0544f1..600d160 100755
--- a/scripts/generate_ssl_debug_helpers.py
+++ b/scripts/generate_ssl_debug_helpers.py
@@ -14,7 +14,9 @@
 import os
 import textwrap
 import argparse
-from mbedtls_dev import build_tree
+
+import framework_scripts_path # pylint: disable=unused-import
+from mbedtls_framework import build_tree
 
 
 def remove_c_comments(string):
@@ -328,7 +330,7 @@
             {translation_table}
                 }};
 
-                return "UNKOWN";
+                return "UNKNOWN";
             }}''')
         body = body.format(translation_table='\n'.join(translation_table))
         return body
diff --git a/scripts/make_generated_files.bat b/scripts/make_generated_files.bat
index abcfc39..f04f6b7 100644
--- a/scripts/make_generated_files.bat
+++ b/scripts/make_generated_files.bat
@@ -10,6 +10,8 @@
 python scripts\generate_ssl_debug_helpers.py || exit /b 1

 perl scripts\generate_visualc_files.pl || exit /b 1

 python scripts\generate_psa_constants.py || exit /b 1

-python tests\scripts\generate_bignum_tests.py || exit /b 1

-python tests\scripts\generate_ecp_tests.py || exit /b 1

-python tests\scripts\generate_psa_tests.py || exit /b 1

+python framework\scripts\generate_bignum_tests.py || exit /b 1

+python framework\scripts\generate_ecp_tests.py || exit /b 1

+python framework\scripts\generate_psa_tests.py || exit /b 1

+python framework\scripts\generate_test_keys.py --output tests\src\test_keys.h || exit /b 1

+python framework\scripts\generate_test_cert_macros.py --output tests\src\test_certs.h || exit /b 1

diff --git a/scripts/mbedtls_dev/__init__.py b/scripts/mbedtls_dev/__init__.py
deleted file mode 100644
index 15b0d60..0000000
--- a/scripts/mbedtls_dev/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# This file needs to exist to make mbedtls_dev a package.
-# Among other things, this allows modules in this directory to make
-# relative imports.
diff --git a/scripts/mbedtls_dev/asymmetric_key_data.py b/scripts/mbedtls_dev/asymmetric_key_data.py
deleted file mode 100644
index 8ca6758..0000000
--- a/scripts/mbedtls_dev/asymmetric_key_data.py
+++ /dev/null
@@ -1,157 +0,0 @@
-"""Sample key material for asymmetric key types.
-
-Meant for use in crypto_knowledge.py.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-import binascii
-import re
-from typing import Dict
-
-STR_TRANS_REMOVE_BLANKS = str.maketrans('', '', ' \t\n\r')
-
-def unhexlify(text: str) -> bytes:
-    return binascii.unhexlify(text.translate(STR_TRANS_REMOVE_BLANKS))
-
-def construct_asymmetric_key_data(src) -> Dict[str, Dict[int, bytes]]:
-    """Split key pairs into separate table entries and convert hex to bytes.
-
-    Input format: src[abbreviated_type][size] = (private_key_hex, public_key_hex)
-    Output format: dst['PSA_KEY_TYPE_xxx'][size] = key_bytes
-    """
-    dst = {} #type: Dict[str, Dict[int, bytes]]
-    for typ in src:
-        private = 'PSA_KEY_TYPE_' + re.sub(r'(\(|\Z)', r'_KEY_PAIR\1', typ, 1)
-        public = 'PSA_KEY_TYPE_' + re.sub(r'(\(|\Z)', r'_PUBLIC_KEY\1', typ, 1)
-        dst[private] = {}
-        dst[public] = {}
-        for size in src[typ]:
-            dst[private][size] = unhexlify(src[typ][size][0])
-            dst[public][size] = unhexlify(src[typ][size][1])
-    return dst
-
-## These are valid keys that don't try to exercise any edge cases. They're
-## either test vectors from some specification, or randomly generated. All
-## pairs consist of a private key and its public key.
-#pylint: disable=line-too-long
-ASYMMETRIC_KEY_DATA = construct_asymmetric_key_data({
-    'ECC(PSA_ECC_FAMILY_SECP_K1)': {
-        192: ("297ac1722ccac7589ecb240dc719842538ca974beb79f228",
-              "0426b7bb38da649ac2138fc050c6548b32553dab68afebc36105d325b75538c12323cb0764789ecb992671beb2b6bef2f5"),
-        225: ("0024122bf020fa113f6c0ac978dfbd41f749257a9468febdbe0dc9f7e8",
-              "042cc7335f4b76042bed44ef45959a62aa215f7a5ff0c8111b8c44ed654ee71c1918326ad485b2d599fe2a6eab096ee26d977334d2bac6d61d"),
-        256: ("7fa06fa02d0e911b9a47fdc17d2d962ca01e2f31d60c6212d0ed7e3bba23a7b9",
-              "045c39154579efd667adc73a81015a797d2c8682cdfbd3c3553c4a185d481cdc50e42a0e1cbc3ca29a32a645e927f54beaed14c9dbbf8279d725f5495ca924b24d"),
-    },
-    'ECC(PSA_ECC_FAMILY_SECP_R1)': {
-        192: ("d83b57a59c51358d9c8bbb898aff507f44dd14cf16917190",
-              "04e35fcbee11cec3154f80a1a61df7d7612de4f2fd70c5608d0ee3a4a1a5719471adb33966dd9b035fdb774feeba94b04c"),
-        224: ("872f203b3ad35b7f2ecc803c3a0e1e0b1ed61cc1afe71b189cd4c995",
-              "046f00eadaa949fee3e9e1c7fa1247eecec86a0dce46418b9bd3117b981d4bd0ae7a990de912f9d060d6cb531a42d22e394ac29e81804bf160"),
-        256: ("49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee",
-              "047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45"),
-        384: ("3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a",
-              "04d9c662b50ba29ca47990450e043aeaf4f0c69b15676d112f622a71c93059af999691c5680d2b44d111579db12f4a413a2ed5c45fcfb67b5b63e00b91ebe59d09a6b1ac2c0c4282aa12317ed5914f999bc488bb132e8342cc36f2ca5e3379c747"),
-        521: ("01b1b6ad07bb79e7320da59860ea28e055284f6058f279de666e06d435d2af7bda28d99fa47b7dd0963e16b0073078ee8b8a38d966a582f46d19ff95df3ad9685aae",
-              "04001de142d54f69eb038ee4b7af9d3ca07736fd9cf719eb354d69879ee7f3c136fb0fbf9f08f86be5fa128ec1a051d3e6c643e85ada8ffacf3663c260bd2c844b6f5600cee8e48a9e65d09cadd89f235dee05f3b8a646be715f1f67d5b434e0ff23a1fc07ef7740193e40eeff6f3bcdfd765aa9155033524fe4f205f5444e292c4c2f6ac1"),
-    },
-    'ECC(PSA_ECC_FAMILY_SECP_R2)': {
-        160: ("00bf539a1cdda0d7f71a50a3f98aec0a2e8e4ced1e",
-              "049570d541398665adb5cfa16f5af73b3196926bbd4b876bdb80f8eab20d0f540c22f4de9c140f6d7b"),
-    },
-    'ECC(PSA_ECC_FAMILY_SECT_K1)': {
-        163: ("03ebc8fcded2d6ab72ec0f75bdb4fd080481273e71",
-              "0406f88f90b4b65950f06ce433afdb097e320f433dc2062b8a65db8fafd3c110f46bc45663fbf021ee7eb9"),
-        233: ("41f08485ce587b06061c087e76e247c359de2ba9927ee013b2f1ed9ca8",
-              "0401e9d7189189f773bd8f71be2c10774ba18842434dfa9312595ea545104400f45a9d5675647513ba75b079fe66a29daac2ec86a6a5d4e75c5f290c1f"),
-        239: ("1a8069ce2c2c8bdd7087f2a6ab49588797e6294e979495602ab9650b9c61",
-              "04068d76b9f4508762c2379db9ee8b87ad8d86d9535132ffba3b5680440cfa28eb133d4232faf1c9aba96af11aefe634a551440800d5f8185105d3072d"),
-        283: ("006d627885dd48b9ec6facb5b3865377d755b75a5d51440e45211c1f600e15eff8a881a0",
-              "0405f48374debceaadb46ba385fd92048fcc5b9af1a1c90408bf94a68b9378df1cbfdfb6fb026a96bea06d8f181bf10c020adbcc88b6ecff96bdc564a9649c247cede601c4be63afc3"),
-        409: ("3ff5e74d932fa77db139b7c948c81e4069c72c24845574064beea8976b70267f1c6f9a503e3892ea1dcbb71fcea423faa370a8",
-              "04012c587f69f68b308ba6dcb238797f4e22290ca939ae806604e2b5ab4d9caef5a74a98fd87c4f88d292dd39d92e556e16c6ecc3c019a105826eef507cd9a04119f54d5d850b3720b3792d5d03410e9105610f7e4b420166ed45604a7a1f229d80975ba6be2060e8b"),
-        571: ("005008c97b4a161c0db1bac6452c72846d57337aa92d8ecb4a66eb01d2f29555ffb61a5317225dcc8ca6917d91789e227efc0bfe9eeda7ee21998cd11c3c9885056b0e55b4f75d51",
-              "04050172a7fd7adf98e4e2ed2742faa5cd12731a15fb0dbbdf75b1c3cc771a4369af6f2fa00e802735650881735759ea9c79961ded18e0daa0ac59afb1d513b5bbda9962e435f454fc020b4afe1445c2302ada07d295ec2580f8849b2dfa7f956b09b4cbe4c88d3b1c217049f75d3900d36df0fa12689256b58dd2ef784ebbeb0564600cf47a841485f8cf897a68accd5a"),
-    },
-    'ECC(PSA_ECC_FAMILY_SECT_R1)': {
-        163: ("009b05dc82d46d64a04a22e6e5ca70ca1231e68c50",
-              "0400465eeb9e7258b11e33c02266bfe834b20bcb118700772796ee4704ec67651bd447e3011959a79a04cb"),
-        233: ("00e5e42834e3c78758088b905deea975f28dc20ef6173e481f96e88afe7f",
-              "0400cd68c8af4430c92ec7a7048becfdf00a6bae8d1b4c37286f2d336f2a0e017eca3748f4ad6d435c85867aa014eea1bd6d9d005bbd8319cab629001d"),
-        283: ("004cecad915f6f3c9bbbd92d1eb101eda23f16c7dad60a57c87c7e1fd2b29b22f6d666ad",
-              "04052f9ff887254c2d1440ba9e30f13e2185ba53c373b2c410dae21cf8c167f796c08134f601cbc4c570bffbc2433082cf4d9eb5ba173ecb8caec15d66a02673f60807b2daa729b765"),
-        409: ("00c22422d265721a3ae2b3b2baeb77bee50416e19877af97b5fc1c700a0a88916ecb9050135883accb5e64edc77a3703f4f67a64",
-              "0401aa25466b1d291846db365957b25431591e50d9c109fe2106e93bb369775896925b15a7bfec397406ab4fe6f6b1a13bf8fdcb9300fa5500a813228676b0a6c572ed96b0f4aec7e87832e7e20f17ca98ecdfd36f59c82bddb8665f1f357a73900e827885ec9e1f22"),
-        571: ("026ac1cdf92a13a1b8d282da9725847908745138f5c6706b52d164e3675fcfbf86fc3e6ab2de732193267db029dd35a0599a94a118f480231cfc6ccca2ebfc1d8f54176e0f5656a1",
-              "040708f3403ee9948114855c17572152a08f8054d486defef5f29cbffcfb7cfd9280746a1ac5f751a6ad902ec1e0525120e9be56f03437af196fbe60ee7856e3542ab2cf87880632d80290e39b1a2bd03c6bbf6225511c567bd2ff41d2325dc58346f2b60b1feee4dc8b2af2296c2dc52b153e0556b5d24152b07f690c3fa24e4d1d19efbdeb1037833a733654d2366c74"),
-    },
-    'ECC(PSA_ECC_FAMILY_SECT_R2)': {
-        163: ("0210b482a458b4822d0cb21daa96819a67c8062d34",
-              "0403692601144c32a6cfa369ae20ae5d43c1c764678c037bafe80c6fd2e42b7ced96171d9c5367fd3dca6f"),
-    },
-    'ECC(PSA_ECC_FAMILY_BRAINPOOL_P_R1)': {
-        160: ("69502c4fdaf48d4fa617bdd24498b0406d0eeaac",
-              "04d4b9186816358e2f9c59cf70748cb70641b22fbab65473db4b4e22a361ed7e3de7e8a8ddc4130c5c"),
-        192: ("1688a2c5fbf4a3c851d76a98c3ec88f445a97996283db59f",
-              "043fdd168c179ff5363dd71dcd58de9617caad791ae0c37328be9ca0bfc79cebabf6a95d1c52df5b5f3c8b1a2441cf6c88"),
-        224: ("a69835dafeb5da5ab89c59860dddebcfd80b529a99f59b880882923c",
-              "045fbea378fc8583b3837e3f21a457c31eaf20a54e18eb11d104b3adc47f9d1c97eb9ea4ac21740d70d88514b98bf0bc31addac1d19c4ab3cc"),
-        256: ("2161d6f2db76526fa62c16f356a80f01f32f776784b36aa99799a8b7662080ff",
-              "04768c8cae4abca6306db0ed81b0c4a6215c378066ec6d616c146e13f1c7df809b96ab6911c27d8a02339f0926840e55236d3d1efbe2669d090e4c4c660fada91d"),
-        320: ("61b8daa7a6e5aa9fccf1ef504220b2e5a5b8c6dc7475d16d3172d7db0b2778414e4f6e8fa2032ead",
-              "049caed8fb4742956cc2ad12a9a1c995e21759ef26a07bc2054136d3d2f28bb331a70e26c4c687275ab1f434be7871e115d2350c0c5f61d4d06d2bcdb67f5cb63fdb794e5947c87dc6849a58694e37e6cd"),
-        384: ("3dd92e750d90d7d39fc1885cd8ad12ea9441f22b9334b4d965202adb1448ce24c5808a85dd9afc229af0a3124f755bcb",
-              "04719f9d093a627e0d350385c661cebf00c61923566fe9006a3107af1d871bc6bb68985fd722ea32be316f8e783b7cd1957785f66cfc0cb195dd5c99a8e7abaa848553a584dfd2b48e76d445fe00dd8be59096d877d4696d23b4bc8db14724e66a"),
-        512: ("372c9778f69f726cbca3f4a268f16b4d617d10280d79a6a029cd51879fe1012934dfe5395455337df6906dc7d6d2eea4dbb2065c0228f73b3ed716480e7d71d2",
-              "0438b7ec92b61c5c6c7fbc28a4ec759d48fcd4e2e374defd5c4968a54dbef7510e517886fbfc38ea39aa529359d70a7156c35d3cbac7ce776bdb251dd64bce71234424ee7049eed072f0dbc4d79996e175d557e263763ae97095c081e73e7db2e38adc3d4c9a0487b1ede876dc1fca61c902e9a1d8722b8612928f18a24845591a"),
-    },
-    'ECC(PSA_ECC_FAMILY_MONTGOMERY)': {
-        255: ("70076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c6a",
-              "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"),
-        448: ("e4e49f52686f9ee3b638528f721f1596196ffd0a1cddb64c3f216f06541805cfeb1a286dc78018095cdfec050e8007b5f4908962ba20d6c1",
-              "c0d3a5a2b416a573dc9909f92f134ac01323ab8f8e36804e578588ba2d09fe7c3e737f771ca112825b548a0ffded6d6a2fd09a3e77dec30e"),
-    },
-    'ECC(PSA_ECC_FAMILY_TWISTED_EDWARDS)': {
-        255: ("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
-              "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"),
-        448: ("6c82a562cb808d10d632be89c8513ebf6c929f34ddfa8c9f63c9960ef6e348a3528c8a3fcc2f044e39a3fc5b94492f8f032e7549a20098f95b",
-              "5fd7449b59b461fd2ce787ec616ad46a1da1342485a70e1f8a0ea75d80e96778edf124769b46c7061bd6783df1e50f6cd1fa1abeafe8256180"),
-    },
-    'RSA': {
-        1024: ("""
-3082025e
- 020100
- 02818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3
- 0203010001
- 02818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1
- 024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113
- 024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091
- 024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d
- 024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1
- 024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24
-""", """
- 308189
-  02818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3
- 0203010001
-"""),
-        1536: ("""
-3082037b
- 020100
- 0281c100c870feb6ca6b1d2bd9f2dd99e20f1fe2d7e5192de662229dbe162bd1ba66336a7182903ca0b72796cd441c83d24bcdc3e9a2f5e4399c8a043f1c3ddf04754a66d4cfe7b3671a37dd31a9b4c13bfe06ee90f9d94ddaa06de67a52ac863e68f756736ceb014405a6160579640f831dddccc34ad0b05070e3f9954a58d1815813e1b83bcadba814789c87f1ef2ba5d738b793ec456a67360eea1b5faf1c7cc7bf24f3b2a9d0f8958b1096e0f0c335f8888d0c63a51c3c0337214fa3f5efdf6dcc35
- 0203010001
- 0281c06d2d670047973a87752a9d5bc14f3dae00acb01f593aa0e24cf4a49f932931de4bbfb332e2d38083da80bc0b6d538edba479f7f77d0deffb4a28e6e67ff6273585bb4cd862535c946605ab0809d65f0e38f76e4ec2c3d9b8cd6e14bcf667943892cd4b34cc6420a439abbf3d7d35ef73976dd6f9cbde35a51fa5213f0107f83e3425835d16d3c9146fc9e36ce75a09bb66cdff21dd5a776899f1cb07e282cca27be46510e9c799f0d8db275a6be085d9f3f803218ee3384265bfb1a3640e8ca1
- 026100e6848c31d466fffefc547e3a3b0d3785de6f78b0dd12610843512e495611a0675509b1650b27415009838dd8e68eec6e7530553b637d602424643b33e8bc5b762e1799bc79d56b13251d36d4f201da2182416ce13574e88278ff04467ad602d9
- 026100de994fdf181f02be2bf9e5f5e4e517a94993b827d1eaf609033e3a6a6f2396ae7c44e9eb594cf1044cb3ad32ea258f0c82963b27bb650ed200cde82cb993374be34be5b1c7ead5446a2b82a4486e8c1810a0b01551609fb0841d474bada802bd
- 026076ddae751b73a959d0bfb8ff49e7fcd378e9be30652ecefe35c82cb8003bc29cc60ae3809909baf20c95db9516fe680865417111d8b193dbcf30281f1249de57c858bf1ba32f5bb1599800e8398a9ef25c7a642c95261da6f9c17670e97265b1
- 0260732482b837d5f2a9443e23c1aa0106d83e82f6c3424673b5fdc3769c0f992d1c5c93991c7038e882fcda04414df4d7a5f4f698ead87851ce37344b60b72d7b70f9c60cae8566e7a257f8e1bef0e89df6e4c2f9d24d21d9f8889e4c7eccf91751
- 026009050d94493da8f00a4ddbe9c800afe3d44b43f78a48941a79b2814a1f0b81a18a8b2347642a03b27998f5a18de9abc9ae0e54ab8294feac66dc87e854cce6f7278ac2710cb5878b592ffeb1f4f0a1853e4e8d1d0561b6efcc831a296cf7eeaf
-""", """
-3081c9
- 0281c100c870feb6ca6b1d2bd9f2dd99e20f1fe2d7e5192de662229dbe162bd1ba66336a7182903ca0b72796cd441c83d24bcdc3e9a2f5e4399c8a043f1c3ddf04754a66d4cfe7b3671a37dd31a9b4c13bfe06ee90f9d94ddaa06de67a52ac863e68f756736ceb014405a6160579640f831dddccc34ad0b05070e3f9954a58d1815813e1b83bcadba814789c87f1ef2ba5d738b793ec456a67360eea1b5faf1c7cc7bf24f3b2a9d0f8958b1096e0f0c335f8888d0c63a51c3c0337214fa3f5efdf6dcc35
- 0203010001
-"""),
-    },
-})
diff --git a/scripts/mbedtls_dev/bignum_common.py b/scripts/mbedtls_dev/bignum_common.py
deleted file mode 100644
index eebc858..0000000
--- a/scripts/mbedtls_dev/bignum_common.py
+++ /dev/null
@@ -1,406 +0,0 @@
-"""Common features for bignum in test generation framework."""
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-from abc import abstractmethod
-import enum
-from typing import Iterator, List, Tuple, TypeVar, Any
-from copy import deepcopy
-from itertools import chain
-from math import ceil
-
-from . import test_case
-from . import test_data_generation
-from .bignum_data import INPUTS_DEFAULT, MODULI_DEFAULT
-
-T = TypeVar('T') #pylint: disable=invalid-name
-
-def invmod(a: int, n: int) -> int:
-    """Return inverse of a to modulo n.
-
-    Equivalent to pow(a, -1, n) in Python 3.8+. Implementation is equivalent
-    to long_invmod() in CPython.
-    """
-    b, c = 1, 0
-    while n:
-        q, r = divmod(a, n)
-        a, b, c, n = n, c, b - q*c, r
-    # at this point a is the gcd of the original inputs
-    if a == 1:
-        return b
-    raise ValueError("Not invertible")
-
-def invmod_positive(a: int, n: int) -> int:
-    """Return a non-negative inverse of a to modulo n."""
-    inv = invmod(a, n)
-    return inv if inv >= 0 else inv + n
-
-def hex_to_int(val: str) -> int:
-    """Implement the syntax accepted by mbedtls_test_read_mpi().
-
-    This is a superset of what is accepted by mbedtls_test_read_mpi_core().
-    """
-    if val in ['', '-']:
-        return 0
-    return int(val, 16)
-
-def quote_str(val: str) -> str:
-    return "\"{}\"".format(val)
-
-def bound_mpi(val: int, bits_in_limb: int) -> int:
-    """First number exceeding number of limbs needed for given input value."""
-    return bound_mpi_limbs(limbs_mpi(val, bits_in_limb), bits_in_limb)
-
-def bound_mpi_limbs(limbs: int, bits_in_limb: int) -> int:
-    """First number exceeding maximum of given number of limbs."""
-    bits = bits_in_limb * limbs
-    return 1 << bits
-
-def limbs_mpi(val: int, bits_in_limb: int) -> int:
-    """Return the number of limbs required to store value."""
-    bit_length = max(val.bit_length(), 1)
-    return (bit_length + bits_in_limb - 1) // bits_in_limb
-
-def combination_pairs(values: List[T]) -> List[Tuple[T, T]]:
-    """Return all pair combinations from input values."""
-    return [(x, y) for x in values for y in values]
-
-def bits_to_limbs(bits: int, bits_in_limb: int) -> int:
-    """ Return the appropriate ammount of limbs needed to store
-        a number contained in input bits"""
-    return ceil(bits / bits_in_limb)
-
-def hex_digits_for_limb(limbs: int, bits_in_limb: int) -> int:
-    """ Return the hex digits need for a number of limbs. """
-    return 2 * ((limbs * bits_in_limb) // 8)
-
-def hex_digits_max_int(val: str, bits_in_limb: int) -> int:
-    """ Return the first number exceeding maximum  the limb space
-    required to store the input hex-string value. This method
-    weights on the input str_len rather than numerical value
-    and works with zero-padded inputs"""
-    n = ((1 << (len(val) * 4)) - 1)
-    l = limbs_mpi(n, bits_in_limb)
-    return bound_mpi_limbs(l, bits_in_limb)
-
-def zfill_match(reference: str, target: str) -> str:
-    """ Zero pad target hex-string to match the limb size of
-    the reference input """
-    lt = len(target)
-    lr = len(reference)
-    target_len = lr if lt < lr else lt
-    return "{:x}".format(int(target, 16)).zfill(target_len)
-
-class OperationCommon(test_data_generation.BaseTest):
-    """Common features for bignum binary operations.
-
-    This adds functionality common in binary operation tests.
-
-    Attributes:
-        symbol: Symbol to use for the operation in case description.
-        input_values: List of values to use as test case inputs. These are
-            combined to produce pairs of values.
-        input_cases: List of tuples containing pairs of test case inputs. This
-            can be used to implement specific pairs of inputs.
-        unique_combinations_only: Boolean to select if test case combinations
-            must be unique. If True, only A,B or B,A would be included as a test
-            case. If False, both A,B and B,A would be included.
-        input_style: Controls the way how test data is passed to the functions
-            in the generated test cases. "variable" passes them as they are
-            defined in the python source. "arch_split" pads the values with
-            zeroes depending on the architecture/limb size. If this is set,
-            test cases are generated for all architectures.
-        arity: the number of operands for the operation. Currently supported
-            values are 1 and 2.
-    """
-    symbol = ""
-    input_values = INPUTS_DEFAULT # type: List[str]
-    input_cases = [] # type: List[Any]
-    dependencies = [] # type: List[Any]
-    unique_combinations_only = False
-    input_styles = ["variable", "fixed", "arch_split"] # type: List[str]
-    input_style = "variable" # type: str
-    limb_sizes = [32, 64] # type: List[int]
-    arities = [1, 2]
-    arity = 2
-    suffix = False   # for arity = 1, symbol can be prefix (default) or suffix
-
-    def __init__(self, val_a: str, val_b: str = "0", bits_in_limb: int = 32) -> None:
-        self.val_a = val_a
-        self.val_b = val_b
-        # Setting the int versions here as opposed to making them @properties
-        # provides earlier/more robust input validation.
-        self.int_a = hex_to_int(val_a)
-        self.int_b = hex_to_int(val_b)
-        self.dependencies = deepcopy(self.dependencies)
-        if bits_in_limb not in self.limb_sizes:
-            raise ValueError("Invalid number of bits in limb!")
-        if self.input_style == "arch_split":
-            self.dependencies.append("MBEDTLS_HAVE_INT{:d}".format(bits_in_limb))
-        self.bits_in_limb = bits_in_limb
-
-    @property
-    def boundary(self) -> int:
-        if self.arity == 1:
-            return self.int_a
-        elif self.arity == 2:
-            return max(self.int_a, self.int_b)
-        raise ValueError("Unsupported number of operands!")
-
-    @property
-    def limb_boundary(self) -> int:
-        return bound_mpi(self.boundary, self.bits_in_limb)
-
-    @property
-    def limbs(self) -> int:
-        return limbs_mpi(self.boundary, self.bits_in_limb)
-
-    @property
-    def hex_digits(self) -> int:
-        return hex_digits_for_limb(self.limbs, self.bits_in_limb)
-
-    def format_arg(self, val: str) -> str:
-        if self.input_style not in self.input_styles:
-            raise ValueError("Unknown input style!")
-        if self.input_style == "variable":
-            return val
-        else:
-            return val.zfill(self.hex_digits)
-
-    def format_result(self, res: int) -> str:
-        res_str = '{:x}'.format(res)
-        return quote_str(self.format_arg(res_str))
-
-    @property
-    def arg_a(self) -> str:
-        return self.format_arg(self.val_a)
-
-    @property
-    def arg_b(self) -> str:
-        if self.arity == 1:
-            raise AttributeError("Operation is unary and doesn't have arg_b!")
-        return self.format_arg(self.val_b)
-
-    def arguments(self) -> List[str]:
-        args = [quote_str(self.arg_a)]
-        if self.arity == 2:
-            args.append(quote_str(self.arg_b))
-        return args + self.result()
-
-    def description(self) -> str:
-        """Generate a description for the test case.
-
-        If not set, case_description uses the form A `symbol` B, where symbol
-        is used to represent the operation. Descriptions of each value are
-        generated to provide some context to the test case.
-        """
-        if not self.case_description:
-            if self.arity == 1:
-                format_string = "{1:x} {0}" if self.suffix else "{0} {1:x}"
-                self.case_description = format_string.format(
-                    self.symbol, self.int_a
-                )
-            elif self.arity == 2:
-                self.case_description = "{:x} {} {:x}".format(
-                    self.int_a, self.symbol, self.int_b
-                )
-        return super().description()
-
-    @property
-    def is_valid(self) -> bool:
-        return True
-
-    @abstractmethod
-    def result(self) -> List[str]:
-        """Get the result of the operation.
-
-        This could be calculated during initialization and stored as `_result`
-        and then returned, or calculated when the method is called.
-        """
-        raise NotImplementedError
-
-    @classmethod
-    def get_value_pairs(cls) -> Iterator[Tuple[str, str]]:
-        """Generator to yield pairs of inputs.
-
-        Combinations are first generated from all input values, and then
-        specific cases provided.
-        """
-        if cls.arity == 1:
-            yield from ((a, "0") for a in cls.input_values)
-        elif cls.arity == 2:
-            if cls.unique_combinations_only:
-                yield from combination_pairs(cls.input_values)
-            else:
-                yield from (
-                    (a, b)
-                    for a in cls.input_values
-                    for b in cls.input_values
-                )
-        else:
-            raise ValueError("Unsupported number of operands!")
-
-    @classmethod
-    def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
-        if cls.input_style not in cls.input_styles:
-            raise ValueError("Unknown input style!")
-        if cls.arity not in cls.arities:
-            raise ValueError("Unsupported number of operands!")
-        if cls.input_style == "arch_split":
-            test_objects = (cls(a, b, bits_in_limb=bil)
-                            for a, b in cls.get_value_pairs()
-                            for bil in cls.limb_sizes)
-            special_cases = (cls(*args, bits_in_limb=bil) # type: ignore
-                             for args in cls.input_cases
-                             for bil in cls.limb_sizes)
-        else:
-            test_objects = (cls(a, b)
-                            for a, b in cls.get_value_pairs())
-            special_cases = (cls(*args) for args in cls.input_cases)
-        yield from (valid_test_object.create_test_case()
-                    for valid_test_object in filter(
-                        lambda test_object: test_object.is_valid,
-                        chain(test_objects, special_cases)
-                        )
-                    )
-
-
-class ModulusRepresentation(enum.Enum):
-    """Representation selector of a modulus."""
-    # Numerical values aligned with the type mbedtls_mpi_mod_rep_selector
-    INVALID = 0
-    MONTGOMERY = 2
-    OPT_RED = 3
-
-    def symbol(self) -> str:
-        """The C symbol for this representation selector."""
-        return 'MBEDTLS_MPI_MOD_REP_' + self.name
-
-    @classmethod
-    def supported_representations(cls) -> List['ModulusRepresentation']:
-        """Return all representations that are supported in positive test cases."""
-        return [cls.MONTGOMERY, cls.OPT_RED]
-
-
-class ModOperationCommon(OperationCommon):
-    #pylint: disable=abstract-method
-    """Target for bignum mod_raw test case generation."""
-    moduli = MODULI_DEFAULT # type: List[str]
-    montgomery_form_a = False
-    disallow_zero_a = False
-
-    def __init__(self, val_n: str, val_a: str, val_b: str = "0",
-                 bits_in_limb: int = 64) -> None:
-        super().__init__(val_a=val_a, val_b=val_b, bits_in_limb=bits_in_limb)
-        self.val_n = val_n
-        # Setting the int versions here as opposed to making them @properties
-        # provides earlier/more robust input validation.
-        self.int_n = hex_to_int(val_n)
-
-    def to_montgomery(self, val: int) -> int:
-        return (val * self.r) % self.int_n
-
-    def from_montgomery(self, val: int) -> int:
-        return (val * self.r_inv) % self.int_n
-
-    def convert_from_canonical(self, canonical: int,
-                               rep: ModulusRepresentation) -> int:
-        """Convert values from canonical representation to the given representation."""
-        if rep is ModulusRepresentation.MONTGOMERY:
-            return self.to_montgomery(canonical)
-        elif rep is ModulusRepresentation.OPT_RED:
-            return canonical
-        else:
-            raise ValueError('Modulus representation not supported: {}'
-                             .format(rep.name))
-
-    @property
-    def boundary(self) -> int:
-        return self.int_n
-
-    @property
-    def arg_a(self) -> str:
-        if self.montgomery_form_a:
-            value_a = self.to_montgomery(self.int_a)
-        else:
-            value_a = self.int_a
-        return self.format_arg('{:x}'.format(value_a))
-
-    @property
-    def arg_n(self) -> str:
-        return self.format_arg(self.val_n)
-
-    def format_arg(self, val: str) -> str:
-        return super().format_arg(val).zfill(self.hex_digits)
-
-    def arguments(self) -> List[str]:
-        return [quote_str(self.arg_n)] + super().arguments()
-
-    @property
-    def r(self) -> int: # pylint: disable=invalid-name
-        l = limbs_mpi(self.int_n, self.bits_in_limb)
-        return bound_mpi_limbs(l, self.bits_in_limb)
-
-    @property
-    def r_inv(self) -> int:
-        return invmod(self.r, self.int_n)
-
-    @property
-    def r2(self) -> int: # pylint: disable=invalid-name
-        return pow(self.r, 2)
-
-    @property
-    def is_valid(self) -> bool:
-        if self.int_a >= self.int_n:
-            return False
-        if self.disallow_zero_a and self.int_a == 0:
-            return False
-        if self.arity == 2 and self.int_b >= self.int_n:
-            return False
-        return True
-
-    def description(self) -> str:
-        """Generate a description for the test case.
-
-        It uses the form A `symbol` B mod N, where symbol is used to represent
-        the operation.
-        """
-
-        if not self.case_description:
-            return super().description() + " mod {:x}".format(self.int_n)
-        return super().description()
-
-    @classmethod
-    def input_cases_args(cls) -> Iterator[Tuple[Any, Any, Any]]:
-        if cls.arity == 1:
-            yield from ((n, a, "0") for a, n in cls.input_cases)
-        elif cls.arity == 2:
-            yield from ((n, a, b) for a, b, n in cls.input_cases)
-        else:
-            raise ValueError("Unsupported number of operands!")
-
-    @classmethod
-    def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
-        if cls.input_style not in cls.input_styles:
-            raise ValueError("Unknown input style!")
-        if cls.arity not in cls.arities:
-            raise ValueError("Unsupported number of operands!")
-        if cls.input_style == "arch_split":
-            test_objects = (cls(n, a, b, bits_in_limb=bil)
-                            for n in cls.moduli
-                            for a, b in cls.get_value_pairs()
-                            for bil in cls.limb_sizes)
-            special_cases = (cls(*args, bits_in_limb=bil)
-                             for args in cls.input_cases_args()
-                             for bil in cls.limb_sizes)
-        else:
-            test_objects = (cls(n, a, b)
-                            for n in cls.moduli
-                            for a, b in cls.get_value_pairs())
-            special_cases = (cls(*args) for args in cls.input_cases_args())
-        yield from (valid_test_object.create_test_case()
-                    for valid_test_object in filter(
-                        lambda test_object: test_object.is_valid,
-                        chain(test_objects, special_cases)
-                        ))
diff --git a/scripts/mbedtls_dev/bignum_core.py b/scripts/mbedtls_dev/bignum_core.py
deleted file mode 100644
index 909f6a3..0000000
--- a/scripts/mbedtls_dev/bignum_core.py
+++ /dev/null
@@ -1,896 +0,0 @@
-"""Framework classes for generation of bignum core test cases."""
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-import random
-
-from typing import Dict, Iterator, List, Tuple
-
-from . import test_case
-from . import test_data_generation
-from . import bignum_common
-from .bignum_data import ADD_SUB_DATA
-
-class BignumCoreTarget(test_data_generation.BaseTarget):
-    #pylint: disable=abstract-method, too-few-public-methods
-    """Target for bignum core test case generation."""
-    target_basename = 'test_suite_bignum_core.generated'
-
-
-class BignumCoreShiftR(BignumCoreTarget, test_data_generation.BaseTest):
-    """Test cases for mbedtls_bignum_core_shift_r()."""
-    count = 0
-    test_function = "mpi_core_shift_r"
-    test_name = "Core shift right"
-
-    DATA = [
-        ('00', '0', [0, 1, 8]),
-        ('01', '1', [0, 1, 2, 8, 64]),
-        ('dee5ca1a7ef10a75', '64-bit',
-         list(range(11)) + [31, 32, 33, 63, 64, 65, 71, 72]),
-        ('002e7ab0070ad57001', '[leading 0 limb]',
-         [0, 1, 8, 63, 64]),
-        ('a1055eb0bb1efa1150ff', '80-bit',
-         [0, 1, 8, 63, 64, 65, 72, 79, 80, 81, 88, 128, 129, 136]),
-        ('020100000000000000001011121314151617', '138-bit',
-         [0, 1, 8, 9, 16, 72, 73, 136, 137, 138, 144]),
-    ]
-
-    def __init__(self, input_hex: str, descr: str, count: int) -> None:
-        self.input_hex = input_hex
-        self.number_description = descr
-        self.shift_count = count
-        self.result = bignum_common.hex_to_int(input_hex) >> count
-
-    def arguments(self) -> List[str]:
-        return ['"{}"'.format(self.input_hex),
-                str(self.shift_count),
-                '"{:0{}x}"'.format(self.result, len(self.input_hex))]
-
-    def description(self) -> str:
-        return 'Core shift {} >> {}'.format(self.number_description,
-                                            self.shift_count)
-
-    @classmethod
-    def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
-        for input_hex, descr, counts in cls.DATA:
-            for count in counts:
-                yield cls(input_hex, descr, count).create_test_case()
-
-
-class BignumCoreShiftL(BignumCoreTarget, bignum_common.ModOperationCommon):
-    """Test cases for mbedtls_bignum_core_shift_l()."""
-
-    BIT_SHIFT_VALUES = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a',
-                        '1f', '20', '21', '3f', '40', '41', '47', '48', '4f',
-                        '50', '51', '58', '80', '81', '88']
-    DATA = ["0", "1", "40", "dee5ca1a7ef10a75", "a1055eb0bb1efa1150ff",
-            "002e7ab0070ad57001", "020100000000000000001011121314151617",
-            "1946e2958a85d8863ae21f4904fcc49478412534ed53eaf321f63f2a222"
-            "7a3c63acbf50b6305595f90cfa8327f6db80d986fe96080bcbb5df1bdbe"
-            "9b74fb8dedf2bddb3f8215b54dffd66409323bcc473e45a8fe9d08e77a51"
-            "1698b5dad0416305db7fcf"]
-    arity = 1
-    test_function = "mpi_core_shift_l"
-    test_name = "Core shift(L)"
-    input_style = "arch_split"
-    symbol = "<<"
-    input_values = BIT_SHIFT_VALUES
-    moduli = DATA
-
-    @property
-    def val_n_max_limbs(self) -> int:
-        """ Return the limb count required to store the maximum number that can
-        fit in a the number of digits used by val_n """
-        m = bignum_common.hex_digits_max_int(self.val_n, self.bits_in_limb) - 1
-        return bignum_common.limbs_mpi(m, self.bits_in_limb)
-
-    def arguments(self) -> List[str]:
-        return [bignum_common.quote_str(self.val_n),
-                str(self.int_a)
-                ] + self.result()
-
-    def description(self) -> str:
-        """ Format the output as:
-        #{count} {hex input} ({input bits} {limbs capacity}) << {bit shift} """
-        bits = "({} bits in {} limbs)".format(self.int_n.bit_length(), self.val_n_max_limbs)
-        return "{} #{} {} {} {} {}".format(self.test_name,
-                                           self.count,
-                                           self.val_n,
-                                           bits,
-                                           self.symbol,
-                                           self.int_a)
-
-    def format_result(self, res: int) -> str:
-        # Override to match zero-pading for leading digits between the output and input.
-        res_str = bignum_common.zfill_match(self.val_n, "{:x}".format(res))
-        return bignum_common.quote_str(res_str)
-
-    def result(self) -> List[str]:
-        result = (self.int_n << self.int_a)
-        # Calculate if there is space for shifting to the left(leading zero limbs)
-        mx = bignum_common.hex_digits_max_int(self.val_n, self.bits_in_limb)
-        # If there are empty limbs ahead, adjust the bitmask accordingly
-        result = result & (mx - 1)
-        return [self.format_result(result)]
-
-    @property
-    def is_valid(self) -> bool:
-        return True
-
-
-class BignumCoreCTLookup(BignumCoreTarget, test_data_generation.BaseTest):
-    """Test cases for mbedtls_mpi_core_ct_uint_table_lookup()."""
-    test_function = "mpi_core_ct_uint_table_lookup"
-    test_name = "Constant time MPI table lookup"
-
-    bitsizes = [
-        (32, "One limb"),
-        (192, "Smallest curve sized"),
-        (512, "Largest curve sized"),
-        (2048, "Small FF/RSA sized"),
-        (4096, "Large FF/RSA sized"),
-        ]
-
-    window_sizes = [0, 1, 2, 3, 4, 5, 6]
-
-    def __init__(self,
-                 bitsize: int, descr: str, window_size: int) -> None:
-        self.bitsize = bitsize
-        self.bitsize_description = descr
-        self.window_size = window_size
-
-    def arguments(self) -> List[str]:
-        return [str(self.bitsize), str(self.window_size)]
-
-    def description(self) -> str:
-        return '{} - {} MPI with {} bit window'.format(
-            BignumCoreCTLookup.test_name,
-            self.bitsize_description,
-            self.window_size
-            )
-
-    @classmethod
-    def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
-        for bitsize, bitsize_description in cls.bitsizes:
-            for window_size in cls.window_sizes:
-                yield (cls(bitsize, bitsize_description, window_size)
-                       .create_test_case())
-
-
-class BignumCoreAddAndAddIf(BignumCoreTarget, bignum_common.OperationCommon):
-    """Test cases for bignum core add and add-if."""
-    count = 0
-    symbol = "+"
-    test_function = "mpi_core_add_and_add_if"
-    test_name = "mpi_core_add_and_add_if"
-    input_style = "arch_split"
-    input_values = ADD_SUB_DATA
-    unique_combinations_only = True
-
-    def result(self) -> List[str]:
-        result = self.int_a + self.int_b
-
-        carry, result = divmod(result, self.limb_boundary)
-
-        return [
-            self.format_result(result),
-            str(carry)
-        ]
-
-
-class BignumCoreSub(BignumCoreTarget, bignum_common.OperationCommon):
-    """Test cases for bignum core sub."""
-    count = 0
-    input_style = "arch_split"
-    symbol = "-"
-    test_function = "mpi_core_sub"
-    test_name = "mbedtls_mpi_core_sub"
-    input_values = ADD_SUB_DATA
-
-    def result(self) -> List[str]:
-        if self.int_a >= self.int_b:
-            result = self.int_a - self.int_b
-            carry = 0
-        else:
-            result = self.limb_boundary + self.int_a - self.int_b
-            carry = 1
-        return [
-            self.format_result(result),
-            str(carry)
-        ]
-
-
-class BignumCoreMLA(BignumCoreTarget, bignum_common.OperationCommon):
-    """Test cases for fixed-size multiply accumulate."""
-    count = 0
-    test_function = "mpi_core_mla"
-    test_name = "mbedtls_mpi_core_mla"
-
-    input_values = [
-        "0", "1", "fffe", "ffffffff", "100000000", "20000000000000",
-        "ffffffffffffffff", "10000000000000000", "1234567890abcdef0",
-        "fffffffffffffffffefefefefefefefe",
-        "100000000000000000000000000000000",
-        "1234567890abcdef01234567890abcdef0",
-        "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
-        "1234567890abcdef01234567890abcdef01234567890abcdef01234567890abcdef0",
-        (
-            "4df72d07b4b71c8dacb6cffa954f8d88254b6277099308baf003fab73227f"
-            "34029643b5a263f66e0d3c3fa297ef71755efd53b8fb6cb812c6bbf7bcf17"
-            "9298bd9947c4c8b14324140a2c0f5fad7958a69050a987a6096e9f055fb38"
-            "edf0c5889eca4a0cfa99b45fbdeee4c696b328ddceae4723945901ec02507"
-            "6b12b"
-        )
-    ] # type: List[str]
-    input_scalars = [
-        "0", "3", "fe", "ff", "ffff", "10000", "ffffffff", "100000000",
-        "7f7f7f7f7f7f7f7f", "8000000000000000", "fffffffffffffffe"
-    ] # type: List[str]
-
-    def __init__(self, val_a: str, val_b: str, val_s: str) -> None:
-        super().__init__(val_a, val_b)
-        self.arg_scalar = val_s
-        self.int_scalar = bignum_common.hex_to_int(val_s)
-        if bignum_common.limbs_mpi(self.int_scalar, 32) > 1:
-            self.dependencies = ["MBEDTLS_HAVE_INT64"]
-
-    def arguments(self) -> List[str]:
-        return [
-            bignum_common.quote_str(self.arg_a),
-            bignum_common.quote_str(self.arg_b),
-            bignum_common.quote_str(self.arg_scalar)
-        ] + self.result()
-
-    def description(self) -> str:
-        """Override and add the additional scalar."""
-        if not self.case_description:
-            self.case_description = "0x{} + 0x{} * 0x{}".format(
-                self.arg_a, self.arg_b, self.arg_scalar
-            )
-        return super().description()
-
-    def result(self) -> List[str]:
-        result = self.int_a + (self.int_b * self.int_scalar)
-        bound_val = max(self.int_a, self.int_b)
-        bound_4 = bignum_common.bound_mpi(bound_val, 32)
-        bound_8 = bignum_common.bound_mpi(bound_val, 64)
-        carry_4, remainder_4 = divmod(result, bound_4)
-        carry_8, remainder_8 = divmod(result, bound_8)
-        return [
-            "\"{:x}\"".format(remainder_4),
-            "\"{:x}\"".format(carry_4),
-            "\"{:x}\"".format(remainder_8),
-            "\"{:x}\"".format(carry_8)
-        ]
-
-    @classmethod
-    def get_value_pairs(cls) -> Iterator[Tuple[str, str]]:
-        """Generator to yield pairs of inputs.
-
-        Combinations are first generated from all input values, and then
-        specific cases provided.
-        """
-        yield from super().get_value_pairs()
-        yield from cls.input_cases
-
-    @classmethod
-    def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
-        """Override for additional scalar input."""
-        for a_value, b_value in cls.get_value_pairs():
-            for s_value in cls.input_scalars:
-                cur_op = cls(a_value, b_value, s_value)
-                yield cur_op.create_test_case()
-
-
-class BignumCoreMul(BignumCoreTarget, bignum_common.OperationCommon):
-    """Test cases for bignum core multiplication."""
-    count = 0
-    input_style = "arch_split"
-    symbol = "*"
-    test_function = "mpi_core_mul"
-    test_name = "mbedtls_mpi_core_mul"
-    arity = 2
-    unique_combinations_only = True
-
-    def format_arg(self, val: str) -> str:
-        return val
-
-    def format_result(self, res: int) -> str:
-        res_str = '{:x}'.format(res)
-        a_limbs = bignum_common.limbs_mpi(self.int_a, self.bits_in_limb)
-        b_limbs = bignum_common.limbs_mpi(self.int_b, self.bits_in_limb)
-        hex_digits = bignum_common.hex_digits_for_limb(a_limbs + b_limbs, self.bits_in_limb)
-        return bignum_common.quote_str(self.format_arg(res_str).zfill(hex_digits))
-
-    def result(self) -> List[str]:
-        result = self.int_a * self.int_b
-        return [self.format_result(result)]
-
-
-class BignumCoreMontmul(BignumCoreTarget, test_data_generation.BaseTest):
-    """Test cases for Montgomery multiplication."""
-    count = 0
-    test_function = "mpi_core_montmul"
-    test_name = "mbedtls_mpi_core_montmul"
-
-    start_2_mpi4 = False
-    start_2_mpi8 = False
-
-    replay_test_cases = [
-        (2, 1, 1, 1, "19", "1", "1D"), (2, 1, 1, 1, "7", "1", "9"),
-        (2, 1, 1, 1, "4", "1", "9"),
-        (
-            12, 1, 6, 1, (
-                "3C246D0E059A93A266288A7718419EC741661B474C58C032C5EDAF92709402"
-                "B07CC8C7CE0B781C641A1EA8DB2F4343"
-            ), "1", (
-                "66A198186C18C10B2F5ED9B522752A9830B69916E535C8F047518A889A43A5"
-                "94B6BED27A168D31D4A52F88925AA8F5"
-            )
-        ), (
-            8, 1, 4, 1,
-            "1E442976B0E63D64FCCE74B999E470CA9888165CB75BFA1F340E918CE03C6211",
-            "1", "B3A119602EE213CDE28581ECD892E0F592A338655DCE4CA88054B3D124D0E561"
-        ), (
-            22, 1, 11, 1, (
-                "7CF5AC97304E0B63C65413F57249F59994B0FED1D2A8D3D83ED5FA38560FFB"
-                "82392870D6D08F87D711917FD7537E13B7E125BE407E74157776839B0AC9DB"
-                "23CBDFC696104353E4D2780B2B4968F8D8542306BCA7A2366E"
-            ), "1", (
-                "284139EA19C139EBE09A8111926AAA39A2C2BE12ED487A809D3CB5BC558547"
-                "25B4CDCB5734C58F90B2F60D99CC1950CDBC8D651793E93C9C6F0EAD752500"
-                "A32C56C62082912B66132B2A6AA42ADA923E1AD22CEB7BA0123"
-            )
-        )
-    ] # type: List[Tuple[int, int, int, int, str, str, str]]
-
-    random_test_cases = [
-        ("2", "2", "3", ""), ("1", "2", "3", ""), ("2", "1", "3", ""),
-        ("6", "5", "7", ""), ("3", "4", "7", ""), ("1", "6", "7", ""), ("5", "6", "7", ""),
-        ("3", "4", "B", ""), ("7", "4", "B", ""), ("9", "7", "B", ""), ("2", "a", "B", ""),
-        ("25", "16", "29", "(0x29 is prime)"), ("8", "28", "29", ""),
-        ("18", "21", "29", ""), ("15", "f", "29", ""),
-        ("e2", "ea", "FF", ""), ("43", "72", "FF", ""),
-        ("d8", "70", "FF", ""), ("3c", "7c", "FF", ""),
-        ("99", "b9", "101", "(0x101 is prime)"), ("65", "b2", "101", ""),
-        ("81", "32", "101", ""), ("51", "dd", "101", ""),
-        ("d5", "143", "38B", "(0x38B is prime)"), ("3d", "387", "38B", ""),
-        ("160", "2e5", "38B", ""), ("10f", "137", "38B", ""),
-        ("7dac", "25a", "8003", "(0x8003 is prime)"), ("6f1c", "3286", "8003", ""),
-        ("59ed", "2f3f", "8003", ""), ("6893", "736d", "8003", ""),
-        ("d199", "2832", "10001", "(0x10001 is prime)"), ("c3b2", "3e5b", "10001", ""),
-        ("abe4", "214e", "10001", ""), ("4360", "a05d", "10001", ""),
-        ("3f5a1", "165b2", "7F7F7", ""), ("3bd29", "37863", "7F7F7", ""),
-        ("60c47", "64819", "7F7F7", ""), ("16584", "12c49", "7F7F7", ""),
-        ("1ff03f", "610347", "800009", "(0x800009 is prime)"), ("340fd5", "19812e", "800009", ""),
-        ("3fe2e8", "4d0dc7", "800009", ""), ("40356", "e6392", "800009", ""),
-        ("dd8a1d", "266c0e", "100002B", "(0x100002B is prime)"),
-        ("3fa1cb", "847fd6", "100002B", ""), ("5f439d", "5c3196", "100002B", ""),
-        ("18d645", "f72dc6", "100002B", ""),
-        ("20051ad", "37def6e", "37EEE9D", "(0x37EEE9D is prime)"),
-        ("2ec140b", "3580dbf", "37EEE9D", ""), ("1d91b46", "190d4fc", "37EEE9D", ""),
-        ("34e488d", "1224d24", "37EEE9D", ""),
-        ("2a4fe2cb", "263466a9", "8000000B", "(0x8000000B is prime)"),
-        ("5643fe94", "29a1aefa", "8000000B", ""), ("29633513", "7b007ac4", "8000000B", ""),
-        ("2439cef5", "5c9d5a47", "8000000B", ""),
-        ("4de3cfaa", "50dea178", "8CD626B9", "(0x8CD626B9 is prime)"),
-        ("b8b8563", "10dbbbac", "8CD626B9", ""), ("4e8a6151", "5574ec19", "8CD626B9", ""),
-        ("69224878", "309cfc23", "8CD626B9", ""),
-        ("fb6f7fb6", "afb05423", "10000000F", "(0x10000000F is prime)"),
-        ("8391a243", "26034dcd", "10000000F", ""), ("d26b98c", "14b2d6aa", "10000000F", ""),
-        ("6b9f1371", "a21daf1d", "10000000F", ""),
-        (
-            "9f49435ad", "c8264ade8", "174876E7E9",
-            "0x174876E7E9 is prime (dec) 99999999977"
-        ),
-        ("c402da434", "1fb427acf", "174876E7E9", ""),
-        ("f6ebc2bb1", "1096d39f2a", "174876E7E9", ""),
-        ("153b7f7b6b", "878fda8ff", "174876E7E9", ""),
-        ("2c1adbb8d6", "4384d2d3c6", "8000000017", "(0x8000000017 is prime)"),
-        ("2e4f9cf5fb", "794f3443d9", "8000000017", ""),
-        ("149e495582", "3802b8f7b7", "8000000017", ""),
-        ("7b9d49df82", "69c68a442a", "8000000017", ""),
-        ("683a134600", "6dd80ea9f6", "864CB9076D", "(0x864CB9076D is prime)"),
-        ("13a870ff0d", "59b099694a", "864CB9076D", ""),
-        ("37d06b0e63", "4d2147e46f", "864CB9076D", ""),
-        ("661714f8f4", "22e55df507", "864CB9076D", ""),
-        ("2f0a96363", "52693307b4", "F7F7F7F7F7", ""),
-        ("3c85078e64", "f2275ecb6d", "F7F7F7F7F7", ""),
-        ("352dae68d1", "707775b4c6", "F7F7F7F7F7", ""),
-        ("37ae0f3e0b", "912113040f", "F7F7F7F7F7", ""),
-        ("6dada15e31", "f58ed9eff7", "1000000000F", "(0x1000000000F is prime)"),
-        ("69627a7c89", "cfb5ebd13d", "1000000000F", ""),
-        ("a5e1ad239b", "afc030c731", "1000000000F", ""),
-        ("f1cc45f4c5", "c64ad607c8", "1000000000F", ""),
-        ("2ebad87d2e31", "4c72d90bca78", "800000000005", "(0x800000000005 is prime)"),
-        ("a30b3cc50d", "29ac4fe59490", "800000000005", ""),
-        ("33674e9647b4", "5ec7ee7e72d3", "800000000005", ""),
-        ("3d956f474f61", "74070040257d", "800000000005", ""),
-        ("48348e3717d6", "43fcb4399571", "800795D9BA47", "(0x800795D9BA47 is prime)"),
-        ("5234c03cc99b", "2f3cccb87803", "800795D9BA47", ""),
-        ("3ed13db194ab", "44b8f4ba7030", "800795D9BA47", ""),
-        ("1c11e843bfdb", "95bd1b47b08", "800795D9BA47", ""),
-        ("a81d11cb81fd", "1e5753a3f33d", "1000000000015", "(0x1000000000015 is prime)"),
-        ("688c4db99232", "36fc0cf7ed", "1000000000015", ""),
-        ("f0720cc07e07", "fc76140ed903", "1000000000015", ""),
-        ("2ec61f8d17d1", "d270c85e36d2", "1000000000015", ""),
-        (
-            "6a24cd3ab63820", "ed4aad55e5e348", "100000000000051",
-            "(0x100000000000051 is prime)"
-        ),
-        ("e680c160d3b248", "31e0d8840ed510", "100000000000051", ""),
-        ("a80637e9aebc38", "bb81decc4e1738", "100000000000051", ""),
-        ("9afa5a59e9d630", "be9e65a6d42938", "100000000000051", ""),
-        ("ab5e104eeb71c000", "2cffbd639e9fea00", "ABCDEF0123456789", ""),
-        ("197b867547f68a00", "44b796cf94654800", "ABCDEF0123456789", ""),
-        ("329f9483a04f2c00", "9892f76961d0f000", "ABCDEF0123456789", ""),
-        ("4a2e12dfb4545000", "1aa3e89a69794500", "ABCDEF0123456789", ""),
-        (
-            "8b9acdf013d140f000", "12e4ceaefabdf2b2f00", "25A55A46E5DA99C71C7",
-            "0x25A55A46E5DA99C71C7 is the 3rd repunit prime(dec) 11111111111111111111111"
-        ),
-        ("1b8d960ea277e3f5500", "14418aa980e37dd000", "25A55A46E5DA99C71C7", ""),
-        ("7314524977e8075980", "8172fa45618ccd0d80", "25A55A46E5DA99C71C7", ""),
-        ("ca14f031769be63580", "147a2f3cf2964ca9400", "25A55A46E5DA99C71C7", ""),
-        (
-            "18532ba119d5cd0cf39735c0000", "25f9838e31634844924733000000",
-            "314DC643FB763F2B8C0E2DE00879",
-            "0x314DC643FB763F2B8C0E2DE00879 is (dec)99999999977^3"
-        ),
-        (
-            "a56e2d2517519e3970e70c40000", "ec27428d4bb380458588fa80000",
-            "314DC643FB763F2B8C0E2DE00879", ""
-        ),
-        (
-            "1cb5e8257710e8653fff33a00000", "15fdd42fe440fd3a1d121380000",
-            "314DC643FB763F2B8C0E2DE00879", ""
-        ),
-        (
-            "e50d07a65fc6f93e538ce040000", "1f4b059ca609f3ce597f61240000",
-            "314DC643FB763F2B8C0E2DE00879", ""
-        ),
-        (
-            "1ea3ade786a095d978d387f30df9f20000000",
-            "127c448575f04af5a367a7be06c7da0000000",
-            "47BF19662275FA2F6845C74942ED1D852E521",
-            "0x47BF19662275FA2F6845C74942ED1D852E521 is (dec) 99999999977^4"
-        ),
-        (
-            "16e15b0ca82764e72e38357b1f10a20000000",
-            "43e2355d8514bbe22b0838fdc3983a0000000",
-            "47BF19662275FA2F6845C74942ED1D852E521", ""
-        ),
-        (
-            "be39332529d93f25c3d116c004c620000000",
-            "5cccec42370a0a2c89c6772da801a0000000",
-            "47BF19662275FA2F6845C74942ED1D852E521", ""
-        ),
-        (
-            "ecaa468d90de0eeda474d39b3e1fc0000000",
-            "1e714554018de6dc0fe576bfd3b5660000000",
-            "47BF19662275FA2F6845C74942ED1D852E521", ""
-        ),
-        (
-            "32298816711c5dce46f9ba06e775c4bedfc770e6700000000000000",
-            "8ee751fd5fb24f0b4a653cb3a0c8b7d9e724574d168000000000000",
-            "97EDD86E4B5C4592C6D32064AC55C888A7245F07CA3CC455E07C931",
-            (
-                "0x97EDD86E4B5C4592C6D32064AC55C888A7245F07CA3CC455E07C931"
-                " is (dec) 99999999977^6"
-            )
-        ),
-        (
-            "29213b9df3cfd15f4b428645b67b677c29d1378d810000000000000",
-            "6cbb732c65e10a28872394dfdd1936d5171c3c3aac0000000000000",
-            "97EDD86E4B5C4592C6D32064AC55C888A7245F07CA3CC455E07C931", ""
-        ),
-        (
-            "6f18db06ad4abc52c0c50643dd13098abccd4a232f0000000000000",
-            "7e6bf41f2a86098ad51f98dfc10490ba3e8081bc830000000000000",
-            "97EDD86E4B5C4592C6D32064AC55C888A7245F07CA3CC455E07C931", ""
-        ),
-        (
-            "62d3286cd706ad9d73caff63f1722775d7e8c731208000000000000",
-            "530f7ba02ae2b04c2fe3e3d27ec095925631a6c2528000000000000",
-            "97EDD86E4B5C4592C6D32064AC55C888A7245F07CA3CC455E07C931", ""
-        ),
-        (
-            "a6c6503e3c031fdbf6009a89ed60582b7233c5a85de28b16000000000000000",
-            "75c8ed18270b583f16d442a467d32bf95c5e491e9b8523798000000000000000",
-            "DD15FE80B731872AC104DB37832F7E75A244AA2631BC87885B861E8F20375499",
-            (
-                "0xDD15FE80B731872AC104DB37832F7E75A244AA2631BC87885B861E8F20375499"
-                " is (dec) 99999999977^7"
-            )
-        ),
-        (
-            "bf84d1f85cf6b51e04d2c8f4ffd03532d852053cf99b387d4000000000000000",
-            "397ba5a743c349f4f28bc583ecd5f06e0a25f9c6d98f09134000000000000000",
-            "DD15FE80B731872AC104DB37832F7E75A244AA2631BC87885B861E8F20375499", ""
-        ),
-        (
-            "6db11c3a4152ed1a2aa6fa34b0903ec82ea1b88908dcb482000000000000000",
-            "ac8ac576a74ad6ca48f201bf89f77350ce86e821358d85920000000000000000",
-            "DD15FE80B731872AC104DB37832F7E75A244AA2631BC87885B861E8F20375499", ""
-        ),
-        (
-            "3001d96d7fe8b733f33687646fc3017e3ac417eb32e0ec708000000000000000",
-            "925ddbdac4174e8321a48a32f79640e8cf7ec6f46ea235a80000000000000000",
-            "DD15FE80B731872AC104DB37832F7E75A244AA2631BC87885B861E8F20375499", ""
-        ),
-        (
-            "1029048755f2e60dd98c8de6d9989226b6bb4f0db8e46bd1939de560000000000000000000",
-            "51bb7270b2e25cec0301a03e8275213bb6c2f6e6ec93d4d46d36ca0000000000000000000",
-            "141B8EBD9009F84C241879A1F680FACCED355DA36C498F73E96E880CF78EA5F96146380E41",
-            (
-                "0x141B8EBD9009F84C241879A1F680FACCED355DA36C498F73E96E880CF78EA5F96146"
-                "380E41 is 99999999977^8"
-            )
-        ),
-        (
-            "1c5337ff982b3ad6611257dbff5bbd7a9920ba2d4f5838a0cc681ce000000000000000000",
-            "520c5d049ca4702031ba728591b665c4d4ccd3b2b86864d4c160fd2000000000000000000",
-            "141B8EBD9009F84C241879A1F680FACCED355DA36C498F73E96E880CF78EA5F96146380E41",
-            ""
-        ),
-        (
-            "57074dfa00e42f6555bae624b7f0209f218adf57f73ed34ab0ff90c000000000000000000",
-            "41eb14b6c07bfd3d1fe4f4a610c17cc44fcfcda695db040e011065000000000000000000",
-            "141B8EBD9009F84C241879A1F680FACCED355DA36C498F73E96E880CF78EA5F96146380E41",
-            ""
-        ),
-        (
-            "d8ed7feed2fe855e6997ad6397f776158573d425031bf085a615784000000000000000000",
-            "6f121dcd18c578ab5e229881006007bb6d319b179f11015fe958b9c000000000000000000",
-            "141B8EBD9009F84C241879A1F680FACCED355DA36C498F73E96E880CF78EA5F96146380E41",
-            ""
-        ),
-        (
-            (
-                "2a462b156180ea5fe550d3758c764e06fae54e626b5f503265a09df76edbdfbf"
-                "a1e6000000000000000000000000"
-            ), (
-                "1136f41d1879fd4fb9e49e0943a46b6704d77c068ee237c3121f9071cfd3e6a0"
-                "0315800000000000000000000000"
-            ), (
-                "2A94608DE88B6D5E9F8920F5ABB06B24CC35AE1FBACC87D075C621C3E2833EC90"
-                "2713E40F51E3B3C214EDFABC451"
-            ), (
-                "0x2A94608DE88B6D5E9F8920F5ABB06B24CC35AE1FBACC87D075C621C3E2833EC"
-                "902713E40F51E3B3C214EDFABC451 is (dec) 99999999977^10"
-            )
-        ),
-        (
-            (
-                "c1ac3800dfb3c6954dea391d206200cf3c47f795bf4a5603b4cb88ae7e574de47"
-                "40800000000000000000000000"
-            ), (
-                "c0d16eda0549ede42fa0deb4635f7b7ce061fadea02ee4d85cba4c4f709603419"
-                "3c800000000000000000000000"
-            ), (
-                "2A94608DE88B6D5E9F8920F5ABB06B24CC35AE1FBACC87D075C621C3E2833EC90"
-                "2713E40F51E3B3C214EDFABC451"
-            ), ""
-        ),
-        (
-            (
-                "19e45bb7633094d272588ad2e43bcb3ee341991c6731b6fa9d47c4018d7ce7bba"
-                "5ee800000000000000000000000"
-            ), (
-                "1e4f83166ae59f6b9cc8fd3e7677ed8bfc01bb99c98bd3eb084246b64c1e18c33"
-                "65b800000000000000000000000"
-            ), (
-                "2A94608DE88B6D5E9F8920F5ABB06B24CC35AE1FBACC87D075C621C3E2833EC90"
-                "2713E40F51E3B3C214EDFABC451"
-            ), ""
-        ),
-        (
-            (
-                "1aa93395fad5f9b7f20b8f9028a054c0bb7c11bb8520e6a95e5a34f06cb70bcdd"
-                "01a800000000000000000000000"
-            ), (
-                "54b45afa5d4310192f8d224634242dd7dcfb342318df3d9bd37b4c614788ba13b"
-                "8b000000000000000000000000"
-            ), (
-                "2A94608DE88B6D5E9F8920F5ABB06B24CC35AE1FBACC87D075C621C3E2833EC90"
-                "2713E40F51E3B3C214EDFABC451"
-            ), ""
-        ),
-        (
-            (
-                "544f2628a28cfb5ce0a1b7180ee66b49716f1d9476c466c57f0c4b23089917843"
-                "06d48f78686115ee19e25400000000000000000000000000000000"
-            ), (
-                "677eb31ef8d66c120fa872a60cd47f6e10cbfdf94f90501bd7883cba03d185be0"
-                "a0148d1625745e9c4c827300000000000000000000000000000000"
-            ), (
-                "8335616AED761F1F7F44E6BD49E807B82E3BF2BF11BFA6AF813C808DBF33DBFA1"
-                "1DABD6E6144BEF37C6800000000000000000000000000000000051"
-            ), (
-                "0x8335616AED761F1F7F44E6BD49E807B82E3BF2BF11BFA6AF813C808DBF33DBF"
-                "A11DABD6E6144BEF37C6800000000000000000000000000000000051 is prime,"
-                " (dec) 10^143 + 3^4"
-            )
-        ),
-        (
-            (
-                "76bb3470985174915e9993522aec989666908f9e8cf5cb9f037bf4aee33d8865c"
-                "b6464174795d07e30015b80000000000000000000000000000000"
-            ), (
-                "6aaaf60d5784dcef612d133613b179a317532ecca0eed40b8ad0c01e6d4a6d8c7"
-                "9a52af190abd51739009a900000000000000000000000000000000"
-            ), (
-                "8335616AED761F1F7F44E6BD49E807B82E3BF2BF11BFA6AF813C808DBF33DBFA1"
-                "1DABD6E6144BEF37C6800000000000000000000000000000000051"
-            ), ""
-        ),
-        (
-            (
-                "6cfdd6e60912e441d2d1fc88f421b533f0103a5322ccd3f4db84861643ad63fd6"
-                "3d1d8cfbc1d498162786ba00000000000000000000000000000000"
-            ), (
-                "1177246ec5e93814816465e7f8f248b350d954439d35b2b5d75d917218e7fd5fb"
-                "4c2f6d0667f9467fdcf33400000000000000000000000000000000"
-            ), (
-                "8335616AED761F1F7F44E6BD49E807B82E3BF2BF11BFA6AF813C808DBF33DBFA1"
-                "1DABD6E6144BEF37C6800000000000000000000000000000000051"
-            ), ""
-        ),
-        (
-            (
-                "7a09a0b0f8bbf8057116fb0277a9bdf3a91b5eaa8830d448081510d8973888be5"
-                "a9f0ad04facb69aa3715f00000000000000000000000000000000"
-            ), (
-                "764dec6c05a1c0d87b649efa5fd94c91ea28bffb4725d4ab4b33f1a3e8e3b314d"
-                "799020e244a835a145ec9800000000000000000000000000000000"
-            ), (
-                "8335616AED761F1F7F44E6BD49E807B82E3BF2BF11BFA6AF813C808DBF33DBFA1"
-                "1DABD6E6144BEF37C6800000000000000000000000000000000051"
-            ), ""
-        )
-    ] # type: List[Tuple[str, str, str, str]]
-
-    def __init__(
-            self, val_a: str, val_b: str, val_n: str, case_description: str = ""
-        ):
-        self.case_description = case_description
-        self.arg_a = val_a
-        self.int_a = bignum_common.hex_to_int(val_a)
-        self.arg_b = val_b
-        self.int_b = bignum_common.hex_to_int(val_b)
-        self.arg_n = val_n
-        self.int_n = bignum_common.hex_to_int(val_n)
-
-        limbs_a4 = bignum_common.limbs_mpi(self.int_a, 32)
-        limbs_a8 = bignum_common.limbs_mpi(self.int_a, 64)
-        self.limbs_b4 = bignum_common.limbs_mpi(self.int_b, 32)
-        self.limbs_b8 = bignum_common.limbs_mpi(self.int_b, 64)
-        self.limbs_an4 = bignum_common.limbs_mpi(self.int_n, 32)
-        self.limbs_an8 = bignum_common.limbs_mpi(self.int_n, 64)
-
-        if limbs_a4 > self.limbs_an4 or limbs_a8 > self.limbs_an8:
-            raise Exception("Limbs of input A ({}) exceeds N ({})".format(
-                self.arg_a, self.arg_n
-            ))
-
-    def arguments(self) -> List[str]:
-        return [
-            str(self.limbs_an4), str(self.limbs_b4),
-            str(self.limbs_an8), str(self.limbs_b8),
-            bignum_common.quote_str(self.arg_a),
-            bignum_common.quote_str(self.arg_b),
-            bignum_common.quote_str(self.arg_n)
-        ] + self.result()
-
-    def description(self) -> str:
-        if self.case_description != "replay":
-            if not self.start_2_mpi4 and self.limbs_an4 > 1:
-                tmp = "(start of 2-MPI 4-byte bignums) "
-                self.__class__.start_2_mpi4 = True
-            elif not self.start_2_mpi8 and self.limbs_an8 > 1:
-                tmp = "(start of 2-MPI 8-byte bignums) "
-                self.__class__.start_2_mpi8 = True
-            else:
-                tmp = "(gen) "
-            self.case_description = tmp + self.case_description
-        return super().description()
-
-    def result(self) -> List[str]:
-        """Get the result of the operation."""
-        r4 = bignum_common.bound_mpi_limbs(self.limbs_an4, 32)
-        i4 = bignum_common.invmod(r4, self.int_n)
-        x4 = self.int_a * self.int_b * i4
-        x4 = x4 % self.int_n
-
-        r8 = bignum_common.bound_mpi_limbs(self.limbs_an8, 64)
-        i8 = bignum_common.invmod(r8, self.int_n)
-        x8 = self.int_a * self.int_b * i8
-        x8 = x8 % self.int_n
-        return [
-            "\"{:x}\"".format(x4),
-            "\"{:x}\"".format(x8)
-        ]
-
-    def set_limbs(
-            self, limbs_an4: int, limbs_b4: int, limbs_an8: int, limbs_b8: int
-        ) -> None:
-        """Set number of limbs for each input.
-
-        Replaces default values set during initialization.
-        """
-        self.limbs_an4 = limbs_an4
-        self.limbs_b4 = limbs_b4
-        self.limbs_an8 = limbs_an8
-        self.limbs_b8 = limbs_b8
-
-    @classmethod
-    def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
-        """Generate replay and randomly generated test cases."""
-        # Test cases which replay captured invocations during unit test runs.
-        for limbs_an4, limbs_b4, limbs_an8, limbs_b8, a, b, n in cls.replay_test_cases:
-            cur_op = cls(a, b, n, case_description="replay")
-            cur_op.set_limbs(limbs_an4, limbs_b4, limbs_an8, limbs_b8)
-            yield cur_op.create_test_case()
-        # Random test cases can be generated using mpi_modmul_case_generate()
-        # Uses a mixture of primes and odd numbers as N, with four randomly
-        # generated cases for each N.
-        for a, b, n, description in cls.random_test_cases:
-            cur_op = cls(a, b, n, case_description=description)
-            yield cur_op.create_test_case()
-
-
-def mpi_modmul_case_generate() -> None:
-    """Generate valid inputs for montmul tests using moduli.
-
-    For each modulus, generates random values for A and B and simple descriptions
-    for the test case.
-    """
-    moduli = [
-        ("3", ""), ("7", ""), ("B", ""), ("29", ""), ("FF", ""),
-        ("101", ""), ("38B", ""), ("8003", ""), ("10001", ""),
-        ("7F7F7", ""), ("800009", ""), ("100002B", ""), ("37EEE9D", ""),
-        ("8000000B", ""), ("8CD626B9", ""), ("10000000F", ""),
-        ("174876E7E9", "is prime (dec) 99999999977"),
-        ("8000000017", ""), ("864CB9076D", ""), ("F7F7F7F7F7", ""),
-        ("1000000000F", ""), ("800000000005", ""), ("800795D9BA47", ""),
-        ("1000000000015", ""), ("100000000000051", ""), ("ABCDEF0123456789", ""),
-        (
-            "25A55A46E5DA99C71C7",
-            "is the 3rd repunit prime (dec) 11111111111111111111111"
-        ),
-        ("314DC643FB763F2B8C0E2DE00879", "is (dec)99999999977^3"),
-        ("47BF19662275FA2F6845C74942ED1D852E521", "is (dec) 99999999977^4"),
-        (
-            "97EDD86E4B5C4592C6D32064AC55C888A7245F07CA3CC455E07C931",
-            "is (dec) 99999999977^6"
-        ),
-        (
-            "DD15FE80B731872AC104DB37832F7E75A244AA2631BC87885B861E8F20375499",
-            "is (dec) 99999999977^7"
-        ),
-        (
-            "141B8EBD9009F84C241879A1F680FACCED355DA36C498F73E96E880CF78EA5F96146380E41",
-            "is (dec) 99999999977^8"
-        ),
-        (
-            (
-                "2A94608DE88B6D5E9F8920F5ABB06B24CC35AE1FBACC87D075C621C3E283"
-                "3EC902713E40F51E3B3C214EDFABC451"
-            ),
-            "is (dec) 99999999977^10"
-        ),
-        (
-            "8335616AED761F1F7F44E6BD49E807B82E3BF2BF11BFA6AF813C808DBF33DBFA11"
-            "DABD6E6144BEF37C6800000000000000000000000000000000051",
-            "is prime, (dec) 10^143 + 3^4"
-        )
-    ] # type: List[Tuple[str, str]]
-    primes = [
-        "3", "7", "B", "29", "101", "38B", "8003", "10001", "800009",
-        "100002B", "37EEE9D", "8000000B", "8CD626B9",
-        # From here they require > 1 4-byte MPI
-        "10000000F", "174876E7E9", "8000000017", "864CB9076D", "1000000000F",
-        "800000000005", "800795D9BA47", "1000000000015", "100000000000051",
-        # From here they require > 1 8-byte MPI
-        "25A55A46E5DA99C71C7",      # this is 11111111111111111111111 decimal
-        # 10^143 + 3^4: (which is prime)
-        # 100000000000000000000000000000000000000000000000000000000000000000000000000000
-        # 000000000000000000000000000000000000000000000000000000000000000081
-        (
-            "8335616AED761F1F7F44E6BD49E807B82E3BF2BF11BFA6AF813C808DBF33DBFA11"
-            "DABD6E6144BEF37C6800000000000000000000000000000000051"
-        )
-    ] # type: List[str]
-    generated_inputs = []
-    for mod, description in moduli:
-        n = bignum_common.hex_to_int(mod)
-        mod_read = "{:x}".format(n)
-        case_count = 3 if n < 5 else 4
-        cases = {} # type: Dict[int, int]
-        i = 0
-        while i < case_count:
-            a = random.randint(1, n)
-            b = random.randint(1, n)
-            if cases.get(a) == b:
-                continue
-            cases[a] = b
-            if description:
-                out_description = "0x{} {}".format(mod_read, description)
-            elif i == 0 and len(mod) > 1 and mod in primes:
-                out_description = "(0x{} is prime)"
-            else:
-                out_description = ""
-            generated_inputs.append(
-                ("{:x}".format(a), "{:x}".format(b), mod, out_description)
-            )
-            i += 1
-    print(generated_inputs)
-
-
-class BignumCoreExpMod(BignumCoreTarget, bignum_common.ModOperationCommon):
-    """Test cases for bignum core exponentiation."""
-    symbol = "^"
-    test_function = "mpi_core_exp_mod"
-    test_name = "Core modular exponentiation (Mongtomery form only)"
-    input_style = "fixed"
-    montgomery_form_a = True
-
-    def result(self) -> List[str]:
-        # Result has to be given in Montgomery form too
-        result = pow(self.int_a, self.int_b, self.int_n)
-        mont_result = self.to_montgomery(result)
-        return [self.format_result(mont_result)]
-
-    @property
-    def is_valid(self) -> bool:
-        # The base needs to be canonical, but the exponent can be larger than
-        # the modulus (see for example exponent blinding)
-        return bool(self.int_a < self.int_n)
-
-
-class BignumCoreSubInt(BignumCoreTarget, bignum_common.OperationCommon):
-    """Test cases for bignum core sub int."""
-    count = 0
-    symbol = "-"
-    test_function = "mpi_core_sub_int"
-    test_name = "mpi_core_sub_int"
-    input_style = "arch_split"
-
-    @property
-    def is_valid(self) -> bool:
-        # This is "sub int", so b is only one limb
-        if bignum_common.limbs_mpi(self.int_b, self.bits_in_limb) > 1:
-            return False
-        return True
-
-    # Overriding because we don't want leading zeros on b
-    @property
-    def arg_b(self) -> str:
-        return self.val_b
-
-    def result(self) -> List[str]:
-        result = self.int_a - self.int_b
-
-        borrow, result = divmod(result, self.limb_boundary)
-
-        # Borrow will be -1 if non-zero, but we want it to be 1 in the test data
-        return [
-            self.format_result(result),
-            str(-borrow)
-        ]
-
-class BignumCoreZeroCheckCT(BignumCoreTarget, bignum_common.OperationCommon):
-    """Test cases for bignum core zero check (constant flow)."""
-    count = 0
-    symbol = "== 0"
-    test_function = "mpi_core_check_zero_ct"
-    test_name = "mpi_core_check_zero_ct"
-    input_style = "variable"
-    arity = 1
-    suffix = True
-
-    def result(self) -> List[str]:
-        result = 1 if self.int_a == 0 else 0
-        return [str(result)]
diff --git a/scripts/mbedtls_dev/bignum_data.py b/scripts/mbedtls_dev/bignum_data.py
deleted file mode 100644
index 5c6c2c8..0000000
--- a/scripts/mbedtls_dev/bignum_data.py
+++ /dev/null
@@ -1,159 +0,0 @@
-"""Base values and datasets for bignum generated tests and helper functions that
-produced them."""
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-import random
-
-# Functions calling these were used to produce test data and are here only for
-# reproducibility, they are not used by the test generation framework/classes
-try:
-    from Cryptodome.Util.number import isPrime, getPrime #type: ignore #pylint: disable=import-error
-except ImportError:
-    pass
-
-# Generated by bignum_common.gen_safe_prime(192,1)
-SAFE_PRIME_192_BIT_SEED_1 = "d1c127a667786703830500038ebaef20e5a3e2dc378fb75b"
-
-# First number generated by random.getrandbits(192) - seed(2,2), not a prime
-RANDOM_192_BIT_SEED_2_NO1 = "177219d30e7a269fd95bafc8f2a4d27bdcf4bb99f4bea973"
-
-# Second number generated by random.getrandbits(192) - seed(2,2), not a prime
-RANDOM_192_BIT_SEED_2_NO2 = "cf1822ffbc6887782b491044d5e341245c6e433715ba2bdd"
-
-# Third number generated by random.getrandbits(192) - seed(2,2), not a prime
-RANDOM_192_BIT_SEED_2_NO3 = "3653f8dd9b1f282e4067c3584ee207f8da94e3e8ab73738f"
-
-# Fourth number generated by random.getrandbits(192) - seed(2,2), not a prime
-RANDOM_192_BIT_SEED_2_NO4 = "ffed9235288bc781ae66267594c9c9500925e4749b575bd1"
-
-# Ninth number generated by random.getrandbits(192) - seed(2,2), not a prime
-RANDOM_192_BIT_SEED_2_NO9 = "2a1be9cd8697bbd0e2520e33e44c50556c71c4a66148a86f"
-
-# Generated by bignum_common.gen_safe_prime(1024,3)
-SAFE_PRIME_1024_BIT_SEED_3 = ("c93ba7ec74d96f411ba008bdb78e63ff11bb5df46a51e16b"
-                              "2c9d156f8e4e18abf5e052cb01f47d0d1925a77f60991577"
-                              "e128fb6f52f34a27950a594baadd3d8057abeb222cf3cca9"
-                              "62db16abf79f2ada5bd29ab2f51244bf295eff9f6aaba130"
-                              "2efc449b128be75eeaca04bc3c1a155d11d14e8be32a2c82"
-                              "87b3996cf6ad5223")
-
-# First number generated by random.getrandbits(1024) - seed(4,2), not a prime
-RANDOM_1024_BIT_SEED_4_NO1 = ("6905269ed6f0b09f165c8ce36e2f24b43000de01b2ed40ed"
-                              "3addccb2c33be0ac79d679346d4ac7a5c3902b38963dc6e8"
-                              "534f45738d048ec0f1099c6c3e1b258fd724452ccea71ff4"
-                              "a14876aeaff1a098ca5996666ceab360512bd13110722311"
-                              "710cf5327ac435a7a97c643656412a9b8a1abcd1a6916c74"
-                              "da4f9fc3c6da5d7")
-
-# Second number generated by random.getrandbits(1024) - seed(4,2), not a prime
-RANDOM_1024_BIT_SEED_4_NO2 = ("f1cfd99216df648647adec26793d0e453f5082492d83a823"
-                              "3fb62d2c81862fc9634f806fabf4a07c566002249b191bf4"
-                              "d8441b5616332aca5f552773e14b0190d93936e1daca3c06"
-                              "f5ff0c03bb5d7385de08caa1a08179104a25e4664f5253a0"
-                              "2a3187853184ff27459142deccea264542a00403ce80c4b0"
-                              "a4042bb3d4341aad")
-
-# Third number generated by random.getrandbits(1024) - seed(4,2), not a prime
-RANDOM_1024_BIT_SEED_4_NO3 = ("14c15c910b11ad28cc21ce88d0060cc54278c2614e1bcb38"
-                              "3bb4a570294c4ea3738d243a6e58d5ca49c7b59b995253fd"
-                              "6c79a3de69f85e3131f3b9238224b122c3e4a892d9196ada"
-                              "4fcfa583e1df8af9b474c7e89286a1754abcb06ae8abb93f"
-                              "01d89a024cdce7a6d7288ff68c320f89f1347e0cdd905ecf"
-                              "d160c5d0ef412ed6")
-
-# Fourth number generated by random.getrandbits(1024) - seed(4,2), not a prime
-RANDOM_1024_BIT_SEED_4_NO4 = ("32decd6b8efbc170a26a25c852175b7a96b98b5fbf37a2be"
-                              "6f98bca35b17b9662f0733c846bbe9e870ef55b1a1f65507"
-                              "a2909cb633e238b4e9dd38b869ace91311021c9e32111ac1"
-                              "ac7cc4a4ff4dab102522d53857c49391b36cc9aa78a330a1"
-                              "a5e333cb88dcf94384d4cd1f47ca7883ff5a52f1a05885ac"
-                              "7671863c0bdbc23a")
-
-# Fifth number generated by random.getrandbits(1024) - seed(4,2), not a prime
-RANDOM_1024_BIT_SEED_4_NO5 = ("53be4721f5b9e1f5acdac615bc20f6264922b9ccf469aef8"
-                              "f6e7d078e55b85dd1525f363b281b8885b69dc230af5ac87"
-                              "0692b534758240df4a7a03052d733dcdef40af2e54c0ce68"
-                              "1f44ebd13cc75f3edcb285f89d8cf4d4950b16ffc3e1ac3b"
-                              "4708d9893a973000b54a23020fc5b043d6e4a51519d9c9cc"
-                              "52d32377e78131c1")
-
-# Adding 192 bit and 1024 bit numbers because these are the shortest required
-# for ECC and RSA respectively.
-INPUTS_DEFAULT = [
-        "0", "1", # corner cases
-        "2", "3", # small primes
-        "4",      # non-prime even
-        "38",     # small random
-        SAFE_PRIME_192_BIT_SEED_1,  # prime
-        RANDOM_192_BIT_SEED_2_NO1,  # not a prime
-        RANDOM_192_BIT_SEED_2_NO2,  # not a prime
-        SAFE_PRIME_1024_BIT_SEED_3, # prime
-        RANDOM_1024_BIT_SEED_4_NO1, # not a prime
-        RANDOM_1024_BIT_SEED_4_NO3, # not a prime
-        RANDOM_1024_BIT_SEED_4_NO2, # largest (not a prime)
-        ]
-
-ADD_SUB_DATA = [
-    "0", "1", "3", "f", "fe", "ff", "100", "ff00",
-    "fffe", "ffff", "10000", # 2^16 - 1, 2^16, 2^16 + 1
-    "fffffffe", "ffffffff", "100000000", # 2^32 - 1, 2^32, 2^32 + 1
-    "1f7f7f7f7f7f7f",
-    "8000000000000000", "fefefefefefefefe",
-    "fffffffffffffffe", "ffffffffffffffff", "10000000000000000", # 2^64 - 1, 2^64, 2^64 + 1
-    "1234567890abcdef0",
-    "fffffffffffffffffffffffe",
-    "ffffffffffffffffffffffff",
-    "1000000000000000000000000",
-    "fffffffffffffffffefefefefefefefe",
-    "fffffffffffffffffffffffffffffffe",
-    "ffffffffffffffffffffffffffffffff",
-    "100000000000000000000000000000000",
-    "1234567890abcdef01234567890abcdef0",
-    "fffffffffffffffffffffffffffffffffffffffffffffffffefefefefefefefe",
-    "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
-    "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
-    "10000000000000000000000000000000000000000000000000000000000000000",
-    "1234567890abcdef01234567890abcdef01234567890abcdef01234567890abcdef0",
-    ]
-
-# Only odd moduli are present as in the new bignum code only odd moduli are
-# supported for now.
-MODULI_DEFAULT = [
-        "53", # safe prime
-        "45", # non-prime
-        SAFE_PRIME_192_BIT_SEED_1,  # safe prime
-        RANDOM_192_BIT_SEED_2_NO4,  # not a prime
-        SAFE_PRIME_1024_BIT_SEED_3, # safe prime
-        RANDOM_1024_BIT_SEED_4_NO5, # not a prime
-        ]
-
-# Some functions, e.g. mbedtls_mpi_mod_raw_inv_prime(), only support prime moduli.
-ONLY_PRIME_MODULI = [
-        "53", # safe prime
-        "8ac72304057392b5",     # 9999999997777777333 (longer, not safe, prime)
-        # The next prime has a different R in Montgomery form depending on
-        # whether 32- or 64-bit MPIs are used.
-        "152d02c7e14af67fe0bf", # 99999999999999999991999
-        SAFE_PRIME_192_BIT_SEED_1,  # safe prime
-        SAFE_PRIME_1024_BIT_SEED_3, # safe prime
-        ]
-
-def __gen_safe_prime(bits, seed):
-    '''
-    Generate a safe prime.
-
-    This function is intended for generating constants offline and shouldn't be
-    used in test generation classes.
-
-    Requires pycryptodomex for getPrime and isPrime and python 3.9 or later for
-    randbytes.
-    '''
-    rng = random.Random()
-    # We want reproducibility across python versions
-    rng.seed(seed, version=2)
-    while True:
-        prime = 2*getPrime(bits-1, rng.randbytes)+1 #pylint: disable=no-member
-        if isPrime(prime, 1e-30):
-            return prime
diff --git a/scripts/mbedtls_dev/bignum_mod.py b/scripts/mbedtls_dev/bignum_mod.py
deleted file mode 100644
index f554001..0000000
--- a/scripts/mbedtls_dev/bignum_mod.py
+++ /dev/null
@@ -1,102 +0,0 @@
-"""Framework classes for generation of bignum mod test cases."""
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-from typing import Dict, List
-
-from . import test_data_generation
-from . import bignum_common
-from .bignum_data import ONLY_PRIME_MODULI
-
-class BignumModTarget(test_data_generation.BaseTarget):
-    #pylint: disable=abstract-method, too-few-public-methods
-    """Target for bignum mod test case generation."""
-    target_basename = 'test_suite_bignum_mod.generated'
-
-
-class BignumModMul(bignum_common.ModOperationCommon,
-                   BignumModTarget):
-    # pylint:disable=duplicate-code
-    """Test cases for bignum mpi_mod_mul()."""
-    symbol = "*"
-    test_function = "mpi_mod_mul"
-    test_name = "mbedtls_mpi_mod_mul"
-    input_style = "arch_split"
-    arity = 2
-
-    def arguments(self) -> List[str]:
-        return [self.format_result(self.to_montgomery(self.int_a)),
-                self.format_result(self.to_montgomery(self.int_b)),
-                bignum_common.quote_str(self.arg_n)
-               ] + self.result()
-
-    def result(self) -> List[str]:
-        result = (self.int_a * self.int_b) % self.int_n
-        return [self.format_result(self.to_montgomery(result))]
-
-
-class BignumModSub(bignum_common.ModOperationCommon, BignumModTarget):
-    """Test cases for bignum mpi_mod_sub()."""
-    symbol = "-"
-    test_function = "mpi_mod_sub"
-    test_name = "mbedtls_mpi_mod_sub"
-    input_style = "fixed"
-    arity = 2
-
-    def result(self) -> List[str]:
-        result = (self.int_a - self.int_b) % self.int_n
-        # To make negative tests easier, append 0 for success to the
-        # generated cases
-        return [self.format_result(result), "0"]
-
-class BignumModInvNonMont(bignum_common.ModOperationCommon, BignumModTarget):
-    """Test cases for bignum mpi_mod_inv() - not in Montgomery form."""
-    moduli = ONLY_PRIME_MODULI  # for now only prime moduli supported
-    symbol = "^ -1"
-    test_function = "mpi_mod_inv_non_mont"
-    test_name = "mbedtls_mpi_mod_inv non-Mont. form"
-    input_style = "fixed"
-    arity = 1
-    suffix = True
-    disallow_zero_a = True
-
-    def result(self) -> List[str]:
-        result = bignum_common.invmod_positive(self.int_a, self.int_n)
-        # To make negative tests easier, append 0 for success to the
-        # generated cases
-        return [self.format_result(result), "0"]
-
-class BignumModInvMont(bignum_common.ModOperationCommon, BignumModTarget):
-    """Test cases for bignum mpi_mod_inv() - Montgomery form."""
-    moduli = ONLY_PRIME_MODULI  # for now only prime moduli supported
-    symbol = "^ -1"
-    test_function = "mpi_mod_inv_mont"
-    test_name = "mbedtls_mpi_mod_inv Mont. form"
-    input_style = "arch_split"  # Mont. form requires arch_split
-    arity = 1
-    suffix = True
-    disallow_zero_a = True
-    montgomery_form_a = True
-
-    def result(self) -> List[str]:
-        result = bignum_common.invmod_positive(self.int_a, self.int_n)
-        mont_result = self.to_montgomery(result)
-        # To make negative tests easier, append 0 for success to the
-        # generated cases
-        return [self.format_result(mont_result), "0"]
-
-
-class BignumModAdd(bignum_common.ModOperationCommon, BignumModTarget):
-    """Test cases for bignum mpi_mod_add()."""
-    count = 0
-    symbol = "+"
-    test_function = "mpi_mod_add"
-    test_name = "mbedtls_mpi_mod_add"
-    input_style = "fixed"
-
-    def result(self) -> List[str]:
-        result = (self.int_a + self.int_b) % self.int_n
-        # To make negative tests easier, append "0" for success to the
-        # generated cases
-        return [self.format_result(result), "0"]
diff --git a/scripts/mbedtls_dev/bignum_mod_raw.py b/scripts/mbedtls_dev/bignum_mod_raw.py
deleted file mode 100644
index 37ad27a..0000000
--- a/scripts/mbedtls_dev/bignum_mod_raw.py
+++ /dev/null
@@ -1,242 +0,0 @@
-"""Framework classes for generation of bignum mod_raw test cases."""
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-from typing import Iterator, List
-
-from . import test_case
-from . import test_data_generation
-from . import bignum_common
-from .bignum_data import ONLY_PRIME_MODULI
-
-class BignumModRawTarget(test_data_generation.BaseTarget):
-    #pylint: disable=abstract-method, too-few-public-methods
-    """Target for bignum mod_raw test case generation."""
-    target_basename = 'test_suite_bignum_mod_raw.generated'
-
-
-class BignumModRawSub(bignum_common.ModOperationCommon,
-                      BignumModRawTarget):
-    """Test cases for bignum mpi_mod_raw_sub()."""
-    symbol = "-"
-    test_function = "mpi_mod_raw_sub"
-    test_name = "mbedtls_mpi_mod_raw_sub"
-    input_style = "fixed"
-    arity = 2
-
-    def arguments(self) -> List[str]:
-        return [bignum_common.quote_str(n) for n in [self.arg_a,
-                                                     self.arg_b,
-                                                     self.arg_n]
-               ] + self.result()
-
-    def result(self) -> List[str]:
-        result = (self.int_a - self.int_b) % self.int_n
-        return [self.format_result(result)]
-
-class BignumModRawFixQuasiReduction(bignum_common.ModOperationCommon,
-                                    BignumModRawTarget):
-    """Test cases for ecp quasi_reduction()."""
-    symbol = "-"
-    test_function = "mpi_mod_raw_fix_quasi_reduction"
-    test_name = "fix_quasi_reduction"
-    input_style = "fixed"
-    arity = 1
-
-    # Extend the default values with n < x < 2n
-    input_values = bignum_common.ModOperationCommon.input_values + [
-        "73",
-
-        # First number generated by random.getrandbits(1024) - seed(3,2)
-        "ea7b5bf55eb561a4216363698b529b4a97b750923ceb3ffd",
-
-        # First number generated by random.getrandbits(1024) - seed(1,2)
-        ("cd447e35b8b6d8fe442e3d437204e52db2221a58008a05a6c4647159c324c985"
-         "9b810e766ec9d28663ca828dd5f4b3b2e4b06ce60741c7a87ce42c8218072e8c"
-         "35bf992dc9e9c616612e7696a6cecc1b78e510617311d8a3c2ce6f447ed4d57b"
-         "1e2feb89414c343c1027c4d1c386bbc4cd613e30d8f16adf91b7584a2265b1f5")
-    ] # type: List[str]
-
-    def result(self) -> List[str]:
-        result = self.int_a % self.int_n
-        return [self.format_result(result)]
-
-    @property
-    def is_valid(self) -> bool:
-        return bool(self.int_a < 2 * self.int_n)
-
-class BignumModRawMul(bignum_common.ModOperationCommon,
-                      BignumModRawTarget):
-    """Test cases for bignum mpi_mod_raw_mul()."""
-    symbol = "*"
-    test_function = "mpi_mod_raw_mul"
-    test_name = "mbedtls_mpi_mod_raw_mul"
-    input_style = "arch_split"
-    arity = 2
-
-    def arguments(self) -> List[str]:
-        return [self.format_result(self.to_montgomery(self.int_a)),
-                self.format_result(self.to_montgomery(self.int_b)),
-                bignum_common.quote_str(self.arg_n)
-               ] + self.result()
-
-    def result(self) -> List[str]:
-        result = (self.int_a * self.int_b) % self.int_n
-        return [self.format_result(self.to_montgomery(result))]
-
-
-class BignumModRawInvPrime(bignum_common.ModOperationCommon,
-                           BignumModRawTarget):
-    """Test cases for bignum mpi_mod_raw_inv_prime()."""
-    moduli = ONLY_PRIME_MODULI
-    symbol = "^ -1"
-    test_function = "mpi_mod_raw_inv_prime"
-    test_name = "mbedtls_mpi_mod_raw_inv_prime (Montgomery form only)"
-    input_style = "arch_split"
-    arity = 1
-    suffix = True
-    montgomery_form_a = True
-    disallow_zero_a = True
-
-    def result(self) -> List[str]:
-        result = bignum_common.invmod_positive(self.int_a, self.int_n)
-        mont_result = self.to_montgomery(result)
-        return [self.format_result(mont_result)]
-
-
-class BignumModRawAdd(bignum_common.ModOperationCommon,
-                      BignumModRawTarget):
-    """Test cases for bignum mpi_mod_raw_add()."""
-    symbol = "+"
-    test_function = "mpi_mod_raw_add"
-    test_name = "mbedtls_mpi_mod_raw_add"
-    input_style = "fixed"
-    arity = 2
-
-    def result(self) -> List[str]:
-        result = (self.int_a + self.int_b) % self.int_n
-        return [self.format_result(result)]
-
-
-class BignumModRawConvertRep(bignum_common.ModOperationCommon,
-                             BignumModRawTarget):
-    # This is an abstract class, it's ok to have unimplemented methods.
-    #pylint: disable=abstract-method
-    """Test cases for representation conversion."""
-    symbol = ""
-    input_style = "arch_split"
-    arity = 1
-    rep = bignum_common.ModulusRepresentation.INVALID
-
-    def set_representation(self, r: bignum_common.ModulusRepresentation) -> None:
-        self.rep = r
-
-    def arguments(self) -> List[str]:
-        return ([bignum_common.quote_str(self.arg_n), self.rep.symbol(),
-                 bignum_common.quote_str(self.arg_a)] +
-                self.result())
-
-    def description(self) -> str:
-        base = super().description()
-        mod_with_rep = 'mod({})'.format(self.rep.name)
-        return base.replace('mod', mod_with_rep, 1)
-
-    @classmethod
-    def test_cases_for_values(cls, rep: bignum_common.ModulusRepresentation,
-                              n: str, a: str) -> Iterator[test_case.TestCase]:
-        """Emit test cases for the given values (if any).
-
-        This may emit no test cases if a isn't valid for the modulus n,
-        or multiple test cases if rep requires different data depending
-        on the limb size.
-        """
-        for bil in cls.limb_sizes:
-            test_object = cls(n, a, bits_in_limb=bil)
-            test_object.set_representation(rep)
-            # The class is set to having separate test cases for each limb
-            # size, because the Montgomery representation requires it.
-            # But other representations don't require it. So for other
-            # representations, emit a single test case with no dependency
-            # on the limb size.
-            if rep is not bignum_common.ModulusRepresentation.MONTGOMERY:
-                test_object.dependencies = \
-                    [dep for dep in test_object.dependencies
-                     if not dep.startswith('MBEDTLS_HAVE_INT')]
-            if test_object.is_valid:
-                yield test_object.create_test_case()
-            if rep is not bignum_common.ModulusRepresentation.MONTGOMERY:
-                # A single test case (emitted, or skipped due to invalidity)
-                # is enough, since this test case doesn't depend on the
-                # limb size.
-                break
-
-    # The parent class doesn't support non-bignum parameters. So we override
-    # test generation, in order to have the representation as a parameter.
-    @classmethod
-    def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
-
-        for rep in bignum_common.ModulusRepresentation.supported_representations():
-            for n in cls.moduli:
-                for a in cls.input_values:
-                    yield from cls.test_cases_for_values(rep, n, a)
-
-class BignumModRawCanonicalToModulusRep(BignumModRawConvertRep):
-    """Test cases for mpi_mod_raw_canonical_to_modulus_rep."""
-    test_function = "mpi_mod_raw_canonical_to_modulus_rep"
-    test_name = "Rep canon->mod"
-
-    def result(self) -> List[str]:
-        return [self.format_result(self.convert_from_canonical(self.int_a, self.rep))]
-
-class BignumModRawModulusToCanonicalRep(BignumModRawConvertRep):
-    """Test cases for mpi_mod_raw_modulus_to_canonical_rep."""
-    test_function = "mpi_mod_raw_modulus_to_canonical_rep"
-    test_name = "Rep mod->canon"
-
-    @property
-    def arg_a(self) -> str:
-        return self.format_arg("{:x}".format(self.convert_from_canonical(self.int_a, self.rep)))
-
-    def result(self) -> List[str]:
-        return [self.format_result(self.int_a)]
-
-
-class BignumModRawConvertToMont(bignum_common.ModOperationCommon,
-                                BignumModRawTarget):
-    """ Test cases for mpi_mod_raw_to_mont_rep(). """
-    test_function = "mpi_mod_raw_to_mont_rep"
-    test_name = "Convert into Mont: "
-    symbol = "R *"
-    input_style = "arch_split"
-    arity = 1
-
-    def result(self) -> List[str]:
-        result = self.to_montgomery(self.int_a)
-        return [self.format_result(result)]
-
-class BignumModRawConvertFromMont(bignum_common.ModOperationCommon,
-                                  BignumModRawTarget):
-    """ Test cases for mpi_mod_raw_from_mont_rep(). """
-    test_function = "mpi_mod_raw_from_mont_rep"
-    test_name = "Convert from Mont: "
-    symbol = "1/R *"
-    input_style = "arch_split"
-    arity = 1
-
-    def result(self) -> List[str]:
-        result = self.from_montgomery(self.int_a)
-        return [self.format_result(result)]
-
-class BignumModRawModNegate(bignum_common.ModOperationCommon,
-                            BignumModRawTarget):
-    """ Test cases for mpi_mod_raw_neg(). """
-    test_function = "mpi_mod_raw_neg"
-    test_name = "Modular negation: "
-    symbol = "-"
-    input_style = "arch_split"
-    arity = 1
-
-    def result(self) -> List[str]:
-        result = (self.int_n - self.int_a) % self.int_n
-        return [self.format_result(result)]
diff --git a/scripts/mbedtls_dev/build_tree.py b/scripts/mbedtls_dev/build_tree.py
deleted file mode 100644
index ec67e4c..0000000
--- a/scripts/mbedtls_dev/build_tree.py
+++ /dev/null
@@ -1,120 +0,0 @@
-"""Mbed TLS build tree information and manipulation.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-import os
-import inspect
-from typing import Optional
-
-def looks_like_tf_psa_crypto_root(path: str) -> bool:
-    """Whether the given directory looks like the root of the PSA Crypto source tree."""
-    return all(os.path.isdir(os.path.join(path, subdir))
-               for subdir in ['include', 'core', 'drivers', 'programs', 'tests'])
-
-def looks_like_mbedtls_root(path: str) -> bool:
-    """Whether the given directory looks like the root of the Mbed TLS source tree."""
-    return all(os.path.isdir(os.path.join(path, subdir))
-               for subdir in ['include', 'library', 'programs', 'tests'])
-
-def looks_like_root(path: str) -> bool:
-    return looks_like_tf_psa_crypto_root(path) or looks_like_mbedtls_root(path)
-
-def crypto_core_directory(root: Optional[str] = None, relative: Optional[bool] = False) -> str:
-    """
-    Return the path of the directory containing the PSA crypto core
-    for either TF-PSA-Crypto or Mbed TLS.
-
-    Returns either the full path or relative path depending on the
-    "relative" boolean argument.
-    """
-    if root is None:
-        root = guess_project_root()
-    if looks_like_tf_psa_crypto_root(root):
-        if relative:
-            return "core"
-        return os.path.join(root, "core")
-    elif looks_like_mbedtls_root(root):
-        if relative:
-            return "library"
-        return os.path.join(root, "library")
-    else:
-        raise Exception('Neither Mbed TLS nor TF-PSA-Crypto source tree found')
-
-def crypto_library_filename(root: Optional[str] = None) -> str:
-    """Return the crypto library filename for either TF-PSA-Crypto or Mbed TLS."""
-    if root is None:
-        root = guess_project_root()
-    if looks_like_tf_psa_crypto_root(root):
-        return "tfpsacrypto"
-    elif looks_like_mbedtls_root(root):
-        return "mbedcrypto"
-    else:
-        raise Exception('Neither Mbed TLS nor TF-PSA-Crypto source tree found')
-
-def check_repo_path():
-    """Check that the current working directory is the project root, and throw
-    an exception if not.
-    """
-    if not all(os.path.isdir(d) for d in ["include", "library", "tests"]):
-        raise Exception("This script must be run from Mbed TLS root")
-
-def chdir_to_root() -> None:
-    """Detect the root of the Mbed TLS source tree and change to it.
-
-    The current directory must be up to two levels deep inside an Mbed TLS
-    source tree.
-    """
-    for d in [os.path.curdir,
-              os.path.pardir,
-              os.path.join(os.path.pardir, os.path.pardir)]:
-        if looks_like_root(d):
-            os.chdir(d)
-            return
-    raise Exception('Mbed TLS source tree not found')
-
-def guess_project_root():
-    """Guess project source code directory.
-
-    Return the first possible project root directory.
-    """
-    dirs = set({})
-    for frame in inspect.stack():
-        path = os.path.dirname(frame.filename)
-        for d in ['.', os.path.pardir] \
-                 + [os.path.join(*([os.path.pardir]*i)) for i in range(2, 10)]:
-            d = os.path.abspath(os.path.join(path, d))
-            if d in dirs:
-                continue
-            dirs.add(d)
-            if looks_like_root(d):
-                return d
-    raise Exception('Neither Mbed TLS nor TF-PSA-Crypto source tree found')
-
-def guess_mbedtls_root(root: Optional[str] = None) -> str:
-    """Guess Mbed TLS source code directory.
-
-    Return the first possible Mbed TLS root directory.
-    Raise an exception if we are not in Mbed TLS.
-    """
-    if root is None:
-        root = guess_project_root()
-    if looks_like_mbedtls_root(root):
-        return root
-    else:
-        raise Exception('Mbed TLS source tree not found')
-
-def guess_tf_psa_crypto_root(root: Optional[str] = None) -> str:
-    """Guess TF-PSA-Crypto source code directory.
-
-    Return the first possible TF-PSA-Crypto root directory.
-    Raise an exception if we are not in TF-PSA-Crypto.
-    """
-    if root is None:
-        root = guess_project_root()
-    if looks_like_tf_psa_crypto_root(root):
-        return root
-    else:
-        raise Exception('TF-PSA-Crypto source tree not found')
diff --git a/scripts/mbedtls_dev/c_build_helper.py b/scripts/mbedtls_dev/c_build_helper.py
deleted file mode 100644
index f2cbbe4..0000000
--- a/scripts/mbedtls_dev/c_build_helper.py
+++ /dev/null
@@ -1,162 +0,0 @@
-"""Generate and run C code.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-import os
-import platform
-import subprocess
-import sys
-import tempfile
-
-def remove_file_if_exists(filename):
-    """Remove the specified file, ignoring errors."""
-    if not filename:
-        return
-    try:
-        os.remove(filename)
-    except OSError:
-        pass
-
-def create_c_file(file_label):
-    """Create a temporary C file.
-
-    * ``file_label``: a string that will be included in the file name.
-
-    Return ```(c_file, c_name, exe_name)``` where ``c_file`` is a Python
-    stream open for writing to the file, ``c_name`` is the name of the file
-    and ``exe_name`` is the name of the executable that will be produced
-    by compiling the file.
-    """
-    c_fd, c_name = tempfile.mkstemp(prefix='tmp-{}-'.format(file_label),
-                                    suffix='.c')
-    exe_suffix = '.exe' if platform.system() == 'Windows' else ''
-    exe_name = c_name[:-2] + exe_suffix
-    remove_file_if_exists(exe_name)
-    c_file = os.fdopen(c_fd, 'w', encoding='ascii')
-    return c_file, c_name, exe_name
-
-def generate_c_printf_expressions(c_file, cast_to, printf_format, expressions):
-    """Generate C instructions to print the value of ``expressions``.
-
-    Write the code with ``c_file``'s ``write`` method.
-
-    Each expression is cast to the type ``cast_to`` and printed with the
-    printf format ``printf_format``.
-    """
-    for expr in expressions:
-        c_file.write('    printf("{}\\n", ({}) {});\n'
-                     .format(printf_format, cast_to, expr))
-
-def generate_c_file(c_file,
-                    caller, header,
-                    main_generator):
-    """Generate a temporary C source file.
-
-    * ``c_file`` is an open stream on the C source file.
-    * ``caller``: an informational string written in a comment at the top
-      of the file.
-    * ``header``: extra code to insert before any function in the generated
-      C file.
-    * ``main_generator``: a function called with ``c_file`` as its sole argument
-      to generate the body of the ``main()`` function.
-    """
-    c_file.write('/* Generated by {} */'
-                 .format(caller))
-    c_file.write('''
-#include <stdio.h>
-''')
-    c_file.write(header)
-    c_file.write('''
-int main(void)
-{
-''')
-    main_generator(c_file)
-    c_file.write('''    return 0;
-}
-''')
-
-def compile_c_file(c_filename, exe_filename, include_dirs):
-    """Compile a C source file with the host compiler.
-
-    * ``c_filename``: the name of the source file to compile.
-    * ``exe_filename``: the name for the executable to be created.
-    * ``include_dirs``: a list of paths to include directories to be passed
-      with the -I switch.
-    """
-    # Respect $HOSTCC if it is set
-    cc = os.getenv('HOSTCC', None)
-    if cc is None:
-        cc = os.getenv('CC', 'cc')
-    cmd = [cc]
-
-    proc = subprocess.Popen(cmd,
-                            stdout=subprocess.DEVNULL,
-                            stderr=subprocess.PIPE,
-                            universal_newlines=True)
-    cc_is_msvc = 'Microsoft (R) C/C++' in proc.communicate()[1]
-
-    cmd += ['-I' + dir for dir in include_dirs]
-    if cc_is_msvc:
-        # MSVC has deprecated using -o to specify the output file,
-        # and produces an object file in the working directory by default.
-        obj_filename = exe_filename[:-4] + '.obj'
-        cmd += ['-Fe' + exe_filename, '-Fo' + obj_filename]
-    else:
-        cmd += ['-o' + exe_filename]
-
-    subprocess.check_call(cmd + [c_filename])
-
-def get_c_expression_values(
-        cast_to, printf_format,
-        expressions,
-        caller=__name__, file_label='',
-        header='', include_path=None,
-        keep_c=False,
-): # pylint: disable=too-many-arguments, too-many-locals
-    """Generate and run a program to print out numerical values for expressions.
-
-    * ``cast_to``: a C type.
-    * ``printf_format``: a printf format suitable for the type ``cast_to``.
-    * ``header``: extra code to insert before any function in the generated
-      C file.
-    * ``expressions``: a list of C language expressions that have the type
-      ``cast_to``.
-    * ``include_path``: a list of directories containing header files.
-    * ``keep_c``: if true, keep the temporary C file (presumably for debugging
-      purposes).
-
-    Use the C compiler specified by the ``CC`` environment variable, defaulting
-    to ``cc``. If ``CC`` looks like MSVC, use its command line syntax,
-    otherwise assume the compiler supports Unix traditional ``-I`` and ``-o``.
-
-    Return the list of values of the ``expressions``.
-    """
-    if include_path is None:
-        include_path = []
-    c_name = None
-    exe_name = None
-    obj_name = None
-    try:
-        c_file, c_name, exe_name = create_c_file(file_label)
-        generate_c_file(
-            c_file, caller, header,
-            lambda c_file: generate_c_printf_expressions(c_file,
-                                                         cast_to, printf_format,
-                                                         expressions)
-        )
-        c_file.close()
-
-        compile_c_file(c_name, exe_name, include_path)
-        if keep_c:
-            sys.stderr.write('List of {} tests kept at {}\n'
-                             .format(caller, c_name))
-        else:
-            os.remove(c_name)
-        output = subprocess.check_output([exe_name])
-        return output.decode('ascii').strip().split('\n')
-    finally:
-        remove_file_if_exists(exe_name)
-        remove_file_if_exists(obj_name)
diff --git a/scripts/mbedtls_dev/c_parsing_helper.py b/scripts/mbedtls_dev/c_parsing_helper.py
deleted file mode 100644
index 2657b7d..0000000
--- a/scripts/mbedtls_dev/c_parsing_helper.py
+++ /dev/null
@@ -1,131 +0,0 @@
-"""Helper functions to parse C code in heavily constrained scenarios.
-
-Currently supported functionality:
-
-* read_function_declarations: read function declarations from a header file.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-
-### WARNING: the code in this file has not been extensively reviewed yet.
-### We do not think it is harmful, but it may be below our normal standards
-### for robustness and maintainability.
-
-import re
-from typing import Dict, Iterable, Iterator, List, Optional, Tuple
-
-
-class ArgumentInfo:
-    """Information about an argument to an API function."""
-    #pylint: disable=too-few-public-methods
-
-    _KEYWORDS = [
-        'const', 'register', 'restrict',
-        'int', 'long', 'short', 'signed', 'unsigned',
-    ]
-    _DECLARATION_RE = re.compile(
-        r'(?P<type>\w[\w\s*]*?)\s*' +
-        r'(?!(?:' + r'|'.join(_KEYWORDS) + r'))(?P<name>\b\w+\b)?' +
-        r'\s*(?P<suffix>\[[^][]*\])?\Z',
-        re.A | re.S)
-
-    @classmethod
-    def normalize_type(cls, typ: str) -> str:
-        """Normalize whitespace in a type."""
-        typ = re.sub(r'\s+', r' ', typ)
-        typ = re.sub(r'\s*\*', r' *', typ)
-        return typ
-
-    def __init__(self, decl: str) -> None:
-        self.decl = decl.strip()
-        m = self._DECLARATION_RE.match(self.decl)
-        if not m:
-            raise ValueError(self.decl)
-        self.type = self.normalize_type(m.group('type')) #type: str
-        self.name = m.group('name') #type: Optional[str]
-        self.suffix = m.group('suffix') if m.group('suffix') else '' #type: str
-
-
-class FunctionInfo:
-    """Information about an API function."""
-    #pylint: disable=too-few-public-methods
-
-    # Regex matching the declaration of a function that returns void.
-    VOID_RE = re.compile(r'\s*\bvoid\s*\Z', re.A)
-
-    def __init__(self, #pylint: disable=too-many-arguments
-                 filename: str,
-                 line_number: int,
-                 qualifiers: Iterable[str],
-                 return_type: str,
-                 name: str,
-                 arguments: List[str]) -> None:
-        self.filename = filename
-        self.line_number = line_number
-        self.qualifiers = frozenset(qualifiers)
-        self.return_type = return_type
-        self.name = name
-        self.arguments = [ArgumentInfo(arg) for arg in arguments]
-
-    def returns_void(self) -> bool:
-        """Whether the function returns void."""
-        return bool(self.VOID_RE.search(self.return_type))
-
-
-# Match one C comment.
-# Note that we match both comment types, so things like // in a /*...*/
-# comment are handled correctly.
-_C_COMMENT_RE = re.compile(r'//(?:[^\n]|\\\n)*|/\*.*?\*/', re.S)
-_NOT_NEWLINES_RE = re.compile(r'[^\n]+')
-
-def read_logical_lines(filename: str) -> Iterator[Tuple[int, str]]:
-    """Read logical lines from a file.
-
-    Logical lines are one or more physical line, with balanced parentheses.
-    """
-    with open(filename, encoding='utf-8') as inp:
-        content = inp.read()
-    # Strip comments, but keep newlines for line numbering
-    content = re.sub(_C_COMMENT_RE,
-                     lambda m: re.sub(_NOT_NEWLINES_RE, "", m.group(0)),
-                     content)
-    lines = enumerate(content.splitlines(), 1)
-    for line_number, line in lines:
-        # Read a logical line, containing balanced parentheses.
-        # We assume that parentheses are balanced (this should be ok
-        # since comments have been stripped), otherwise there will be
-        # a gigantic logical line at the end.
-        paren_level = line.count('(') - line.count(')')
-        while paren_level > 0:
-            _, more = next(lines) #pylint: disable=stop-iteration-return
-            paren_level += more.count('(') - more.count(')')
-            line += '\n' + more
-        yield line_number, line
-
-_C_FUNCTION_DECLARATION_RE = re.compile(
-    r'(?P<qualifiers>(?:(?:extern|inline|static)\b\s*)*)'
-    r'(?P<return_type>\w[\w\s*]*?)\s*' +
-    r'\b(?P<name>\w+)' +
-    r'\s*\((?P<arguments>.*)\)\s*;',
-    re.A | re.S)
-
-def read_function_declarations(functions: Dict[str, FunctionInfo],
-                               filename: str) -> None:
-    """Collect function declarations from a C header file."""
-    for line_number, line in read_logical_lines(filename):
-        m = _C_FUNCTION_DECLARATION_RE.match(line)
-        if not m:
-            continue
-        qualifiers = m.group('qualifiers').split()
-        return_type = m.group('return_type')
-        name = m.group('name')
-        arguments = m.group('arguments').split(',')
-        if len(arguments) == 1 and re.match(FunctionInfo.VOID_RE, arguments[0]):
-            arguments = []
-        # Note: we replace any existing declaration for the same name.
-        functions[name] = FunctionInfo(filename, line_number,
-                                       qualifiers,
-                                       return_type,
-                                       name,
-                                       arguments)
diff --git a/scripts/mbedtls_dev/c_wrapper_generator.py b/scripts/mbedtls_dev/c_wrapper_generator.py
deleted file mode 100644
index 3cf1e05..0000000
--- a/scripts/mbedtls_dev/c_wrapper_generator.py
+++ /dev/null
@@ -1,473 +0,0 @@
-"""Generate C wrapper functions.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-
-### WARNING: the code in this file has not been extensively reviewed yet.
-### We do not think it is harmful, but it may be below our normal standards
-### for robustness and maintainability.
-
-import os
-import re
-import sys
-import typing
-from typing import Dict, List, Optional, Tuple
-
-from .c_parsing_helper import ArgumentInfo, FunctionInfo
-from . import typing_util
-
-
-def c_declare(prefix: str, name: str, suffix: str) -> str:
-    """Format a declaration of name with the given type prefix and suffix."""
-    if not prefix.endswith('*'):
-        prefix += ' '
-    return prefix + name + suffix
-
-
-WrapperInfo = typing.NamedTuple('WrapperInfo', [
-    ('argument_names', List[str]),
-    ('guard', Optional[str]),
-    ('wrapper_name', str),
-])
-
-
-class Base:
-    """Generate a C source file containing wrapper functions."""
-
-    # This class is designed to have many methods potentially overloaded.
-    # Tell pylint not to complain about methods that have unused arguments:
-    # child classes are likely to override those methods and need the
-    # arguments in question.
-    #pylint: disable=no-self-use,unused-argument
-
-    # Prefix prepended to the function's name to form the wrapper name.
-    _WRAPPER_NAME_PREFIX = ''
-    # Suffix appended to the function's name to form the wrapper name.
-    _WRAPPER_NAME_SUFFIX = '_wrap'
-
-    # Functions with one of these qualifiers are skipped.
-    _SKIP_FUNCTION_WITH_QUALIFIERS = frozenset(['inline', 'static'])
-
-    def __init__(self):
-        """Construct a wrapper generator object.
-        """
-        self.program_name = os.path.basename(sys.argv[0])
-        # To be populated in a derived class
-        self.functions = {} #type: Dict[str, FunctionInfo]
-        # Preprocessor symbol used as a guard against multiple inclusion in the
-        # header. Must be set before writing output to a header.
-        # Not used when writing .c output.
-        self.header_guard = None #type: Optional[str]
-
-    def _write_prologue(self, out: typing_util.Writable, header: bool) -> None:
-        """Write the prologue of a C file.
-
-        This includes a description comment and some include directives.
-        """
-        out.write("""/* Automatically generated by {}, do not edit! */
-
-/* Copyright The Mbed TLS Contributors
- * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
- */
-"""
-                  .format(self.program_name))
-        if header:
-            out.write("""
-#ifndef {guard}
-#define {guard}
-
-#ifdef __cplusplus
-extern "C" {{
-#endif
-"""
-                      .format(guard=self.header_guard))
-        out.write("""
-#include <mbedtls/build_info.h>
-""")
-
-    def _write_epilogue(self, out: typing_util.Writable, header: bool) -> None:
-        """Write the epilogue of a C file.
-        """
-        if header:
-            out.write("""
-#ifdef __cplusplus
-}}
-#endif
-
-#endif /* {guard} */
-"""
-                      .format(guard=self.header_guard))
-        out.write("""
-/* End of automatically generated file. */
-""")
-
-    def _wrapper_function_name(self, original_name: str) -> str:
-        """The name of the wrapper function.
-
-        By default, this adds a suffix.
-        """
-        return (self._WRAPPER_NAME_PREFIX +
-                original_name +
-                self._WRAPPER_NAME_SUFFIX)
-
-    def _wrapper_declaration_start(self,
-                                   function: FunctionInfo,
-                                   wrapper_name: str) -> str:
-        """The beginning of the wrapper function declaration.
-
-        This ends just before the opening parenthesis of the argument list.
-
-        This is a string containing at least the return type and the
-        function name. It may start with additional qualifiers or attributes
-        such as `static`, `__attribute__((...))`, etc.
-        """
-        return c_declare(function.return_type, wrapper_name, '')
-
-    def _argument_name(self,
-                       function_name: str,
-                       num: int,
-                       arg: ArgumentInfo) -> str:
-        """Name to use for the given argument in the wrapper function.
-
-        Argument numbers count from 0.
-        """
-        name = 'arg' + str(num)
-        if arg.name:
-            name += '_' + arg.name
-        return name
-
-    def _wrapper_declaration_argument(self,
-                                      function_name: str,
-                                      num: int, name: str,
-                                      arg: ArgumentInfo) -> str:
-        """One argument definition in the wrapper function declaration.
-
-        Argument numbers count from 0.
-        """
-        return c_declare(arg.type, name, arg.suffix)
-
-    def _underlying_function_name(self, function: FunctionInfo) -> str:
-        """The name of the underlying function.
-
-        By default, this is the name of the wrapped function.
-        """
-        return function.name
-
-    def _return_variable_name(self, function: FunctionInfo) -> str:
-        """The name of the variable that will contain the return value."""
-        return 'retval'
-
-    def _write_function_call(self, out: typing_util.Writable,
-                             function: FunctionInfo,
-                             argument_names: List[str]) -> None:
-        """Write the call to the underlying function.
-        """
-        # Note that the function name is in parentheses, to avoid calling
-        # a function-like macro with the same name, since in typical usage
-        # there is a function-like macro with the same name which is the
-        # wrapper.
-        call = '({})({})'.format(self._underlying_function_name(function),
-                                 ', '.join(argument_names))
-        if function.returns_void():
-            out.write('    {};\n'.format(call))
-        else:
-            ret_name = self._return_variable_name(function)
-            ret_decl = c_declare(function.return_type, ret_name, '')
-            out.write('    {} = {};\n'.format(ret_decl, call))
-
-    def _write_function_return(self, out: typing_util.Writable,
-                               function: FunctionInfo,
-                               if_void: bool = False) -> None:
-        """Write a return statement.
-
-        If the function returns void, only write a statement if if_void is true.
-        """
-        if function.returns_void():
-            if if_void:
-                out.write('    return;\n')
-        else:
-            ret_name = self._return_variable_name(function)
-            out.write('    return {};\n'.format(ret_name))
-
-    def _write_function_body(self, out: typing_util.Writable,
-                             function: FunctionInfo,
-                             argument_names: List[str]) -> None:
-        """Write the body of the wrapper code for the specified function.
-        """
-        self._write_function_call(out, function, argument_names)
-        self._write_function_return(out, function)
-
-    def _skip_function(self, function: FunctionInfo) -> bool:
-        """Whether to skip this function.
-
-        By default, static or inline functions are skipped.
-        """
-        if not self._SKIP_FUNCTION_WITH_QUALIFIERS.isdisjoint(function.qualifiers):
-            return True
-        return False
-
-    _FUNCTION_GUARDS = {
-    } #type: Dict[str, str]
-
-    def _function_guard(self, function: FunctionInfo) -> Optional[str]:
-        """A preprocessor condition for this function.
-
-        The wrapper will be guarded with `#if` on this condition, if not None.
-        """
-        return self._FUNCTION_GUARDS.get(function.name)
-
-    def _wrapper_info(self, function: FunctionInfo) -> Optional[WrapperInfo]:
-        """Information about the wrapper for one function.
-
-        Return None if the function should be skipped.
-        """
-        if self._skip_function(function):
-            return None
-        argument_names = [self._argument_name(function.name, num, arg)
-                          for num, arg in enumerate(function.arguments)]
-        return WrapperInfo(
-            argument_names=argument_names,
-            guard=self._function_guard(function),
-            wrapper_name=self._wrapper_function_name(function.name),
-        )
-
-    def _write_function_prototype(self, out: typing_util.Writable,
-                                  function: FunctionInfo,
-                                  wrapper: WrapperInfo,
-                                  header: bool) -> None:
-        """Write the prototype of a wrapper function.
-
-        If header is true, write a function declaration, with a semicolon at
-        the end. Otherwise just write the prototype, intended to be followed
-        by the function's body.
-        """
-        declaration_start = self._wrapper_declaration_start(function,
-                                                            wrapper.wrapper_name)
-        arg_indent = '    '
-        terminator = ';\n' if header else '\n'
-        if function.arguments:
-            out.write(declaration_start + '(\n')
-            for num in range(len(function.arguments)):
-                arg_def = self._wrapper_declaration_argument(
-                    function.name,
-                    num, wrapper.argument_names[num], function.arguments[num])
-                arg_terminator = \
-                    (')' + terminator if num == len(function.arguments) - 1 else
-                     ',\n')
-                out.write(arg_indent + arg_def + arg_terminator)
-        else:
-            out.write(declaration_start + '(void)' + terminator)
-
-    def _write_c_function(self, out: typing_util.Writable,
-                          function: FunctionInfo) -> None:
-        """Write wrapper code for one function.
-
-        Do nothing if the function is skipped.
-        """
-        wrapper = self._wrapper_info(function)
-        if wrapper is None:
-            return
-        out.write("""
-/* Wrapper for {} */
-"""
-                  .format(function.name))
-        if wrapper.guard is not None:
-            out.write('#if {}\n'.format(wrapper.guard))
-        self._write_function_prototype(out, function, wrapper, False)
-        out.write('{\n')
-        self._write_function_body(out, function, wrapper.argument_names)
-        out.write('}\n')
-        if wrapper.guard is not None:
-            out.write('#endif /* {} */\n'.format(wrapper.guard))
-
-    def _write_h_function_declaration(self, out: typing_util.Writable,
-                                      function: FunctionInfo,
-                                      wrapper: WrapperInfo) -> None:
-        """Write the declaration of one wrapper function.
-        """
-        self._write_function_prototype(out, function, wrapper, True)
-
-    def _write_h_macro_definition(self, out: typing_util.Writable,
-                                  function: FunctionInfo,
-                                  wrapper: WrapperInfo) -> None:
-        """Write the macro definition for one wrapper.
-        """
-        arg_list = ', '.join(wrapper.argument_names)
-        out.write('#define {function_name}({args}) \\\n    {wrapper_name}({args})\n'
-                  .format(function_name=function.name,
-                          wrapper_name=wrapper.wrapper_name,
-                          args=arg_list))
-
-    def _write_h_function(self, out: typing_util.Writable,
-                          function: FunctionInfo) -> None:
-        """Write the complete header content for one wrapper.
-
-        This is the declaration of the wrapper function, and the
-        definition of a function-like macro that calls the wrapper function.
-
-        Do nothing if the function is skipped.
-        """
-        wrapper = self._wrapper_info(function)
-        if wrapper is None:
-            return
-        out.write('\n')
-        if wrapper.guard is not None:
-            out.write('#if {}\n'.format(wrapper.guard))
-        self._write_h_function_declaration(out, function, wrapper)
-        self._write_h_macro_definition(out, function, wrapper)
-        if wrapper.guard is not None:
-            out.write('#endif /* {} */\n'.format(wrapper.guard))
-
-    def write_c_file(self, filename: str) -> None:
-        """Output a whole C file containing function wrapper definitions."""
-        with open(filename, 'w', encoding='utf-8') as out:
-            self._write_prologue(out, False)
-            for name in sorted(self.functions):
-                self._write_c_function(out, self.functions[name])
-            self._write_epilogue(out, False)
-
-    def _header_guard_from_file_name(self, filename: str) -> str:
-        """Preprocessor symbol used as a guard against multiple inclusion."""
-        # Heuristic to strip irrelevant leading directories
-        filename = re.sub(r'.*include[\\/]', r'', filename)
-        return re.sub(r'[^0-9A-Za-z]', r'_', filename, re.A).upper()
-
-    def write_h_file(self, filename: str) -> None:
-        """Output a header file with function wrapper declarations and macro definitions."""
-        self.header_guard = self._header_guard_from_file_name(filename)
-        with open(filename, 'w', encoding='utf-8') as out:
-            self._write_prologue(out, True)
-            for name in sorted(self.functions):
-                self._write_h_function(out, self.functions[name])
-            self._write_epilogue(out, True)
-
-
-class UnknownTypeForPrintf(Exception):
-    """Exception raised when attempting to generate code that logs a value of an unknown type."""
-
-    def __init__(self, typ: str) -> None:
-        super().__init__("Unknown type for printf format generation: " + typ)
-
-
-class Logging(Base):
-    """Generate wrapper functions that log the inputs and outputs."""
-
-    def __init__(self) -> None:
-        """Construct a wrapper generator including logging of inputs and outputs.
-
-        Log to stdout by default. Call `set_stream` to change this.
-        """
-        super().__init__()
-        self.stream = 'stdout'
-
-    def set_stream(self, stream: str) -> None:
-        """Set the stdio stream to log to.
-
-        Call this method before calling `write_c_output` or `write_h_output`.
-        """
-        self.stream = stream
-
-    def _write_prologue(self, out: typing_util.Writable, header: bool) -> None:
-        super()._write_prologue(out, header)
-        if not header:
-            out.write("""
-#if defined(MBEDTLS_FS_IO) && defined(MBEDTLS_TEST_HOOKS)
-#include <stdio.h>
-#include <inttypes.h>
-#include <mbedtls/debug.h> // for MBEDTLS_PRINTF_SIZET
-#include <mbedtls/platform.h> // for mbedtls_fprintf
-#endif /* defined(MBEDTLS_FS_IO) && defined(MBEDTLS_TEST_HOOKS) */
-""")
-
-    _PRINTF_SIMPLE_FORMAT = {
-        'int': '%d',
-        'long': '%ld',
-        'long long': '%lld',
-        'size_t': '%"MBEDTLS_PRINTF_SIZET"',
-        'unsigned': '0x%08x',
-        'unsigned int': '0x%08x',
-        'unsigned long': '0x%08lx',
-        'unsigned long long': '0x%016llx',
-    }
-
-    def _printf_simple_format(self, typ: str) -> Optional[str]:
-        """Use this printf format for a value of typ.
-
-        Return None if values of typ need more complex handling.
-        """
-        return self._PRINTF_SIMPLE_FORMAT.get(typ)
-
-    _PRINTF_TYPE_CAST = {
-        'int32_t': 'int',
-        'uint32_t': 'unsigned',
-        'uint64_t': 'unsigned long long',
-    } #type: Dict[str, str]
-
-    def _printf_type_cast(self, typ: str) -> Optional[str]:
-        """Cast values of typ to this type before passing them to printf.
-
-        Return None if values of the given type do not need a cast.
-        """
-        return self._PRINTF_TYPE_CAST.get(typ)
-
-    _POINTER_TYPE_RE = re.compile(r'\s*\*\Z')
-
-    def _printf_parameters(self, typ: str, var: str) -> Tuple[str, List[str]]:
-        """The printf format and arguments for a value of type typ stored in var.
-        """
-        expr = var
-        base_type = typ
-        # For outputs via a pointer, get the value that has been written.
-        # Note: we don't support pointers to pointers here.
-        pointer_match = self._POINTER_TYPE_RE.search(base_type)
-        if pointer_match:
-            base_type = base_type[:pointer_match.start(0)]
-            expr = '*({})'.format(expr)
-        # Maybe cast the value to a standard type.
-        cast_to = self._printf_type_cast(base_type)
-        if cast_to is not None:
-            expr = '({}) {}'.format(cast_to, expr)
-            base_type = cast_to
-        # Try standard types.
-        fmt = self._printf_simple_format(base_type)
-        if fmt is not None:
-            return '{}={}'.format(var, fmt), [expr]
-        raise UnknownTypeForPrintf(typ)
-
-    def _write_function_logging(self, out: typing_util.Writable,
-                                function: FunctionInfo,
-                                argument_names: List[str]) -> None:
-        """Write code to log the function's inputs and outputs."""
-        formats, values = '%s', ['"' + function.name + '"']
-        for arg_info, arg_name in zip(function.arguments, argument_names):
-            fmt, vals = self._printf_parameters(arg_info.type, arg_name)
-            if fmt:
-                formats += ' ' + fmt
-                values += vals
-        if not function.returns_void():
-            ret_name = self._return_variable_name(function)
-            fmt, vals = self._printf_parameters(function.return_type, ret_name)
-            if fmt:
-                formats += ' ' + fmt
-                values += vals
-        out.write("""\
-#if defined(MBEDTLS_FS_IO) && defined(MBEDTLS_TEST_HOOKS)
-    if ({stream}) {{
-        mbedtls_fprintf({stream}, "{formats}\\n",
-                        {values});
-    }}
-#endif /* defined(MBEDTLS_FS_IO) && defined(MBEDTLS_TEST_HOOKS) */
-"""
-                  .format(stream=self.stream,
-                          formats=formats,
-                          values=', '.join(values)))
-
-    def _write_function_body(self, out: typing_util.Writable,
-                             function: FunctionInfo,
-                             argument_names: List[str]) -> None:
-        """Write the body of the wrapper code for the specified function.
-        """
-        self._write_function_call(out, function, argument_names)
-        self._write_function_logging(out, function, argument_names)
-        self._write_function_return(out, function)
diff --git a/scripts/mbedtls_dev/crypto_data_tests.py b/scripts/mbedtls_dev/crypto_data_tests.py
deleted file mode 100644
index a36de69..0000000
--- a/scripts/mbedtls_dev/crypto_data_tests.py
+++ /dev/null
@@ -1,112 +0,0 @@
-"""Generate test data for cryptographic mechanisms.
-
-This module is a work in progress, only implementing a few cases for now.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-import hashlib
-from typing import Callable, Dict, Iterator, List, Optional #pylint: disable=unused-import
-
-from . import crypto_knowledge
-from . import psa_information
-from . import test_case
-
-
-def psa_low_level_dependencies(*expressions: str) -> List[str]:
-    """Infer dependencies of a PSA low-level test case by looking for PSA_xxx symbols.
-
-    This function generates MBEDTLS_PSA_BUILTIN_xxx symbols.
-    """
-    high_level = psa_information.automatic_dependencies(*expressions)
-    for dep in high_level:
-        assert dep.startswith('PSA_WANT_')
-    return ['MBEDTLS_PSA_BUILTIN_' + dep[9:] for dep in high_level]
-
-
-class HashPSALowLevel:
-    """Generate test cases for the PSA low-level hash interface."""
-
-    def __init__(self, info: psa_information.Information) -> None:
-        self.info = info
-        base_algorithms = sorted(info.constructors.algorithms)
-        all_algorithms = \
-            [crypto_knowledge.Algorithm(expr)
-             for expr in info.constructors.generate_expressions(base_algorithms)]
-        self.algorithms = \
-            [alg
-             for alg in all_algorithms
-             if (not alg.is_wildcard and
-                 alg.can_do(crypto_knowledge.AlgorithmCategory.HASH))]
-
-    # CALCULATE[alg] = function to return the hash of its argument in hex
-    # TO-DO: implement the None entries with a third-party library, because
-    # hashlib might not have everything, depending on the Python version and
-    # the underlying OpenSSL. On Ubuntu 16.04, truncated sha512 and sha3/shake
-    # are not available. On Ubuntu 22.04, md2, md4 and ripemd160 are not
-    # available.
-    CALCULATE = {
-        'PSA_ALG_MD5': lambda data: hashlib.md5(data).hexdigest(),
-        'PSA_ALG_RIPEMD160': None, #lambda data: hashlib.new('ripdemd160').hexdigest()
-        'PSA_ALG_SHA_1': lambda data: hashlib.sha1(data).hexdigest(),
-        'PSA_ALG_SHA_224': lambda data: hashlib.sha224(data).hexdigest(),
-        'PSA_ALG_SHA_256': lambda data: hashlib.sha256(data).hexdigest(),
-        'PSA_ALG_SHA_384': lambda data: hashlib.sha384(data).hexdigest(),
-        'PSA_ALG_SHA_512': lambda data: hashlib.sha512(data).hexdigest(),
-        'PSA_ALG_SHA_512_224': None, #lambda data: hashlib.new('sha512_224').hexdigest()
-        'PSA_ALG_SHA_512_256': None, #lambda data: hashlib.new('sha512_256').hexdigest()
-        'PSA_ALG_SHA3_224': None, #lambda data: hashlib.sha3_224(data).hexdigest(),
-        'PSA_ALG_SHA3_256': None, #lambda data: hashlib.sha3_256(data).hexdigest(),
-        'PSA_ALG_SHA3_384': None, #lambda data: hashlib.sha3_384(data).hexdigest(),
-        'PSA_ALG_SHA3_512': None, #lambda data: hashlib.sha3_512(data).hexdigest(),
-        'PSA_ALG_SHAKE256_512': None, #lambda data: hashlib.shake_256(data).hexdigest(64),
-    } #type: Dict[str, Optional[Callable[[bytes], str]]]
-
-    @staticmethod
-    def one_test_case(alg: crypto_knowledge.Algorithm,
-                      function: str, note: str,
-                      arguments: List[str]) -> test_case.TestCase:
-        """Construct one test case involving a hash."""
-        tc = test_case.TestCase()
-        tc.set_description('{}{} {}'
-                           .format(function,
-                                   ' ' + note if note else '',
-                                   alg.short_expression()))
-        tc.set_dependencies(psa_low_level_dependencies(alg.expression))
-        tc.set_function(function)
-        tc.set_arguments([alg.expression] +
-                         ['"{}"'.format(arg) for arg in arguments])
-        return tc
-
-    def test_cases_for_hash(self,
-                            alg: crypto_knowledge.Algorithm
-                            ) -> Iterator[test_case.TestCase]:
-        """Enumerate all test cases for one hash algorithm."""
-        calc = self.CALCULATE[alg.expression]
-        if calc is None:
-            return # not implemented yet
-
-        short = b'abc'
-        hash_short = calc(short)
-        long = (b'Hello, world. Here are 16 unprintable bytes: ['
-                b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a'
-                b'\x80\x81\x82\x83\xfe\xff]. '
-                b' This message was brought to you by a natural intelligence. '
-                b' If you can read this, good luck with your debugging!')
-        hash_long = calc(long)
-
-        yield self.one_test_case(alg, 'hash_empty', '', [calc(b'')])
-        yield self.one_test_case(alg, 'hash_valid_one_shot', '',
-                                 [short.hex(), hash_short])
-        for n in [0, 1, 64, len(long) - 1, len(long)]:
-            yield self.one_test_case(alg, 'hash_valid_multipart',
-                                     '{} + {}'.format(n, len(long) - n),
-                                     [long[:n].hex(), calc(long[:n]),
-                                      long[n:].hex(), hash_long])
-
-    def all_test_cases(self) -> Iterator[test_case.TestCase]:
-        """Enumerate all test cases for all hash algorithms."""
-        for alg in self.algorithms:
-            yield from self.test_cases_for_hash(alg)
diff --git a/scripts/mbedtls_dev/crypto_knowledge.py b/scripts/mbedtls_dev/crypto_knowledge.py
deleted file mode 100644
index ebfd55c..0000000
--- a/scripts/mbedtls_dev/crypto_knowledge.py
+++ /dev/null
@@ -1,568 +0,0 @@
-"""Knowledge about cryptographic mechanisms implemented in Mbed TLS.
-
-This module is entirely based on the PSA API.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-import enum
-import re
-from typing import FrozenSet, Iterable, List, Optional, Tuple, Dict
-
-from .asymmetric_key_data import ASYMMETRIC_KEY_DATA
-
-
-def short_expression(original: str, level: int = 0) -> str:
-    """Abbreviate the expression, keeping it human-readable.
-
-    If `level` is 0, just remove parts that are implicit from context,
-    such as a leading ``PSA_KEY_TYPE_``.
-    For larger values of `level`, also abbreviate some names in an
-    unambiguous, but ad hoc way.
-    """
-    short = original
-    short = re.sub(r'\bPSA_(?:ALG|DH_FAMILY|ECC_FAMILY|KEY_[A-Z]+)_', r'', short)
-    short = re.sub(r' +', r'', short)
-    if level >= 1:
-        short = re.sub(r'PUBLIC_KEY\b', r'PUB', short)
-        short = re.sub(r'KEY_PAIR\b', r'PAIR', short)
-        short = re.sub(r'\bBRAINPOOL_P', r'BP', short)
-        short = re.sub(r'\bMONTGOMERY\b', r'MGM', short)
-        short = re.sub(r'AEAD_WITH_SHORTENED_TAG\b', r'AEAD_SHORT', short)
-        short = re.sub(r'\bDETERMINISTIC_', r'DET_', short)
-        short = re.sub(r'\bKEY_AGREEMENT\b', r'KA', short)
-        short = re.sub(r'_PSK_TO_MS\b', r'_PSK2MS', short)
-    return short
-
-
-BLOCK_CIPHERS = frozenset(['AES', 'ARIA', 'CAMELLIA', 'DES'])
-BLOCK_MAC_MODES = frozenset(['CBC_MAC', 'CMAC'])
-BLOCK_CIPHER_MODES = frozenset([
-    'CTR', 'CFB', 'OFB', 'XTS', 'CCM_STAR_NO_TAG',
-    'ECB_NO_PADDING', 'CBC_NO_PADDING', 'CBC_PKCS7',
-])
-BLOCK_AEAD_MODES = frozenset(['CCM', 'GCM'])
-
-class EllipticCurveCategory(enum.Enum):
-    """Categorization of elliptic curve families.
-
-    The category of a curve determines what algorithms are defined over it.
-    """
-
-    SHORT_WEIERSTRASS = 0
-    MONTGOMERY = 1
-    TWISTED_EDWARDS = 2
-
-    @staticmethod
-    def from_family(family: str) -> 'EllipticCurveCategory':
-        if family == 'PSA_ECC_FAMILY_MONTGOMERY':
-            return EllipticCurveCategory.MONTGOMERY
-        if family == 'PSA_ECC_FAMILY_TWISTED_EDWARDS':
-            return EllipticCurveCategory.TWISTED_EDWARDS
-        # Default to SW, which most curves belong to.
-        return EllipticCurveCategory.SHORT_WEIERSTRASS
-
-
-class KeyType:
-    """Knowledge about a PSA key type."""
-
-    def __init__(self, name: str, params: Optional[Iterable[str]] = None) -> None:
-        """Analyze a key type.
-
-        The key type must be specified in PSA syntax. In its simplest form,
-        `name` is a string 'PSA_KEY_TYPE_xxx' which is the name of a PSA key
-        type macro. For key types that take arguments, the arguments can
-        be passed either through the optional argument `params` or by
-        passing an expression of the form 'PSA_KEY_TYPE_xxx(param1, ...)'
-        in `name` as a string.
-        """
-
-        self.name = name.strip()
-        """The key type macro name (``PSA_KEY_TYPE_xxx``).
-
-        For key types constructed from a macro with arguments, this is the
-        name of the macro, and the arguments are in `self.params`.
-        """
-        if params is None:
-            if '(' in self.name:
-                m = re.match(r'(\w+)\s*\((.*)\)\Z', self.name)
-                assert m is not None
-                self.name = m.group(1)
-                params = m.group(2).split(',')
-        self.params = (None if params is None else
-                       [param.strip() for param in params])
-        """The parameters of the key type, if there are any.
-
-        None if the key type is a macro without arguments.
-        """
-        assert re.match(r'PSA_KEY_TYPE_\w+\Z', self.name)
-
-        self.expression = self.name
-        """A C expression whose value is the key type encoding."""
-        if self.params is not None:
-            self.expression += '(' + ', '.join(self.params) + ')'
-
-        m = re.match(r'PSA_KEY_TYPE_(\w+)', self.name)
-        assert m
-        self.head = re.sub(r'_(?:PUBLIC_KEY|KEY_PAIR)\Z', r'', m.group(1))
-        """The key type macro name, with common prefixes and suffixes stripped."""
-
-        self.private_type = re.sub(r'_PUBLIC_KEY\Z', r'_KEY_PAIR', self.name)
-        """The key type macro name for the corresponding key pair type.
-
-        For everything other than a public key type, this is the same as
-        `self.name`.
-        """
-
-    def short_expression(self, level: int = 0) -> str:
-        """Abbreviate the expression, keeping it human-readable.
-
-        See `crypto_knowledge.short_expression`.
-        """
-        return short_expression(self.expression, level=level)
-
-    def is_public(self) -> bool:
-        """Whether the key type is for public keys."""
-        return self.name.endswith('_PUBLIC_KEY')
-
-    DH_KEY_SIZES = {
-        'PSA_DH_FAMILY_RFC7919': (2048, 3072, 4096, 6144, 8192),
-    } # type: Dict[str, Tuple[int, ...]]
-    ECC_KEY_SIZES = {
-        'PSA_ECC_FAMILY_SECP_K1': (192, 225, 256),
-        'PSA_ECC_FAMILY_SECP_R1': (224, 256, 384, 521),
-        'PSA_ECC_FAMILY_SECP_R2': (160,),
-        'PSA_ECC_FAMILY_SECT_K1': (163, 233, 239, 283, 409, 571),
-        'PSA_ECC_FAMILY_SECT_R1': (163, 233, 283, 409, 571),
-        'PSA_ECC_FAMILY_SECT_R2': (163,),
-        'PSA_ECC_FAMILY_BRAINPOOL_P_R1': (160, 192, 224, 256, 320, 384, 512),
-        'PSA_ECC_FAMILY_MONTGOMERY': (255, 448),
-        'PSA_ECC_FAMILY_TWISTED_EDWARDS': (255, 448),
-    } # type: Dict[str, Tuple[int, ...]]
-    KEY_TYPE_SIZES = {
-        'PSA_KEY_TYPE_AES': (128, 192, 256), # exhaustive
-        'PSA_KEY_TYPE_ARIA': (128, 192, 256), # exhaustive
-        'PSA_KEY_TYPE_CAMELLIA': (128, 192, 256), # exhaustive
-        'PSA_KEY_TYPE_CHACHA20': (256,), # exhaustive
-        'PSA_KEY_TYPE_DERIVE': (120, 128), # sample
-        'PSA_KEY_TYPE_DES': (64, 128, 192), # exhaustive
-        'PSA_KEY_TYPE_HMAC': (128, 160, 224, 256, 384, 512), # standard size for each supported hash
-        'PSA_KEY_TYPE_PASSWORD': (48, 168, 336), # sample
-        'PSA_KEY_TYPE_PASSWORD_HASH': (128, 256), # sample
-        'PSA_KEY_TYPE_PEPPER': (128, 256), # sample
-        'PSA_KEY_TYPE_RAW_DATA': (8, 40, 128), # sample
-        'PSA_KEY_TYPE_RSA_KEY_PAIR': (1024, 1536), # small sample
-    } # type: Dict[str, Tuple[int, ...]]
-    def sizes_to_test(self) -> Tuple[int, ...]:
-        """Return a tuple of key sizes to test.
-
-        For key types that only allow a single size, or only a small set of
-        sizes, these are all the possible sizes. For key types that allow a
-        wide range of sizes, these are a representative sample of sizes,
-        excluding large sizes for which a typical resource-constrained platform
-        may run out of memory.
-        """
-        if self.private_type == 'PSA_KEY_TYPE_ECC_KEY_PAIR':
-            assert self.params is not None
-            return self.ECC_KEY_SIZES[self.params[0]]
-        if self.private_type == 'PSA_KEY_TYPE_DH_KEY_PAIR':
-            assert self.params is not None
-            return self.DH_KEY_SIZES[self.params[0]]
-        return self.KEY_TYPE_SIZES[self.private_type]
-
-    # "48657265006973206b6579a064617461"
-    DATA_BLOCK = b'Here\000is key\240data'
-    def key_material(self, bits: int) -> bytes:
-        """Return a byte string containing suitable key material with the given bit length.
-
-        Use the PSA export representation. The resulting byte string is one that
-        can be obtained with the following code:
-        ```
-        psa_set_key_type(&attributes, `self.expression`);
-        psa_set_key_bits(&attributes, `bits`);
-        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT);
-        psa_generate_key(&attributes, &id);
-        psa_export_key(id, `material`, ...);
-        ```
-        """
-        if self.expression in ASYMMETRIC_KEY_DATA:
-            if bits not in ASYMMETRIC_KEY_DATA[self.expression]:
-                raise ValueError('No key data for {}-bit {}'
-                                 .format(bits, self.expression))
-            return ASYMMETRIC_KEY_DATA[self.expression][bits]
-        if bits % 8 != 0:
-            raise ValueError('Non-integer number of bytes: {} bits for {}'
-                             .format(bits, self.expression))
-        length = bits // 8
-        if self.name == 'PSA_KEY_TYPE_DES':
-            # "644573206b457901644573206b457902644573206b457904"
-            des3 = b'dEs kEy\001dEs kEy\002dEs kEy\004'
-            return des3[:length]
-        return b''.join([self.DATA_BLOCK] * (length // len(self.DATA_BLOCK)) +
-                        [self.DATA_BLOCK[:length % len(self.DATA_BLOCK)]])
-
-    def can_do(self, alg: 'Algorithm') -> bool:
-        """Whether this key type can be used for operations with the given algorithm.
-
-        This function does not currently handle key derivation or PAKE.
-        """
-        #pylint: disable=too-many-branches,too-many-return-statements
-        if not alg.is_valid_for_operation():
-            return False
-        if self.head == 'HMAC' and alg.head == 'HMAC':
-            return True
-        if self.head == 'DES':
-            # 64-bit block ciphers only allow a reduced set of modes.
-            return alg.head in [
-                'CBC_NO_PADDING', 'CBC_PKCS7',
-                'ECB_NO_PADDING',
-            ]
-        if self.head in BLOCK_CIPHERS and \
-           alg.head in frozenset.union(BLOCK_MAC_MODES,
-                                       BLOCK_CIPHER_MODES,
-                                       BLOCK_AEAD_MODES):
-            if alg.head in ['CMAC', 'OFB'] and \
-               self.head in ['ARIA', 'CAMELLIA']:
-                return False # not implemented in Mbed TLS
-            return True
-        if self.head == 'CHACHA20' and alg.head == 'CHACHA20_POLY1305':
-            return True
-        if self.head in {'ARC4', 'CHACHA20'} and \
-           alg.head == 'STREAM_CIPHER':
-            return True
-        if self.head == 'RSA' and alg.head.startswith('RSA_'):
-            return True
-        if alg.category == AlgorithmCategory.KEY_AGREEMENT and \
-           self.is_public():
-            # The PSA API does not use public key objects in key agreement
-            # operations: it imports the public key as a formatted byte string.
-            # So a public key object with a key agreement algorithm is not
-            # a valid combination.
-            return False
-        if alg.is_invalid_key_agreement_with_derivation():
-            return False
-        if self.head == 'ECC':
-            assert self.params is not None
-            eccc = EllipticCurveCategory.from_family(self.params[0])
-            if alg.head == 'ECDH' and \
-               eccc in {EllipticCurveCategory.SHORT_WEIERSTRASS,
-                        EllipticCurveCategory.MONTGOMERY}:
-                return True
-            if alg.head == 'ECDSA' and \
-               eccc == EllipticCurveCategory.SHORT_WEIERSTRASS:
-                return True
-            if alg.head in {'PURE_EDDSA', 'EDDSA_PREHASH'} and \
-               eccc == EllipticCurveCategory.TWISTED_EDWARDS:
-                return True
-        if self.head == 'DH' and alg.head == 'FFDH':
-            return True
-        return False
-
-
-class AlgorithmCategory(enum.Enum):
-    """PSA algorithm categories."""
-    # The numbers are aligned with the category bits in numerical values of
-    # algorithms.
-    HASH = 2
-    MAC = 3
-    CIPHER = 4
-    AEAD = 5
-    SIGN = 6
-    ASYMMETRIC_ENCRYPTION = 7
-    KEY_DERIVATION = 8
-    KEY_AGREEMENT = 9
-    PAKE = 10
-
-    def requires_key(self) -> bool:
-        """Whether operations in this category are set up with a key."""
-        return self not in {self.HASH, self.KEY_DERIVATION}
-
-    def is_asymmetric(self) -> bool:
-        """Whether operations in this category involve asymmetric keys."""
-        return self in {
-            self.SIGN,
-            self.ASYMMETRIC_ENCRYPTION,
-            self.KEY_AGREEMENT
-        }
-
-
-class AlgorithmNotRecognized(Exception):
-    def __init__(self, expr: str) -> None:
-        super().__init__('Algorithm not recognized: ' + expr)
-        self.expr = expr
-
-
-class Algorithm:
-    """Knowledge about a PSA algorithm."""
-
-    @staticmethod
-    def determine_base(expr: str) -> str:
-        """Return an expression for the "base" of the algorithm.
-
-        This strips off variants of algorithms such as MAC truncation.
-
-        This function does not attempt to detect invalid inputs.
-        """
-        m = re.match(r'PSA_ALG_(?:'
-                     r'(?:TRUNCATED|AT_LEAST_THIS_LENGTH)_MAC|'
-                     r'AEAD_WITH_(?:SHORTENED|AT_LEAST_THIS_LENGTH)_TAG'
-                     r')\((.*),[^,]+\)\Z', expr)
-        if m:
-            expr = m.group(1)
-        return expr
-
-    @staticmethod
-    def determine_head(expr: str) -> str:
-        """Return the head of an algorithm expression.
-
-        The head is the first (outermost) constructor, without its PSA_ALG_
-        prefix, and with some normalization of similar algorithms.
-        """
-        m = re.match(r'PSA_ALG_(?:DETERMINISTIC_)?(\w+)', expr)
-        if not m:
-            raise AlgorithmNotRecognized(expr)
-        head = m.group(1)
-        if head == 'KEY_AGREEMENT':
-            m = re.match(r'PSA_ALG_KEY_AGREEMENT\s*\(\s*PSA_ALG_(\w+)', expr)
-            if not m:
-                raise AlgorithmNotRecognized(expr)
-            head = m.group(1)
-        head = re.sub(r'_ANY\Z', r'', head)
-        if re.match(r'ED[0-9]+PH\Z', head):
-            head = 'EDDSA_PREHASH'
-        return head
-
-    CATEGORY_FROM_HEAD = {
-        'SHA': AlgorithmCategory.HASH,
-        'SHAKE256_512': AlgorithmCategory.HASH,
-        'MD': AlgorithmCategory.HASH,
-        'RIPEMD': AlgorithmCategory.HASH,
-        'ANY_HASH': AlgorithmCategory.HASH,
-        'HMAC': AlgorithmCategory.MAC,
-        'STREAM_CIPHER': AlgorithmCategory.CIPHER,
-        'CHACHA20_POLY1305': AlgorithmCategory.AEAD,
-        'DSA': AlgorithmCategory.SIGN,
-        'ECDSA': AlgorithmCategory.SIGN,
-        'EDDSA': AlgorithmCategory.SIGN,
-        'PURE_EDDSA': AlgorithmCategory.SIGN,
-        'RSA_PSS': AlgorithmCategory.SIGN,
-        'RSA_PKCS1V15_SIGN': AlgorithmCategory.SIGN,
-        'RSA_PKCS1V15_CRYPT': AlgorithmCategory.ASYMMETRIC_ENCRYPTION,
-        'RSA_OAEP': AlgorithmCategory.ASYMMETRIC_ENCRYPTION,
-        'HKDF': AlgorithmCategory.KEY_DERIVATION,
-        'TLS12_PRF': AlgorithmCategory.KEY_DERIVATION,
-        'TLS12_PSK_TO_MS': AlgorithmCategory.KEY_DERIVATION,
-        'TLS12_ECJPAKE_TO_PMS': AlgorithmCategory.KEY_DERIVATION,
-        'PBKDF': AlgorithmCategory.KEY_DERIVATION,
-        'ECDH': AlgorithmCategory.KEY_AGREEMENT,
-        'FFDH': AlgorithmCategory.KEY_AGREEMENT,
-        # KEY_AGREEMENT(...) is a key derivation with a key agreement component
-        'KEY_AGREEMENT': AlgorithmCategory.KEY_DERIVATION,
-        'JPAKE': AlgorithmCategory.PAKE,
-    }
-    for x in BLOCK_MAC_MODES:
-        CATEGORY_FROM_HEAD[x] = AlgorithmCategory.MAC
-    for x in BLOCK_CIPHER_MODES:
-        CATEGORY_FROM_HEAD[x] = AlgorithmCategory.CIPHER
-    for x in BLOCK_AEAD_MODES:
-        CATEGORY_FROM_HEAD[x] = AlgorithmCategory.AEAD
-
-    def determine_category(self, expr: str, head: str) -> AlgorithmCategory:
-        """Return the category of the given algorithm expression.
-
-        This function does not attempt to detect invalid inputs.
-        """
-        prefix = head
-        while prefix:
-            if prefix in self.CATEGORY_FROM_HEAD:
-                return self.CATEGORY_FROM_HEAD[prefix]
-            if re.match(r'.*[0-9]\Z', prefix):
-                prefix = re.sub(r'_*[0-9]+\Z', r'', prefix)
-            else:
-                prefix = re.sub(r'_*[^_]*\Z', r'', prefix)
-        raise AlgorithmNotRecognized(expr)
-
-    @staticmethod
-    def determine_wildcard(expr) -> bool:
-        """Whether the given algorithm expression is a wildcard.
-
-        This function does not attempt to detect invalid inputs.
-        """
-        if re.search(r'\bPSA_ALG_ANY_HASH\b', expr):
-            return True
-        if re.search(r'_AT_LEAST_', expr):
-            return True
-        return False
-
-    def __init__(self, expr: str) -> None:
-        """Analyze an algorithm value.
-
-        The algorithm must be expressed as a C expression containing only
-        calls to PSA algorithm constructor macros and numeric literals.
-
-        This class is only programmed to handle valid expressions. Invalid
-        expressions may result in exceptions or in nonsensical results.
-        """
-        self.expression = re.sub(r'\s+', r'', expr)
-        self.base_expression = self.determine_base(self.expression)
-        self.head = self.determine_head(self.base_expression)
-        self.category = self.determine_category(self.base_expression, self.head)
-        self.is_wildcard = self.determine_wildcard(self.expression)
-
-    def get_key_agreement_derivation(self) -> Optional[str]:
-        """For a combined key agreement and key derivation algorithm, get the derivation part.
-
-        For anything else, return None.
-        """
-        if self.category != AlgorithmCategory.KEY_AGREEMENT:
-            return None
-        m = re.match(r'PSA_ALG_KEY_AGREEMENT\(\w+,\s*(.*)\)\Z', self.expression)
-        if not m:
-            return None
-        kdf_alg = m.group(1)
-        # Assume kdf_alg is either a valid KDF or 0.
-        if re.match(r'(?:0[Xx])?0+\s*\Z', kdf_alg):
-            return None
-        return kdf_alg
-
-    KEY_DERIVATIONS_INCOMPATIBLE_WITH_AGREEMENT = frozenset([
-        'PSA_ALG_TLS12_ECJPAKE_TO_PMS', # secret input in specific format
-    ])
-    def is_valid_key_agreement_with_derivation(self) -> bool:
-        """Whether this is a valid combined key agreement and key derivation algorithm."""
-        kdf_alg = self.get_key_agreement_derivation()
-        if kdf_alg is None:
-            return False
-        return kdf_alg not in self.KEY_DERIVATIONS_INCOMPATIBLE_WITH_AGREEMENT
-
-    def is_invalid_key_agreement_with_derivation(self) -> bool:
-        """Whether this is an invalid combined key agreement and key derivation algorithm."""
-        kdf_alg = self.get_key_agreement_derivation()
-        if kdf_alg is None:
-            return False
-        return kdf_alg in self.KEY_DERIVATIONS_INCOMPATIBLE_WITH_AGREEMENT
-
-    def short_expression(self, level: int = 0) -> str:
-        """Abbreviate the expression, keeping it human-readable.
-
-        See `crypto_knowledge.short_expression`.
-        """
-        return short_expression(self.expression, level=level)
-
-    HASH_LENGTH = {
-        'PSA_ALG_MD5': 16,
-        'PSA_ALG_SHA_1': 20,
-    }
-    HASH_LENGTH_BITS_RE = re.compile(r'([0-9]+)\Z')
-    @classmethod
-    def hash_length(cls, alg: str) -> int:
-        """The length of the given hash algorithm, in bytes."""
-        if alg in cls.HASH_LENGTH:
-            return cls.HASH_LENGTH[alg]
-        m = cls.HASH_LENGTH_BITS_RE.search(alg)
-        if m:
-            return int(m.group(1)) // 8
-        raise ValueError('Unknown hash length for ' + alg)
-
-    PERMITTED_TAG_LENGTHS = {
-        'PSA_ALG_CCM': frozenset([4, 6, 8, 10, 12, 14, 16]),
-        'PSA_ALG_CHACHA20_POLY1305': frozenset([16]),
-        'PSA_ALG_GCM': frozenset([4, 8, 12, 13, 14, 15, 16]),
-    }
-    MAC_LENGTH = {
-        'PSA_ALG_CBC_MAC': 16, # actually the block cipher length
-        'PSA_ALG_CMAC': 16, # actually the block cipher length
-    }
-    HMAC_RE = re.compile(r'PSA_ALG_HMAC\((.*)\)\Z')
-    @classmethod
-    def permitted_truncations(cls, base: str) -> FrozenSet[int]:
-        """Permitted output lengths for the given MAC or AEAD base algorithm.
-
-        For a MAC algorithm, this is the set of truncation lengths that
-        Mbed TLS supports.
-        For an AEAD algorithm, this is the set of truncation lengths that
-        are permitted by the algorithm specification.
-        """
-        if base in cls.PERMITTED_TAG_LENGTHS:
-            return cls.PERMITTED_TAG_LENGTHS[base]
-        max_length = cls.MAC_LENGTH.get(base, None)
-        if max_length is None:
-            m = cls.HMAC_RE.match(base)
-            if m:
-                max_length = cls.hash_length(m.group(1))
-        if max_length is None:
-            raise ValueError('Unknown permitted lengths for ' + base)
-        return frozenset(range(4, max_length + 1))
-
-    TRUNCATED_ALG_RE = re.compile(
-        r'(?P<face>PSA_ALG_(?:AEAD_WITH_SHORTENED_TAG|TRUNCATED_MAC))'
-        r'\((?P<base>.*),'
-        r'(?P<length>0[Xx][0-9A-Fa-f]+|[1-9][0-9]*|0[0-7]*)[LUlu]*\)\Z')
-    def is_invalid_truncation(self) -> bool:
-        """False for a MAC or AEAD algorithm truncated to an invalid length.
-
-        True for a MAC or AEAD algorithm truncated to a valid length or to
-        a length that cannot be determined. True for anything other than
-        a truncated MAC or AEAD.
-        """
-        m = self.TRUNCATED_ALG_RE.match(self.expression)
-        if m:
-            base = m.group('base')
-            to_length = int(m.group('length'), 0)
-            permitted_lengths = self.permitted_truncations(base)
-            if to_length not in permitted_lengths:
-                return True
-        return False
-
-    def is_valid_for_operation(self) -> bool:
-        """Whether this algorithm construction is valid for an operation.
-
-        This function assumes that the algorithm is constructed in a
-        "grammatically" correct way, and only rejects semantically invalid
-        combinations.
-        """
-        if self.is_wildcard:
-            return False
-        if self.is_invalid_truncation():
-            return False
-        return True
-
-    def can_do(self, category: AlgorithmCategory) -> bool:
-        """Whether this algorithm can perform operations in the given category.
-        """
-        if category == self.category:
-            return True
-        if category == AlgorithmCategory.KEY_DERIVATION and \
-           self.is_valid_key_agreement_with_derivation():
-            return True
-        return False
-
-    def usage_flags(self, public: bool = False) -> List[str]:
-        """The list of usage flags describing operations that can perform this algorithm.
-
-        If public is true, only return public-key operations, not private-key operations.
-        """
-        if self.category == AlgorithmCategory.HASH:
-            flags = []
-        elif self.category == AlgorithmCategory.MAC:
-            flags = ['SIGN_HASH', 'SIGN_MESSAGE',
-                     'VERIFY_HASH', 'VERIFY_MESSAGE']
-        elif self.category == AlgorithmCategory.CIPHER or \
-             self.category == AlgorithmCategory.AEAD:
-            flags = ['DECRYPT', 'ENCRYPT']
-        elif self.category == AlgorithmCategory.SIGN:
-            flags = ['VERIFY_HASH', 'VERIFY_MESSAGE']
-            if not public:
-                flags += ['SIGN_HASH', 'SIGN_MESSAGE']
-        elif self.category == AlgorithmCategory.ASYMMETRIC_ENCRYPTION:
-            flags = ['ENCRYPT']
-            if not public:
-                flags += ['DECRYPT']
-        elif self.category == AlgorithmCategory.KEY_DERIVATION or \
-             self.category == AlgorithmCategory.KEY_AGREEMENT:
-            flags = ['DERIVE']
-        else:
-            raise AlgorithmNotRecognized(self.expression)
-        return ['PSA_KEY_USAGE_' + flag for flag in flags]
diff --git a/scripts/mbedtls_dev/ecp.py b/scripts/mbedtls_dev/ecp.py
deleted file mode 100644
index b40f3b1..0000000
--- a/scripts/mbedtls_dev/ecp.py
+++ /dev/null
@@ -1,875 +0,0 @@
-"""Framework classes for generation of ecp test cases."""
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-from typing import List
-
-from . import test_data_generation
-from . import bignum_common
-
-
-class EcpTarget(test_data_generation.BaseTarget):
-    #pylint: disable=abstract-method, too-few-public-methods
-    """Target for ecp test case generation."""
-    target_basename = 'test_suite_ecp.generated'
-
-
-class EcpP192R1Raw(bignum_common.ModOperationCommon,
-                   EcpTarget):
-    """Test cases for ECP P192 fast reduction."""
-    symbol = "-"
-    test_function = "ecp_mod_p_generic_raw"
-    test_name = "ecp_mod_p192_raw"
-    input_style = "fixed"
-    arity = 1
-    dependencies = ["MBEDTLS_ECP_DP_SECP192R1_ENABLED",
-                    "MBEDTLS_ECP_NIST_OPTIM"]
-
-    moduli = ["fffffffffffffffffffffffffffffffeffffffffffffffff"] # type: List[str]
-
-    input_values = [
-        "0", "1",
-
-        # Modulus - 1
-        "fffffffffffffffffffffffffffffffefffffffffffffffe",
-
-        # Modulus + 1
-        "ffffffffffffffffffffffffffffffff0000000000000000",
-
-        # 2^192 - 1
-        "ffffffffffffffffffffffffffffffffffffffffffffffff",
-
-        # Maximum canonical P192 multiplication result
-        ("fffffffffffffffffffffffffffffffdfffffffffffffffc"
-         "000000000000000100000000000000040000000000000004"),
-
-        # Generate an overflow during reduction
-        ("00000000000000000000000000000001ffffffffffffffff"
-         "ffffffffffffffffffffffffffffffff0000000000000000"),
-
-        # Generate an overflow during carry reduction
-        ("ffffffffffffffff00000000000000010000000000000000"
-         "fffffffffffffffeffffffffffffffff0000000000000000"),
-
-        # First 8 number generated by random.getrandbits(384) - seed(2,2)
-        ("cf1822ffbc6887782b491044d5e341245c6e433715ba2bdd"
-         "177219d30e7a269fd95bafc8f2a4d27bdcf4bb99f4bea973"),
-        ("ffed9235288bc781ae66267594c9c9500925e4749b575bd1"
-         "3653f8dd9b1f282e4067c3584ee207f8da94e3e8ab73738f"),
-        ("ef8acd128b4f2fc15f3f57ebf30b94fa82523e86feac7eb7"
-         "dc38f519b91751dacdbd47d364be8049a372db8f6e405d93"),
-        ("e8624fab5186ee32ee8d7ee9770348a05d300cb90706a045"
-         "defc044a09325626e6b58de744ab6cce80877b6f71e1f6d2"),
-        ("2d3d854e061b90303b08c6e33c7295782d6c797f8f7d9b78"
-         "2a1be9cd8697bbd0e2520e33e44c50556c71c4a66148a86f"),
-        ("fec3f6b32e8d4b8a8f54f8ceacaab39e83844b40ffa9b9f1"
-         "5c14bc4a829e07b0829a48d422fe99a22c70501e533c9135"),
-        ("97eeab64ca2ce6bc5d3fd983c34c769fe89204e2e8168561"
-         "867e5e15bc01bfce6a27e0dfcbf8754472154e76e4c11ab2"),
-        ("bd143fa9b714210c665d7435c1066932f4767f26294365b2"
-         "721dea3bf63f23d0dbe53fcafb2147df5ca495fa5a91c89b"),
-
-        # Next 2 number generated by random.getrandbits(192)
-        "47733e847d718d733ff98ff387c56473a7a83ee0761ebfd2",
-        "cbd4d3e2d4dec9ef83f0be4e80371eb97f81375eecc1cb63"
-    ]
-
-    @property
-    def arg_a(self) -> str:
-        return super().format_arg('{:x}'.format(self.int_a)).zfill(2 * self.hex_digits)
-
-    def result(self) -> List[str]:
-        result = self.int_a % self.int_n
-        return [self.format_result(result)]
-
-    @property
-    def is_valid(self) -> bool:
-        return True
-
-    def arguments(self)-> List[str]:
-        args = super().arguments()
-        return  ["MBEDTLS_ECP_DP_SECP192R1"] + args
-
-
-class EcpP224R1Raw(bignum_common.ModOperationCommon,
-                   EcpTarget):
-    """Test cases for ECP P224 fast reduction."""
-    symbol = "-"
-    test_function = "ecp_mod_p_generic_raw"
-    test_name = "ecp_mod_p224_raw"
-    input_style = "arch_split"
-    arity = 1
-    dependencies = ["MBEDTLS_ECP_DP_SECP224R1_ENABLED",
-                    "MBEDTLS_ECP_NIST_OPTIM"]
-
-    moduli = ["ffffffffffffffffffffffffffffffff000000000000000000000001"] # type: List[str]
-
-    input_values = [
-        "0", "1",
-
-        # Modulus - 1
-        "ffffffffffffffffffffffffffffffff000000000000000000000000",
-
-        # Modulus + 1
-        "ffffffffffffffffffffffffffffffff000000000000000000000002",
-
-        # 2^224 - 1
-        "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
-
-        # Maximum canonical P224 multiplication result
-        ("fffffffffffffffffffffffffffffffe000000000000000000000000"
-         "00000001000000000000000000000000000000000000000000000000"),
-
-        # Generate an overflow during reduction
-        ("00000000000000000000000000010000000070000000002000001000"
-         "ffffffffffff9fffffffffe00000efff000070000000002000001003"),
-
-        # Generate an underflow during reduction
-        ("00000001000000000000000000000000000000000000000000000000"
-         "00000000000dc0000000000000000001000000010000000100000003"),
-
-        # First 8 number generated by random.getrandbits(448) - seed(2,2)
-        ("da94e3e8ab73738fcf1822ffbc6887782b491044d5e341245c6e4337"
-         "15ba2bdd177219d30e7a269fd95bafc8f2a4d27bdcf4bb99f4bea973"),
-        ("cdbd47d364be8049a372db8f6e405d93ffed9235288bc781ae662675"
-         "94c9c9500925e4749b575bd13653f8dd9b1f282e4067c3584ee207f8"),
-        ("defc044a09325626e6b58de744ab6cce80877b6f71e1f6d2ef8acd12"
-         "8b4f2fc15f3f57ebf30b94fa82523e86feac7eb7dc38f519b91751da"),
-        ("2d6c797f8f7d9b782a1be9cd8697bbd0e2520e33e44c50556c71c4a6"
-         "6148a86fe8624fab5186ee32ee8d7ee9770348a05d300cb90706a045"),
-        ("8f54f8ceacaab39e83844b40ffa9b9f15c14bc4a829e07b0829a48d4"
-         "22fe99a22c70501e533c91352d3d854e061b90303b08c6e33c729578"),
-        ("97eeab64ca2ce6bc5d3fd983c34c769fe89204e2e8168561867e5e15"
-         "bc01bfce6a27e0dfcbf8754472154e76e4c11ab2fec3f6b32e8d4b8a"),
-        ("a7a83ee0761ebfd2bd143fa9b714210c665d7435c1066932f4767f26"
-         "294365b2721dea3bf63f23d0dbe53fcafb2147df5ca495fa5a91c89b"),
-        ("74667bffe202849da9643a295a9ac6decbd4d3e2d4dec9ef83f0be4e"
-         "80371eb97f81375eecc1cb6347733e847d718d733ff98ff387c56473"),
-
-        # Next 2 number generated by random.getrandbits(224)
-        "eb9ac688b9d39cca91551e8259cc60b17604e4b4e73695c3e652c71a",
-        "f0caeef038c89b38a8acb5137c9260dc74e088a9b9492f258ebdbfe3"
-    ]
-
-    @property
-    def arg_a(self) -> str:
-        limbs = 2 * bignum_common.bits_to_limbs(224, self.bits_in_limb)
-        hex_digits = bignum_common.hex_digits_for_limb(limbs, self.bits_in_limb)
-        return super().format_arg('{:x}'.format(self.int_a)).zfill(hex_digits)
-
-    def result(self) -> List[str]:
-        result = self.int_a % self.int_n
-        return [self.format_result(result)]
-
-    @property
-    def is_valid(self) -> bool:
-        return True
-
-    def arguments(self)-> List[str]:
-        args = super().arguments()
-        return  ["MBEDTLS_ECP_DP_SECP224R1"] + args
-
-
-class EcpP256R1Raw(bignum_common.ModOperationCommon,
-                   EcpTarget):
-    """Test cases for ECP P256 fast reduction."""
-    symbol = "-"
-    test_function = "ecp_mod_p_generic_raw"
-    test_name = "ecp_mod_p256_raw"
-    input_style = "fixed"
-    arity = 1
-    dependencies = ["MBEDTLS_ECP_DP_SECP256R1_ENABLED",
-                    "MBEDTLS_ECP_NIST_OPTIM"]
-
-    moduli = ["ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"] # type: List[str]
-
-    input_values = [
-        "0", "1",
-
-        # Modulus - 1
-        "ffffffff00000001000000000000000000000000fffffffffffffffffffffffe",
-
-        # Modulus + 1
-        "ffffffff00000001000000000000000000000001000000000000000000000000",
-
-        # 2^256 - 1
-        "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
-
-        # Maximum canonical P256 multiplication result
-        ("fffffffe00000002fffffffe0000000100000001fffffffe00000001fffffffc"
-         "00000003fffffffcfffffffffffffffffffffffc000000000000000000000004"),
-
-        # Generate an overflow during reduction
-        ("0000000000000000000000010000000000000000000000000000000000000000"
-         "00000000000000000000000000000000000000000000000000000000ffffffff"),
-
-        # Generate an underflow during reduction
-        ("0000000000000000000000000000000000000000000000000000000000000010"
-         "ffffffff00000000000000000000000000000000000000000000000000000000"),
-
-        # Generate an overflow during carry reduction
-        ("aaaaaaaa00000000000000000000000000000000000000000000000000000000"
-         "00000000000000000000000000000000aaaaaaacaaaaaaaaaaaaaaaa00000000"),
-
-        # Generate an underflow during carry reduction
-        ("000000000000000000000001ffffffff00000000000000000000000000000000"
-         "0000000000000000000000000000000000000002000000020000000100000002"),
-
-        # First 8 number generated by random.getrandbits(512) - seed(2,2)
-        ("4067c3584ee207f8da94e3e8ab73738fcf1822ffbc6887782b491044d5e34124"
-         "5c6e433715ba2bdd177219d30e7a269fd95bafc8f2a4d27bdcf4bb99f4bea973"),
-        ("82523e86feac7eb7dc38f519b91751dacdbd47d364be8049a372db8f6e405d93"
-         "ffed9235288bc781ae66267594c9c9500925e4749b575bd13653f8dd9b1f282e"),
-        ("e8624fab5186ee32ee8d7ee9770348a05d300cb90706a045defc044a09325626"
-         "e6b58de744ab6cce80877b6f71e1f6d2ef8acd128b4f2fc15f3f57ebf30b94fa"),
-        ("829a48d422fe99a22c70501e533c91352d3d854e061b90303b08c6e33c729578"
-         "2d6c797f8f7d9b782a1be9cd8697bbd0e2520e33e44c50556c71c4a66148a86f"),
-        ("e89204e2e8168561867e5e15bc01bfce6a27e0dfcbf8754472154e76e4c11ab2"
-         "fec3f6b32e8d4b8a8f54f8ceacaab39e83844b40ffa9b9f15c14bc4a829e07b0"),
-        ("bd143fa9b714210c665d7435c1066932f4767f26294365b2721dea3bf63f23d0"
-         "dbe53fcafb2147df5ca495fa5a91c89b97eeab64ca2ce6bc5d3fd983c34c769f"),
-        ("74667bffe202849da9643a295a9ac6decbd4d3e2d4dec9ef83f0be4e80371eb9"
-         "7f81375eecc1cb6347733e847d718d733ff98ff387c56473a7a83ee0761ebfd2"),
-        ("d08f1bb2531d6460f0caeef038c89b38a8acb5137c9260dc74e088a9b9492f25"
-         "8ebdbfe3eb9ac688b9d39cca91551e8259cc60b17604e4b4e73695c3e652c71a"),
-
-        # Next 2 number generated by random.getrandbits(256)
-        "c5e2486c44a4a8f69dc8db48e86ec9c6e06f291b2a838af8d5c44a4eb3172062",
-        "d4c0dca8b4c9e755cc9c3adcf515a8234da4daeb4f3f87777ad1f45ae9500ec9"
-    ]
-
-    @property
-    def arg_a(self) -> str:
-        return super().format_arg('{:x}'.format(self.int_a)).zfill(2 * self.hex_digits)
-
-    def result(self) -> List[str]:
-        result = self.int_a % self.int_n
-        return [self.format_result(result)]
-
-    @property
-    def is_valid(self) -> bool:
-        return True
-
-    def arguments(self)-> List[str]:
-        args = super().arguments()
-        return  ["MBEDTLS_ECP_DP_SECP256R1"] + args
-
-
-class EcpP384R1Raw(bignum_common.ModOperationCommon,
-                   EcpTarget):
-    """Test cases for ECP P384 fast reduction."""
-    test_function = "ecp_mod_p_generic_raw"
-    test_name = "ecp_mod_p384_raw"
-    input_style = "fixed"
-    arity = 1
-    dependencies = ["MBEDTLS_ECP_DP_SECP384R1_ENABLED",
-                    "MBEDTLS_ECP_NIST_OPTIM"]
-
-    moduli = [("ffffffffffffffffffffffffffffffffffffffffffffffff"
-               "fffffffffffffffeffffffff0000000000000000ffffffff")
-             ] # type: List[str]
-
-    input_values = [
-        "0", "1",
-
-        # Modulus - 1
-        ("ffffffffffffffffffffffffffffffffffffffffffffffff"
-         "fffffffffffffffeffffffff0000000000000000fffffffe"),
-
-        # Modulus + 1
-        ("ffffffffffffffffffffffffffffffffffffffffffffffff"
-         "fffffffffffffffeffffffff000000000000000100000000"),
-
-        # 2^384 - 1
-        ("ffffffffffffffffffffffffffffffffffffffffffffffff"
-         "ffffffffffffffffffffffffffffffffffffffffffffffff"),
-
-        # Maximum canonical P384 multiplication result
-        ("ffffffffffffffffffffffffffffffffffffffffffffffff"
-         "fffffffffffffffdfffffffe0000000000000001fffffffc"
-         "000000000000000000000000000000010000000200000000"
-         "fffffffe000000020000000400000000fffffffc00000004"),
-
-        # Testing with overflow in A(12) + A(21) + A(20);
-        ("497811378624857a2c2af60d70583376545484cfae5c812f"
-         "e2999fc1abb51d18b559e8ca3b50aaf263fdf8f24bdfb98f"
-         "ffffffff20e65bf9099e4e73a5e8b517cf4fbeb8fd1750fd"
-         "ae6d43f2e53f82d5ffffffffffffffffcc6f1e06111c62e0"),
-
-        # Testing with underflow in A(13) + A(22) + A(23) - A(12) - A(20);
-        ("dfdd25e96777406b3c04b8c7b406f5fcf287e1e576003a09"
-         "2852a6fbe517f2712b68abef41dbd35183a0614fb7222606"
-         "ffffffff84396eee542f18a9189d94396c784059c17a9f18"
-         "f807214ef32f2f10ffffffff8a77fac20000000000000000"),
-
-        # Testing with overflow in A(23) + A(20) + A(19) - A(22);
-        ("783753f8a5afba6c1862eead1deb2fcdd907272be3ffd185"
-         "42b24a71ee8b26cab0aa33513610ff973042bbe1637cc9fc"
-         "99ad36c7f703514572cf4f5c3044469a8f5be6312c19e5d3"
-         "f8fc1ac6ffffffffffffffff8c86252400000000ffffffff"),
-
-        # Testing with underflow in A(23) + A(20) + A(19) - A(22);
-        ("65e1d2362fce922663b7fd517586e88842a9b4bd092e93e6"
-         "251c9c69f278cbf8285d99ae3b53da5ba36e56701e2b17c2"
-         "25f1239556c5f00117fa140218b46ebd8e34f50d0018701f"
-         "a8a0a5cc00000000000000004410bcb4ffffffff00000000"),
-
-        # Testing the second round of carry reduction
-        ("000000000000000000000000ffffffffffffffffffffffff"
-         "ffffffffffffffffffffffffffffffff0000000000000000"
-         "0000000000000000ffffffff000000000000000000000001"
-         "00000000000000000000000000000000ffffffff00000001"),
-
-        # First 8 number generated by random.getrandbits(768) - seed(2,2)
-        ("ffed9235288bc781ae66267594c9c9500925e4749b575bd1"
-         "3653f8dd9b1f282e4067c3584ee207f8da94e3e8ab73738f"
-         "cf1822ffbc6887782b491044d5e341245c6e433715ba2bdd"
-         "177219d30e7a269fd95bafc8f2a4d27bdcf4bb99f4bea973"),
-        ("e8624fab5186ee32ee8d7ee9770348a05d300cb90706a045"
-         "defc044a09325626e6b58de744ab6cce80877b6f71e1f6d2"
-         "ef8acd128b4f2fc15f3f57ebf30b94fa82523e86feac7eb7"
-         "dc38f519b91751dacdbd47d364be8049a372db8f6e405d93"),
-        ("fec3f6b32e8d4b8a8f54f8ceacaab39e83844b40ffa9b9f1"
-         "5c14bc4a829e07b0829a48d422fe99a22c70501e533c9135"
-         "2d3d854e061b90303b08c6e33c7295782d6c797f8f7d9b78"
-         "2a1be9cd8697bbd0e2520e33e44c50556c71c4a66148a86f"),
-        ("bd143fa9b714210c665d7435c1066932f4767f26294365b2"
-         "721dea3bf63f23d0dbe53fcafb2147df5ca495fa5a91c89b"
-         "97eeab64ca2ce6bc5d3fd983c34c769fe89204e2e8168561"
-         "867e5e15bc01bfce6a27e0dfcbf8754472154e76e4c11ab2"),
-        ("8ebdbfe3eb9ac688b9d39cca91551e8259cc60b17604e4b4"
-         "e73695c3e652c71a74667bffe202849da9643a295a9ac6de"
-         "cbd4d3e2d4dec9ef83f0be4e80371eb97f81375eecc1cb63"
-         "47733e847d718d733ff98ff387c56473a7a83ee0761ebfd2"),
-        ("d4c0dca8b4c9e755cc9c3adcf515a8234da4daeb4f3f8777"
-         "7ad1f45ae9500ec9c5e2486c44a4a8f69dc8db48e86ec9c6"
-         "e06f291b2a838af8d5c44a4eb3172062d08f1bb2531d6460"
-         "f0caeef038c89b38a8acb5137c9260dc74e088a9b9492f25"),
-        ("0227eeb7b9d7d01f5769da05d205bbfcc8c69069134bccd3"
-         "e1cf4f589f8e4ce0af29d115ef24bd625dd961e6830b54fa"
-         "7d28f93435339774bb1e386c4fd5079e681b8f5896838b76"
-         "9da59b74a6c3181c81e220df848b1df78feb994a81167346"),
-        ("d322a7353ead4efe440e2b4fda9c025a22f1a83185b98f5f"
-         "c11e60de1b343f52ea748db9e020307aaeb6db2c3a038a70"
-         "9779ac1f45e9dd320c855fdfa7251af0930cdbd30f0ad2a8"
-         "1b2d19a2beaa14a7ff3fe32a30ffc4eed0a7bd04e85bfcdd"),
-
-        # Next 2 number generated by random.getrandbits(384)
-        ("5c3747465cc36c270e8a35b10828d569c268a20eb78ac332"
-         "e5e138e26c4454b90f756132e16dce72f18e859835e1f291"),
-        ("eb2b5693babb7fbb0a76c196067cfdcb11457d9cf45e2fa0"
-         "1d7f4275153924800600571fac3a5b263fdf57cd2c006497")
-    ]
-
-    @property
-    def arg_a(self) -> str:
-        return super().format_arg('{:x}'.format(self.int_a)).zfill(2 * self.hex_digits)
-
-    def result(self) -> List[str]:
-        result = self.int_a % self.int_n
-        return [self.format_result(result)]
-
-    @property
-    def is_valid(self) -> bool:
-        return True
-
-    def arguments(self)-> List[str]:
-        args = super().arguments()
-        return  ["MBEDTLS_ECP_DP_SECP384R1"] + args
-
-
-class EcpP521R1Raw(bignum_common.ModOperationCommon,
-                   EcpTarget):
-    """Test cases for ECP P521 fast reduction."""
-    test_function = "ecp_mod_p_generic_raw"
-    test_name = "ecp_mod_p521_raw"
-    input_style = "arch_split"
-    arity = 1
-    dependencies = ["MBEDTLS_ECP_DP_SECP521R1_ENABLED",
-                    "MBEDTLS_ECP_NIST_OPTIM"]
-
-    moduli = [("01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
-               "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
-             ] # type: List[str]
-
-    input_values = [
-        "0", "1",
-
-        # Modulus - 1
-        ("01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
-         "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"),
-
-        # Modulus + 1
-        ("020000000000000000000000000000000000000000000000000000000000000000"
-         "000000000000000000000000000000000000000000000000000000000000000000"),
-
-        # Maximum canonical P521 multiplication result
-        ("0003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
-         "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
-         "fffff800"
-         "0000000000000000000000000000000000000000000000000000000000000000"
-         "0000000000000000000000000000000000000000000000000000000000000004"),
-
-        # Test case for overflow during addition
-        ("0001efffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
-         "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
-         "000001ef"
-         "0000000000000000000000000000000000000000000000000000000000000000"
-         "000000000000000000000000000000000000000000000000000000000f000000"),
-
-        # First 8 number generated by random.getrandbits(1042) - seed(2,2)
-        ("0003cc2e82523e86feac7eb7dc38f519b91751dacdbd47d364be8049a372db8f"
-         "6e405d93ffed9235288bc781ae66267594c9c9500925e4749b575bd13653f8dd"
-         "9b1f282e"
-         "4067c3584ee207f8da94e3e8ab73738fcf1822ffbc6887782b491044d5e34124"
-         "5c6e433715ba2bdd177219d30e7a269fd95bafc8f2a4d27bdcf4bb99f4bea973"),
-        ("00017052829e07b0829a48d422fe99a22c70501e533c91352d3d854e061b9030"
-         "3b08c6e33c7295782d6c797f8f7d9b782a1be9cd8697bbd0e2520e33e44c5055"
-         "6c71c4a6"
-         "6148a86fe8624fab5186ee32ee8d7ee9770348a05d300cb90706a045defc044a"
-         "09325626e6b58de744ab6cce80877b6f71e1f6d2ef8acd128b4f2fc15f3f57eb"),
-        ("00021f15a7a83ee0761ebfd2bd143fa9b714210c665d7435c1066932f4767f26"
-         "294365b2721dea3bf63f23d0dbe53fcafb2147df5ca495fa5a91c89b97eeab64"
-         "ca2ce6bc"
-         "5d3fd983c34c769fe89204e2e8168561867e5e15bc01bfce6a27e0dfcbf87544"
-         "72154e76e4c11ab2fec3f6b32e8d4b8a8f54f8ceacaab39e83844b40ffa9b9f1"),
-        ("000381bc2a838af8d5c44a4eb3172062d08f1bb2531d6460f0caeef038c89b38"
-         "a8acb5137c9260dc74e088a9b9492f258ebdbfe3eb9ac688b9d39cca91551e82"
-         "59cc60b1"
-         "7604e4b4e73695c3e652c71a74667bffe202849da9643a295a9ac6decbd4d3e2"
-         "d4dec9ef83f0be4e80371eb97f81375eecc1cb6347733e847d718d733ff98ff3"),
-        ("00034816c8c69069134bccd3e1cf4f589f8e4ce0af29d115ef24bd625dd961e6"
-         "830b54fa7d28f93435339774bb1e386c4fd5079e681b8f5896838b769da59b74"
-         "a6c3181c"
-         "81e220df848b1df78feb994a81167346d4c0dca8b4c9e755cc9c3adcf515a823"
-         "4da4daeb4f3f87777ad1f45ae9500ec9c5e2486c44a4a8f69dc8db48e86ec9c6"),
-        ("000397846c4454b90f756132e16dce72f18e859835e1f291d322a7353ead4efe"
-         "440e2b4fda9c025a22f1a83185b98f5fc11e60de1b343f52ea748db9e020307a"
-         "aeb6db2c"
-         "3a038a709779ac1f45e9dd320c855fdfa7251af0930cdbd30f0ad2a81b2d19a2"
-         "beaa14a7ff3fe32a30ffc4eed0a7bd04e85bfcdd0227eeb7b9d7d01f5769da05"),
-        ("00002c3296e6bc4d62b47204007ee4fab105d83e85e951862f0981aebc1b00d9"
-         "2838e766ef9b6bf2d037fe2e20b6a8464174e75a5f834da70569c018eb2b5693"
-         "babb7fbb"
-         "0a76c196067cfdcb11457d9cf45e2fa01d7f4275153924800600571fac3a5b26"
-         "3fdf57cd2c0064975c3747465cc36c270e8a35b10828d569c268a20eb78ac332"),
-        ("00009d23b4917fc09f20dbb0dcc93f0e66dfe717c17313394391b6e2e6eacb0f"
-         "0bb7be72bd6d25009aeb7fa0c4169b148d2f527e72daf0a54ef25c0707e33868"
-         "7d1f7157"
-         "5653a45c49390aa51cf5192bbf67da14be11d56ba0b4a2969d8055a9f03f2d71"
-         "581d8e830112ff0f0948eccaf8877acf26c377c13f719726fd70bddacb4deeec"),
-
-        # Next 2 number generated by random.getrandbits(521)
-        ("12b84ae65e920a63ac1f2b64df6dff07870c9d531ae72a47403063238da1a1fe"
-         "3f9d6a179fa50f96cd4aff9261aa92c0e6f17ec940639bc2ccdf572df00790813e3"),
-        ("166049dd332a73fa0b26b75196cf87eb8a09b27ec714307c68c425424a1574f1"
-         "eedf5b0f16cdfdb839424d201e653f53d6883ca1c107ca6e706649889c0c7f38608")
-    ]
-
-    @property
-    def arg_a(self) -> str:
-        # Number of limbs: 2 * N
-        return super().format_arg('{:x}'.format(self.int_a)).zfill(2 * self.hex_digits)
-
-    def result(self) -> List[str]:
-        result = self.int_a % self.int_n
-        return [self.format_result(result)]
-
-    @property
-    def is_valid(self) -> bool:
-        return True
-
-    def arguments(self)-> List[str]:
-        args = super().arguments()
-        return  ["MBEDTLS_ECP_DP_SECP521R1"] + args
-
-
-class EcpP192K1Raw(bignum_common.ModOperationCommon,
-                   EcpTarget):
-    """Test cases for ECP P192K1 fast reduction."""
-    symbol = "-"
-    test_function = "ecp_mod_p_generic_raw"
-    test_name = "ecp_mod_p192k1_raw"
-    input_style = "fixed"
-    arity = 1
-    dependencies = ["MBEDTLS_ECP_DP_SECP192K1_ENABLED"]
-
-    moduli = ["fffffffffffffffffffffffffffffffffffffffeffffee37"] # type: List[str]
-
-    input_values = [
-        "0", "1",
-
-        # Modulus - 1
-        "fffffffffffffffffffffffffffffffffffffffeffffee36",
-
-        # Modulus + 1
-        "fffffffffffffffffffffffffffffffffffffffeffffee38",
-
-        # 2^192 - 1
-        "ffffffffffffffffffffffffffffffffffffffffffffffff",
-
-        # Maximum canonical P192K1 multiplication result
-        ("fffffffffffffffffffffffffffffffffffffffdffffdc6c"
-         "0000000000000000000000000000000100002394013c7364"),
-
-        # Test case for overflow during addition
-        ("00000007ffff71b809e27dd832cfd5e04d9d2dbb9f8da217"
-         "0000000000000000000000000000000000000000520834f0"),
-
-        # First 8 number generated by random.getrandbits(384) - seed(2,2)
-        ("cf1822ffbc6887782b491044d5e341245c6e433715ba2bdd"
-         "177219d30e7a269fd95bafc8f2a4d27bdcf4bb99f4bea973"),
-        ("ffed9235288bc781ae66267594c9c9500925e4749b575bd1"
-         "3653f8dd9b1f282e4067c3584ee207f8da94e3e8ab73738f"),
-        ("ef8acd128b4f2fc15f3f57ebf30b94fa82523e86feac7eb7"
-         "dc38f519b91751dacdbd47d364be8049a372db8f6e405d93"),
-        ("e8624fab5186ee32ee8d7ee9770348a05d300cb90706a045"
-         "defc044a09325626e6b58de744ab6cce80877b6f71e1f6d2"),
-        ("2d3d854e061b90303b08c6e33c7295782d6c797f8f7d9b78"
-         "2a1be9cd8697bbd0e2520e33e44c50556c71c4a66148a86f"),
-        ("fec3f6b32e8d4b8a8f54f8ceacaab39e83844b40ffa9b9f1"
-         "5c14bc4a829e07b0829a48d422fe99a22c70501e533c9135"),
-        ("97eeab64ca2ce6bc5d3fd983c34c769fe89204e2e8168561"
-         "867e5e15bc01bfce6a27e0dfcbf8754472154e76e4c11ab2"),
-        ("bd143fa9b714210c665d7435c1066932f4767f26294365b2"
-         "721dea3bf63f23d0dbe53fcafb2147df5ca495fa5a91c89b"),
-
-        # Next 2 number generated by random.getrandbits(192)
-        "47733e847d718d733ff98ff387c56473a7a83ee0761ebfd2",
-        "cbd4d3e2d4dec9ef83f0be4e80371eb97f81375eecc1cb63"
-    ]
-
-    @property
-    def arg_a(self) -> str:
-        return super().format_arg('{:x}'.format(self.int_a)).zfill(2 * self.hex_digits)
-
-    def result(self) -> List[str]:
-        result = self.int_a % self.int_n
-        return [self.format_result(result)]
-
-    @property
-    def is_valid(self) -> bool:
-        return True
-
-    def arguments(self):
-        args = super().arguments()
-        return  ["MBEDTLS_ECP_DP_SECP192K1"] + args
-
-
-class EcpP224K1Raw(bignum_common.ModOperationCommon,
-                   EcpTarget):
-    """Test cases for ECP P224 fast reduction."""
-    symbol = "-"
-    test_function = "ecp_mod_p_generic_raw"
-    test_name = "ecp_mod_p224k1_raw"
-    input_style = "arch_split"
-    arity = 1
-    dependencies = ["MBEDTLS_ECP_DP_SECP224K1_ENABLED"]
-
-    moduli = ["fffffffffffffffffffffffffffffffffffffffffffffffeffffe56d"] # type: List[str]
-
-    input_values = [
-        "0", "1",
-
-        # Modulus - 1
-        "fffffffffffffffffffffffffffffffffffffffffffffffeffffe56c",
-
-        # Modulus + 1
-        "fffffffffffffffffffffffffffffffffffffffffffffffeffffe56e",
-
-        # 2^224 - 1
-        "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
-
-        # Maximum canonical P224K1 multiplication result
-        ("fffffffffffffffffffffffffffffffffffffffffffffffdffffcad8"
-         "00000000000000000000000000000000000000010000352802c26590"),
-
-        # Test case for overflow during addition
-        ("0000007ffff2b68161180fd8cd92e1a109be158a19a99b1809db8032"
-         "0000000000000000000000000000000000000000000000000bf04f49"),
-
-        # First 8 number generated by random.getrandbits(448) - seed(2,2)
-        ("da94e3e8ab73738fcf1822ffbc6887782b491044d5e341245c6e4337"
-         "15ba2bdd177219d30e7a269fd95bafc8f2a4d27bdcf4bb99f4bea973"),
-        ("cdbd47d364be8049a372db8f6e405d93ffed9235288bc781ae662675"
-         "94c9c9500925e4749b575bd13653f8dd9b1f282e4067c3584ee207f8"),
-        ("defc044a09325626e6b58de744ab6cce80877b6f71e1f6d2ef8acd12"
-         "8b4f2fc15f3f57ebf30b94fa82523e86feac7eb7dc38f519b91751da"),
-        ("2d6c797f8f7d9b782a1be9cd8697bbd0e2520e33e44c50556c71c4a6"
-         "6148a86fe8624fab5186ee32ee8d7ee9770348a05d300cb90706a045"),
-        ("8f54f8ceacaab39e83844b40ffa9b9f15c14bc4a829e07b0829a48d4"
-         "22fe99a22c70501e533c91352d3d854e061b90303b08c6e33c729578"),
-        ("97eeab64ca2ce6bc5d3fd983c34c769fe89204e2e8168561867e5e15"
-         "bc01bfce6a27e0dfcbf8754472154e76e4c11ab2fec3f6b32e8d4b8a"),
-        ("a7a83ee0761ebfd2bd143fa9b714210c665d7435c1066932f4767f26"
-         "294365b2721dea3bf63f23d0dbe53fcafb2147df5ca495fa5a91c89b"),
-        ("74667bffe202849da9643a295a9ac6decbd4d3e2d4dec9ef83f0be4e"
-         "80371eb97f81375eecc1cb6347733e847d718d733ff98ff387c56473"),
-
-        # Next 2 number generated by random.getrandbits(224)
-        ("eb9ac688b9d39cca91551e8259cc60b17604e4b4e73695c3e652c71a"),
-        ("f0caeef038c89b38a8acb5137c9260dc74e088a9b9492f258ebdbfe3"),
-    ]
-
-    @property
-    def arg_a(self) -> str:
-        limbs = 2 * bignum_common.bits_to_limbs(224, self.bits_in_limb)
-        hex_digits = bignum_common.hex_digits_for_limb(limbs, self.bits_in_limb)
-        return super().format_arg('{:x}'.format(self.int_a)).zfill(hex_digits)
-
-    def result(self) -> List[str]:
-        result = self.int_a % self.int_n
-        return [self.format_result(result)]
-
-    @property
-    def is_valid(self) -> bool:
-        return True
-
-    def arguments(self):
-        args = super().arguments()
-        return  ["MBEDTLS_ECP_DP_SECP224K1"] + args
-
-
-class EcpP256K1Raw(bignum_common.ModOperationCommon,
-                   EcpTarget):
-    """Test cases for ECP P256 fast reduction."""
-    symbol = "-"
-    test_function = "ecp_mod_p_generic_raw"
-    test_name = "ecp_mod_p256k1_raw"
-    input_style = "fixed"
-    arity = 1
-    dependencies = ["MBEDTLS_ECP_DP_SECP256K1_ENABLED"]
-
-    moduli = ["fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"] # type: List[str]
-
-    input_values = [
-        "0", "1",
-
-        # Modulus - 1
-        "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e",
-
-        # Modulus + 1
-        "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30",
-
-        # 2^256 - 1
-        "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
-
-        # Maximum canonical P256K1 multiplication result
-        ("fffffffffffffffffffffffffffffffffffffffffffffffffffffffdfffff85c"
-         "000000000000000000000000000000000000000000000001000007a4000e9844"),
-
-        # Test case for overflow during addition
-        ("0000fffffc2f000e90a0c86a0a63234e5ba641f43a7e4aecc4040e67ec850562"
-         "00000000000000000000000000000000000000000000000000000000585674fd"),
-
-        # Test case for overflow during addition
-        ("0000fffffc2f000e90a0c86a0a63234e5ba641f43a7e4aecc4040e67ec850562"
-         "00000000000000000000000000000000000000000000000000000000585674fd"),
-
-        # First 8 number generated by random.getrandbits(512) - seed(2,2)
-        ("4067c3584ee207f8da94e3e8ab73738fcf1822ffbc6887782b491044d5e34124"
-         "5c6e433715ba2bdd177219d30e7a269fd95bafc8f2a4d27bdcf4bb99f4bea973"),
-        ("82523e86feac7eb7dc38f519b91751dacdbd47d364be8049a372db8f6e405d93"
-         "ffed9235288bc781ae66267594c9c9500925e4749b575bd13653f8dd9b1f282e"),
-        ("e8624fab5186ee32ee8d7ee9770348a05d300cb90706a045defc044a09325626"
-         "e6b58de744ab6cce80877b6f71e1f6d2ef8acd128b4f2fc15f3f57ebf30b94fa"),
-        ("829a48d422fe99a22c70501e533c91352d3d854e061b90303b08c6e33c729578"
-         "2d6c797f8f7d9b782a1be9cd8697bbd0e2520e33e44c50556c71c4a66148a86f"),
-        ("e89204e2e8168561867e5e15bc01bfce6a27e0dfcbf8754472154e76e4c11ab2"
-         "fec3f6b32e8d4b8a8f54f8ceacaab39e83844b40ffa9b9f15c14bc4a829e07b0"),
-        ("bd143fa9b714210c665d7435c1066932f4767f26294365b2721dea3bf63f23d0"
-         "dbe53fcafb2147df5ca495fa5a91c89b97eeab64ca2ce6bc5d3fd983c34c769f"),
-        ("74667bffe202849da9643a295a9ac6decbd4d3e2d4dec9ef83f0be4e80371eb9"
-         "7f81375eecc1cb6347733e847d718d733ff98ff387c56473a7a83ee0761ebfd2"),
-        ("d08f1bb2531d6460f0caeef038c89b38a8acb5137c9260dc74e088a9b9492f25"
-         "8ebdbfe3eb9ac688b9d39cca91551e8259cc60b17604e4b4e73695c3e652c71a"),
-
-        # Next 2 number generated by random.getrandbits(256)
-        ("c5e2486c44a4a8f69dc8db48e86ec9c6e06f291b2a838af8d5c44a4eb3172062"),
-        ("d4c0dca8b4c9e755cc9c3adcf515a8234da4daeb4f3f87777ad1f45ae9500ec9"),
-    ]
-
-    @property
-    def arg_a(self) -> str:
-        return super().format_arg('{:x}'.format(self.int_a)).zfill(2 * self.hex_digits)
-
-    def result(self) -> List[str]:
-        result = self.int_a % self.int_n
-        return [self.format_result(result)]
-
-    @property
-    def is_valid(self) -> bool:
-        return True
-
-    def arguments(self):
-        args = super().arguments()
-        return  ["MBEDTLS_ECP_DP_SECP256K1"] + args
-
-
-class EcpP255Raw(bignum_common.ModOperationCommon,
-                 EcpTarget):
-    """Test cases for ECP 25519 fast reduction."""
-    symbol = "-"
-    test_function = "ecp_mod_p_generic_raw"
-    test_name = "mbedtls_ecp_mod_p255_raw"
-    input_style = "fixed"
-    arity = 1
-    dependencies = ["MBEDTLS_ECP_DP_CURVE25519_ENABLED"]
-
-    moduli = [("7fffffffffffffffffffffffffffffffffffffffffffffffff"
-               "ffffffffffffed")] # type: List[str]
-
-    input_values = [
-        "0", "1",
-
-        # Modulus - 1
-        ("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec"),
-
-        # Modulus + 1
-        ("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee"),
-
-        # 2^255 - 1
-        ("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-
-        # Maximum canonical P255 multiplication result
-        ("3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec"
-         "0000000000000000000000000000000000000000000000000000000000000190"),
-
-        # First 8 number generated by random.getrandbits(510) - seed(2,2)
-        ("1019f0d64ee207f8da94e3e8ab73738fcf1822ffbc6887782b491044d5e34124"
-         "5c6e433715ba2bdd177219d30e7a269fd95bafc8f2a4d27bdcf4bb99f4bea973"),
-        ("20948fa1feac7eb7dc38f519b91751dacdbd47d364be8049a372db8f6e405d93"
-         "ffed9235288bc781ae66267594c9c9500925e4749b575bd13653f8dd9b1f282e"),
-        ("3a1893ea5186ee32ee8d7ee9770348a05d300cb90706a045defc044a09325626"
-         "e6b58de744ab6cce80877b6f71e1f6d2ef8acd128b4f2fc15f3f57ebf30b94fa"),
-        ("20a6923522fe99a22c70501e533c91352d3d854e061b90303b08c6e33c729578"
-         "2d6c797f8f7d9b782a1be9cd8697bbd0e2520e33e44c50556c71c4a66148a86f"),
-        ("3a248138e8168561867e5e15bc01bfce6a27e0dfcbf8754472154e76e4c11ab2"
-         "fec3f6b32e8d4b8a8f54f8ceacaab39e83844b40ffa9b9f15c14bc4a829e07b0"),
-        ("2f450feab714210c665d7435c1066932f4767f26294365b2721dea3bf63f23d0"
-         "dbe53fcafb2147df5ca495fa5a91c89b97eeab64ca2ce6bc5d3fd983c34c769f"),
-        ("1d199effe202849da9643a295a9ac6decbd4d3e2d4dec9ef83f0be4e80371eb9"
-         "7f81375eecc1cb6347733e847d718d733ff98ff387c56473a7a83ee0761ebfd2"),
-        ("3423c6ec531d6460f0caeef038c89b38a8acb5137c9260dc74e088a9b9492f25"
-         "8ebdbfe3eb9ac688b9d39cca91551e8259cc60b17604e4b4e73695c3e652c71a"),
-
-        # Next 2 number generated by random.getrandbits(255)
-        ("62f1243644a4a8f69dc8db48e86ec9c6e06f291b2a838af8d5c44a4eb3172062"),
-        ("6a606e54b4c9e755cc9c3adcf515a8234da4daeb4f3f87777ad1f45ae9500ec9"),
-    ]
-
-    @property
-    def arg_a(self) -> str:
-        return super().format_arg('{:x}'.format(self.int_a)).zfill(2 * self.hex_digits)
-
-    def result(self) -> List[str]:
-        result = self.int_a % self.int_n
-        return [self.format_result(result)]
-
-    @property
-    def is_valid(self) -> bool:
-        return True
-
-    def arguments(self)-> List[str]:
-        args = super().arguments()
-        return  ["MBEDTLS_ECP_DP_CURVE25519"] + args
-
-
-class EcpP448Raw(bignum_common.ModOperationCommon,
-                 EcpTarget):
-    """Test cases for ECP P448 fast reduction."""
-    symbol = "-"
-    test_function = "ecp_mod_p_generic_raw"
-    test_name = "ecp_mod_p448_raw"
-    input_style = "fixed"
-    arity = 1
-    dependencies = ["MBEDTLS_ECP_DP_CURVE448_ENABLED"]
-
-    moduli = [("fffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
-               "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff")] # type: List[str]
-
-    input_values = [
-        "0", "1",
-
-        # Modulus - 1
-        ("fffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
-         "fffffffffffffffffffffffffffffffffffffffffffffffffffffffe"),
-
-        # Modulus + 1
-        ("ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
-         "00000000000000000000000000000000000000000000000000000000"),
-
-        # 2^448 - 1
-        ("ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
-         "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
-
-        # Maximum canonical P448 multiplication result
-        ("fffffffffffffffffffffffffffffffffffffffffffffffffffffffd"
-         "fffffffffffffffffffffffffffffffffffffffffffffffffffffffd"
-         "00000000000000000000000000000000000000000000000000000004"
-         "00000000000000000000000000000000000000000000000000000004"),
-
-        # First 8 number generated by random.getrandbits(896) - seed(2,2)
-        ("74667bffe202849da9643a295a9ac6decbd4d3e2d4dec9ef83f0be4e"
-         "80371eb97f81375eecc1cb6347733e847d718d733ff98ff387c56473"
-         "a7a83ee0761ebfd2bd143fa9b714210c665d7435c1066932f4767f26"
-         "294365b2721dea3bf63f23d0dbe53fcafb2147df5ca495fa5a91c89b"),
-        ("4da4daeb4f3f87777ad1f45ae9500ec9c5e2486c44a4a8f69dc8db48"
-         "e86ec9c6e06f291b2a838af8d5c44a4eb3172062d08f1bb2531d6460"
-         "f0caeef038c89b38a8acb5137c9260dc74e088a9b9492f258ebdbfe3"
-         "eb9ac688b9d39cca91551e8259cc60b17604e4b4e73695c3e652c71a"),
-        ("bc1b00d92838e766ef9b6bf2d037fe2e20b6a8464174e75a5f834da7"
-         "0569c018eb2b5693babb7fbb0a76c196067cfdcb11457d9cf45e2fa0"
-         "1d7f4275153924800600571fac3a5b263fdf57cd2c0064975c374746"
-         "5cc36c270e8a35b10828d569c268a20eb78ac332e5e138e26c4454b9"),
-        ("8d2f527e72daf0a54ef25c0707e338687d1f71575653a45c49390aa5"
-         "1cf5192bbf67da14be11d56ba0b4a2969d8055a9f03f2d71581d8e83"
-         "0112ff0f0948eccaf8877acf26c377c13f719726fd70bddacb4deeec"
-         "0b0c995e96e6bc4d62b47204007ee4fab105d83e85e951862f0981ae"),
-        ("84ae65e920a63ac1f2b64df6dff07870c9d531ae72a47403063238da"
-         "1a1fe3f9d6a179fa50f96cd4aff9261aa92c0e6f17ec940639bc2ccd"
-         "f572df00790813e32748dd1db4917fc09f20dbb0dcc93f0e66dfe717"
-         "c17313394391b6e2e6eacb0f0bb7be72bd6d25009aeb7fa0c4169b14"),
-        ("2bb3b36f29421c4021b7379f0897246a40c270b00e893302aba9e7b8"
-         "23fc5ad2f58105748ed5d1b7b310b730049dd332a73fa0b26b75196c"
-         "f87eb8a09b27ec714307c68c425424a1574f1eedf5b0f16cdfdb8394"
-         "24d201e653f53d6883ca1c107ca6e706649889c0c7f3860895bfa813"),
-        ("af3f5d7841b1256d5c1dc12fb5a1ae519fb8883accda6559caa538a0"
-         "9fc9370d3a6b86a7975b54a31497024640332b0612d4050771d7b14e"
-         "b6c004cc3b8367dc3f2bb31efe9934ad0809eae3ef232a32b5459d83"
-         "fbc46f1aea990e94821d46063b4dbf2ca294523d74115c86188b1044"),
-        ("7430051376e31f5aab63ad02854efa600641b4fa37a47ce41aeffafc"
-         "3b45402ac02659fe2e87d4150511baeb198ababb1a16daff3da95cd2"
-         "167b75dfb948f82a8317cba01c75f67e290535d868a24b7f627f2855"
-         "09167d4126af8090013c3273c02c6b9586b4625b475b51096c4ad652"),
-
-        # Corner case which causes maximum overflow
-        ("f4ae65e920a63ac1f2b64df6dff07870c9d531ae72a47403063238da1"
-         "a1fe3f9d6a179fa50f96cd4aff9261aa92c0e6f17ec940639bc2ccd0B"
-         "519A16DF59C53E0D49B209200F878F362ACE518D5B8BFCF9CDC725E5E"
-         "01C06295E8605AF06932B5006D9E556D3F190E8136BF9C643D332"),
-
-        # Next 2 number generated by random.getrandbits(448)
-        ("8f54f8ceacaab39e83844b40ffa9b9f15c14bc4a829e07b0829a48d4"
-         "22fe99a22c70501e533c91352d3d854e061b90303b08c6e33c729578"),
-        ("97eeab64ca2ce6bc5d3fd983c34c769fe89204e2e8168561867e5e15"
-         "bc01bfce6a27e0dfcbf8754472154e76e4c11ab2fec3f6b32e8d4b8a"),
-
-    ]
-
-    @property
-    def arg_a(self) -> str:
-        return super().format_arg('{:x}'.format(self.int_a)).zfill(2 * self.hex_digits)
-
-    def result(self) -> List[str]:
-        result = self.int_a % self.int_n
-        return [self.format_result(result)]
-
-    @property
-    def is_valid(self) -> bool:
-        return True
-
-    def arguments(self):
-        args = super().arguments()
-        return  ["MBEDTLS_ECP_DP_CURVE448"] + args
diff --git a/scripts/mbedtls_dev/logging_util.py b/scripts/mbedtls_dev/logging_util.py
deleted file mode 100644
index ddd7c7f..0000000
--- a/scripts/mbedtls_dev/logging_util.py
+++ /dev/null
@@ -1,46 +0,0 @@
-"""Auxiliary functions used for logging module.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-import logging
-import sys
-
-def configure_logger(
-        logger: logging.Logger,
-        log_format="[%(levelname)s]: %(message)s",
-        split_level=logging.WARNING
-    ) -> None:
-    """
-    Configure the logging.Logger instance so that:
-        - Format is set to any log_format.
-            Default: "[%(levelname)s]: %(message)s"
-        - loglevel >= split_level are printed to stderr.
-        - loglevel <  split_level are printed to stdout.
-            Default: logging.WARNING
-    """
-    class MaxLevelFilter(logging.Filter):
-        # pylint: disable=too-few-public-methods
-        def __init__(self, max_level, name=''):
-            super().__init__(name)
-            self.max_level = max_level
-
-        def filter(self, record: logging.LogRecord) -> bool:
-            return record.levelno <= self.max_level
-
-    log_formatter = logging.Formatter(log_format)
-
-    # set loglevel >= split_level to be printed to stderr
-    stderr_hdlr = logging.StreamHandler(sys.stderr)
-    stderr_hdlr.setLevel(split_level)
-    stderr_hdlr.setFormatter(log_formatter)
-
-    # set loglevel < split_level to be printed to stdout
-    stdout_hdlr = logging.StreamHandler(sys.stdout)
-    stdout_hdlr.addFilter(MaxLevelFilter(split_level - 1))
-    stdout_hdlr.setFormatter(log_formatter)
-
-    logger.addHandler(stderr_hdlr)
-    logger.addHandler(stdout_hdlr)
diff --git a/scripts/mbedtls_dev/macro_collector.py b/scripts/mbedtls_dev/macro_collector.py
deleted file mode 100644
index d68be00..0000000
--- a/scripts/mbedtls_dev/macro_collector.py
+++ /dev/null
@@ -1,539 +0,0 @@
-"""Collect macro definitions from header files.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-import itertools
-import re
-from typing import Dict, IO, Iterable, Iterator, List, Optional, Pattern, Set, Tuple, Union
-
-
-class ReadFileLineException(Exception):
-    def __init__(self, filename: str, line_number: Union[int, str]) -> None:
-        message = 'in {} at {}'.format(filename, line_number)
-        super(ReadFileLineException, self).__init__(message)
-        self.filename = filename
-        self.line_number = line_number
-
-
-class read_file_lines:
-    # Dear Pylint, conventionally, a context manager class name is lowercase.
-    # pylint: disable=invalid-name,too-few-public-methods
-    """Context manager to read a text file line by line.
-
-    ```
-    with read_file_lines(filename) as lines:
-        for line in lines:
-            process(line)
-    ```
-    is equivalent to
-    ```
-    with open(filename, 'r') as input_file:
-        for line in input_file:
-            process(line)
-    ```
-    except that if process(line) raises an exception, then the read_file_lines
-    snippet annotates the exception with the file name and line number.
-    """
-    def __init__(self, filename: str, binary: bool = False) -> None:
-        self.filename = filename
-        self.file = None #type: Optional[IO[str]]
-        self.line_number = 'entry' #type: Union[int, str]
-        self.generator = None #type: Optional[Iterable[Tuple[int, str]]]
-        self.binary = binary
-    def __enter__(self) -> 'read_file_lines':
-        self.file = open(self.filename, 'rb' if self.binary else 'r')
-        self.generator = enumerate(self.file)
-        return self
-    def __iter__(self) -> Iterator[str]:
-        assert self.generator is not None
-        for line_number, content in self.generator:
-            self.line_number = line_number
-            yield content
-        self.line_number = 'exit'
-    def __exit__(self, exc_type, exc_value, exc_traceback) -> None:
-        if self.file is not None:
-            self.file.close()
-        if exc_type is not None:
-            raise ReadFileLineException(self.filename, self.line_number) \
-                from exc_value
-
-
-class PSAMacroEnumerator:
-    """Information about constructors of various PSA Crypto types.
-
-    This includes macro names as well as information about their arguments
-    when applicable.
-
-    This class only provides ways to enumerate expressions that evaluate to
-    values of the covered types. Derived classes are expected to populate
-    the set of known constructors of each kind, as well as populate
-    `self.arguments_for` for arguments that are not of a kind that is
-    enumerated here.
-    """
-    #pylint: disable=too-many-instance-attributes
-
-    def __init__(self) -> None:
-        """Set up an empty set of known constructor macros.
-        """
-        self.statuses = set() #type: Set[str]
-        self.lifetimes = set() #type: Set[str]
-        self.locations = set() #type: Set[str]
-        self.persistence_levels = set() #type: Set[str]
-        self.algorithms = set() #type: Set[str]
-        self.ecc_curves = set() #type: Set[str]
-        self.dh_groups = set() #type: Set[str]
-        self.key_types = set() #type: Set[str]
-        self.key_usage_flags = set() #type: Set[str]
-        self.hash_algorithms = set() #type: Set[str]
-        self.mac_algorithms = set() #type: Set[str]
-        self.ka_algorithms = set() #type: Set[str]
-        self.kdf_algorithms = set() #type: Set[str]
-        self.pake_algorithms = set() #type: Set[str]
-        self.aead_algorithms = set() #type: Set[str]
-        self.sign_algorithms = set() #type: Set[str]
-        # macro name -> list of argument names
-        self.argspecs = {} #type: Dict[str, List[str]]
-        # argument name -> list of values
-        self.arguments_for = {
-            'mac_length': [],
-            'min_mac_length': [],
-            'tag_length': [],
-            'min_tag_length': [],
-        } #type: Dict[str, List[str]]
-        # Whether to include intermediate macros in enumerations. Intermediate
-        # macros serve as category headers and are not valid values of their
-        # type. See `is_internal_name`.
-        # Always false in this class, may be set to true in derived classes.
-        self.include_intermediate = False
-
-    def is_internal_name(self, name: str) -> bool:
-        """Whether this is an internal macro. Internal macros will be skipped."""
-        if not self.include_intermediate:
-            if name.endswith('_BASE') or name.endswith('_NONE'):
-                return True
-            if '_CATEGORY_' in name:
-                return True
-        return name.endswith('_FLAG') or name.endswith('_MASK')
-
-    def gather_arguments(self) -> None:
-        """Populate the list of values for macro arguments.
-
-        Call this after parsing all the inputs.
-        """
-        self.arguments_for['hash_alg'] = sorted(self.hash_algorithms)
-        self.arguments_for['mac_alg'] = sorted(self.mac_algorithms)
-        self.arguments_for['ka_alg'] = sorted(self.ka_algorithms)
-        self.arguments_for['kdf_alg'] = sorted(self.kdf_algorithms)
-        self.arguments_for['aead_alg'] = sorted(self.aead_algorithms)
-        self.arguments_for['sign_alg'] = sorted(self.sign_algorithms)
-        self.arguments_for['curve'] = sorted(self.ecc_curves)
-        self.arguments_for['group'] = sorted(self.dh_groups)
-        self.arguments_for['persistence'] = sorted(self.persistence_levels)
-        self.arguments_for['location'] = sorted(self.locations)
-        self.arguments_for['lifetime'] = sorted(self.lifetimes)
-
-    @staticmethod
-    def _format_arguments(name: str, arguments: Iterable[str]) -> str:
-        """Format a macro call with arguments.
-
-        The resulting format is consistent with
-        `InputsForTest.normalize_argument`.
-        """
-        return name + '(' + ', '.join(arguments) + ')'
-
-    _argument_split_re = re.compile(r' *, *')
-    @classmethod
-    def _argument_split(cls, arguments: str) -> List[str]:
-        return re.split(cls._argument_split_re, arguments)
-
-    def distribute_arguments(self, name: str) -> Iterator[str]:
-        """Generate macro calls with each tested argument set.
-
-        If name is a macro without arguments, just yield "name".
-        If name is a macro with arguments, yield a series of
-        "name(arg1,...,argN)" where each argument takes each possible
-        value at least once.
-        """
-        try:
-            if name not in self.argspecs:
-                yield name
-                return
-            argspec = self.argspecs[name]
-            if argspec == []:
-                yield name + '()'
-                return
-            argument_lists = [self.arguments_for[arg] for arg in argspec]
-            arguments = [values[0] for values in argument_lists]
-            yield self._format_arguments(name, arguments)
-            # Dear Pylint, enumerate won't work here since we're modifying
-            # the array.
-            # pylint: disable=consider-using-enumerate
-            for i in range(len(arguments)):
-                for value in argument_lists[i][1:]:
-                    arguments[i] = value
-                    yield self._format_arguments(name, arguments)
-                arguments[i] = argument_lists[i][0]
-        except BaseException as e:
-            raise Exception('distribute_arguments({})'.format(name)) from e
-
-    def distribute_arguments_without_duplicates(
-            self, seen: Set[str], name: str
-    ) -> Iterator[str]:
-        """Same as `distribute_arguments`, but don't repeat seen results."""
-        for result in self.distribute_arguments(name):
-            if result not in seen:
-                seen.add(result)
-                yield result
-
-    def generate_expressions(self, names: Iterable[str]) -> Iterator[str]:
-        """Generate expressions covering values constructed from the given names.
-
-        `names` can be any iterable collection of macro names.
-
-        For example:
-        * ``generate_expressions(['PSA_ALG_CMAC', 'PSA_ALG_HMAC'])``
-          generates ``'PSA_ALG_CMAC'`` as well as ``'PSA_ALG_HMAC(h)'`` for
-          every known hash algorithm ``h``.
-        * ``macros.generate_expressions(macros.key_types)`` generates all
-          key types.
-        """
-        seen = set() #type: Set[str]
-        return itertools.chain(*(
-            self.distribute_arguments_without_duplicates(seen, name)
-            for name in names
-        ))
-
-
-class PSAMacroCollector(PSAMacroEnumerator):
-    """Collect PSA crypto macro definitions from C header files.
-    """
-
-    def __init__(self, include_intermediate: bool = False) -> None:
-        """Set up an object to collect PSA macro definitions.
-
-        Call the read_file method of the constructed object on each header file.
-
-        * include_intermediate: if true, include intermediate macros such as
-          PSA_XXX_BASE that do not designate semantic values.
-        """
-        super().__init__()
-        self.include_intermediate = include_intermediate
-        self.key_types_from_curve = {} #type: Dict[str, str]
-        self.key_types_from_group = {} #type: Dict[str, str]
-        self.algorithms_from_hash = {} #type: Dict[str, str]
-
-    @staticmethod
-    def algorithm_tester(name: str) -> str:
-        """The predicate for whether an algorithm is built from the given constructor.
-
-        The given name must be the name of an algorithm constructor of the
-        form ``PSA_ALG_xxx`` which is used as ``PSA_ALG_xxx(yyy)`` to build
-        an algorithm value. Return the corresponding predicate macro which
-        is used as ``predicate(alg)`` to test whether ``alg`` can be built
-        as ``PSA_ALG_xxx(yyy)``. The predicate is usually called
-        ``PSA_ALG_IS_xxx``.
-        """
-        prefix = 'PSA_ALG_'
-        assert name.startswith(prefix)
-        midfix = 'IS_'
-        suffix = name[len(prefix):]
-        if suffix in ['DSA', 'ECDSA']:
-            midfix += 'RANDOMIZED_'
-        elif suffix == 'RSA_PSS':
-            suffix += '_STANDARD_SALT'
-        return prefix + midfix + suffix
-
-    def record_algorithm_subtype(self, name: str, expansion: str) -> None:
-        """Record the subtype of an algorithm constructor.
-
-        Given a ``PSA_ALG_xxx`` macro name and its expansion, if the algorithm
-        is of a subtype that is tracked in its own set, add it to the relevant
-        set.
-        """
-        # This code is very ad hoc and fragile. It should be replaced by
-        # something more robust.
-        if re.match(r'MAC(?:_|\Z)', name):
-            self.mac_algorithms.add(name)
-        elif re.match(r'KDF(?:_|\Z)', name):
-            self.kdf_algorithms.add(name)
-        elif re.search(r'0x020000[0-9A-Fa-f]{2}', expansion):
-            self.hash_algorithms.add(name)
-        elif re.search(r'0x03[0-9A-Fa-f]{6}', expansion):
-            self.mac_algorithms.add(name)
-        elif re.search(r'0x05[0-9A-Fa-f]{6}', expansion):
-            self.aead_algorithms.add(name)
-        elif re.search(r'0x09[0-9A-Fa-f]{2}0000', expansion):
-            self.ka_algorithms.add(name)
-        elif re.search(r'0x08[0-9A-Fa-f]{6}', expansion):
-            self.kdf_algorithms.add(name)
-
-    # "#define" followed by a macro name with either no parameters
-    # or a single parameter and a non-empty expansion.
-    # Grab the macro name in group 1, the parameter name if any in group 2
-    # and the expansion in group 3.
-    _define_directive_re = re.compile(r'\s*#\s*define\s+(\w+)' +
-                                      r'(?:\s+|\((\w+)\)\s*)' +
-                                      r'(.+)')
-    _deprecated_definition_re = re.compile(r'\s*MBEDTLS_DEPRECATED')
-
-    def read_line(self, line):
-        """Parse a C header line and record the PSA identifier it defines if any.
-        This function analyzes lines that start with "#define PSA_"
-        (up to non-significant whitespace) and skips all non-matching lines.
-        """
-        # pylint: disable=too-many-branches
-        m = re.match(self._define_directive_re, line)
-        if not m:
-            return
-        name, parameter, expansion = m.groups()
-        expansion = re.sub(r'/\*.*?\*/|//.*', r' ', expansion)
-        if parameter:
-            self.argspecs[name] = [parameter]
-        if re.match(self._deprecated_definition_re, expansion):
-            # Skip deprecated values, which are assumed to be
-            # backward compatibility aliases that share
-            # numerical values with non-deprecated values.
-            return
-        if self.is_internal_name(name):
-            # Macro only to build actual values
-            return
-        elif (name.startswith('PSA_ERROR_') or name == 'PSA_SUCCESS') \
-           and not parameter:
-            self.statuses.add(name)
-        elif name.startswith('PSA_KEY_TYPE_') and not parameter:
-            self.key_types.add(name)
-        elif name.startswith('PSA_KEY_TYPE_') and parameter == 'curve':
-            self.key_types_from_curve[name] = name[:13] + 'IS_' + name[13:]
-        elif name.startswith('PSA_KEY_TYPE_') and parameter == 'group':
-            self.key_types_from_group[name] = name[:13] + 'IS_' + name[13:]
-        elif name.startswith('PSA_ECC_FAMILY_') and not parameter:
-            self.ecc_curves.add(name)
-        elif name.startswith('PSA_DH_FAMILY_') and not parameter:
-            self.dh_groups.add(name)
-        elif name.startswith('PSA_ALG_') and not parameter:
-            if name in ['PSA_ALG_ECDSA_BASE',
-                        'PSA_ALG_RSA_PKCS1V15_SIGN_BASE']:
-                # Ad hoc skipping of duplicate names for some numerical values
-                return
-            self.algorithms.add(name)
-            self.record_algorithm_subtype(name, expansion)
-        elif name.startswith('PSA_ALG_') and parameter == 'hash_alg':
-            self.algorithms_from_hash[name] = self.algorithm_tester(name)
-        elif name.startswith('PSA_KEY_USAGE_') and not parameter:
-            self.key_usage_flags.add(name)
-        else:
-            # Other macro without parameter
-            return
-
-    _nonascii_re = re.compile(rb'[^\x00-\x7f]+')
-    _continued_line_re = re.compile(rb'\\\r?\n\Z')
-    def read_file(self, header_file):
-        for line in header_file:
-            m = re.search(self._continued_line_re, line)
-            while m:
-                cont = next(header_file)
-                line = line[:m.start(0)] + cont
-                m = re.search(self._continued_line_re, line)
-            line = re.sub(self._nonascii_re, rb'', line).decode('ascii')
-            self.read_line(line)
-
-
-class InputsForTest(PSAMacroEnumerator):
-    # pylint: disable=too-many-instance-attributes
-    """Accumulate information about macros to test.
-enumerate
-    This includes macro names as well as information about their arguments
-    when applicable.
-    """
-
-    def __init__(self) -> None:
-        super().__init__()
-        self.all_declared = set() #type: Set[str]
-        # Identifier prefixes
-        self.table_by_prefix = {
-            'ERROR': self.statuses,
-            'ALG': self.algorithms,
-            'ECC_CURVE': self.ecc_curves,
-            'DH_GROUP': self.dh_groups,
-            'KEY_LIFETIME': self.lifetimes,
-            'KEY_LOCATION': self.locations,
-            'KEY_PERSISTENCE': self.persistence_levels,
-            'KEY_TYPE': self.key_types,
-            'KEY_USAGE': self.key_usage_flags,
-        } #type: Dict[str, Set[str]]
-        # Test functions
-        self.table_by_test_function = {
-            # Any function ending in _algorithm also gets added to
-            # self.algorithms.
-            'key_type': [self.key_types],
-            'block_cipher_key_type': [self.key_types],
-            'stream_cipher_key_type': [self.key_types],
-            'ecc_key_family': [self.ecc_curves],
-            'ecc_key_types': [self.ecc_curves],
-            'dh_key_family': [self.dh_groups],
-            'dh_key_types': [self.dh_groups],
-            'hash_algorithm': [self.hash_algorithms],
-            'mac_algorithm': [self.mac_algorithms],
-            'cipher_algorithm': [],
-            'hmac_algorithm': [self.mac_algorithms, self.sign_algorithms],
-            'aead_algorithm': [self.aead_algorithms],
-            'key_derivation_algorithm': [self.kdf_algorithms],
-            'key_agreement_algorithm': [self.ka_algorithms],
-            'asymmetric_signature_algorithm': [self.sign_algorithms],
-            'asymmetric_signature_wildcard': [self.algorithms],
-            'asymmetric_encryption_algorithm': [],
-            'pake_algorithm': [self.pake_algorithms],
-            'other_algorithm': [],
-            'lifetime': [self.lifetimes],
-        } #type: Dict[str, List[Set[str]]]
-        mac_lengths = [str(n) for n in [
-            1,  # minimum expressible
-            4,  # minimum allowed by policy
-            13, # an odd size in a plausible range
-            14, # an even non-power-of-two size in a plausible range
-            16, # same as full size for at least one algorithm
-            63, # maximum expressible
-        ]]
-        self.arguments_for['mac_length'] += mac_lengths
-        self.arguments_for['min_mac_length'] += mac_lengths
-        aead_lengths = [str(n) for n in [
-            1,  # minimum expressible
-            4,  # minimum allowed by policy
-            13, # an odd size in a plausible range
-            14, # an even non-power-of-two size in a plausible range
-            16, # same as full size for at least one algorithm
-            63, # maximum expressible
-        ]]
-        self.arguments_for['tag_length'] += aead_lengths
-        self.arguments_for['min_tag_length'] += aead_lengths
-
-    def add_numerical_values(self) -> None:
-        """Add numerical values that are not supported to the known identifiers."""
-        # Sets of names per type
-        self.algorithms.add('0xffffffff')
-        self.ecc_curves.add('0xff')
-        self.dh_groups.add('0xff')
-        self.key_types.add('0xffff')
-        self.key_usage_flags.add('0x80000000')
-
-        # Hard-coded values for unknown algorithms
-        #
-        # These have to have values that are correct for their respective
-        # PSA_ALG_IS_xxx macros, but are also not currently assigned and are
-        # not likely to be assigned in the near future.
-        self.hash_algorithms.add('0x020000fe') # 0x020000ff is PSA_ALG_ANY_HASH
-        self.mac_algorithms.add('0x03007fff')
-        self.ka_algorithms.add('0x09fc0000')
-        self.kdf_algorithms.add('0x080000ff')
-        self.pake_algorithms.add('0x0a0000ff')
-        # For AEAD algorithms, the only variability is over the tag length,
-        # and this only applies to known algorithms, so don't test an
-        # unknown algorithm.
-
-    def get_names(self, type_word: str) -> Set[str]:
-        """Return the set of known names of values of the given type."""
-        return {
-            'status': self.statuses,
-            'algorithm': self.algorithms,
-            'ecc_curve': self.ecc_curves,
-            'dh_group': self.dh_groups,
-            'key_type': self.key_types,
-            'key_usage': self.key_usage_flags,
-        }[type_word]
-
-    # Regex for interesting header lines.
-    # Groups: 1=macro name, 2=type, 3=argument list (optional).
-    _header_line_re = \
-        re.compile(r'#define +' +
-                   r'(PSA_((?:(?:DH|ECC|KEY)_)?[A-Z]+)_\w+)' +
-                   r'(?:\(([^\n()]*)\))?')
-    # Regex of macro names to exclude.
-    _excluded_name_re = re.compile(r'_(?:GET|IS|OF)_|_(?:BASE|FLAG|MASK)\Z')
-    # Additional excluded macros.
-    _excluded_names = set([
-        # Macros that provide an alternative way to build the same
-        # algorithm as another macro.
-        'PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG',
-        'PSA_ALG_FULL_LENGTH_MAC',
-        # Auxiliary macro whose name doesn't fit the usual patterns for
-        # auxiliary macros.
-        'PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE',
-    ])
-    def parse_header_line(self, line: str) -> None:
-        """Parse a C header line, looking for "#define PSA_xxx"."""
-        m = re.match(self._header_line_re, line)
-        if not m:
-            return
-        name = m.group(1)
-        self.all_declared.add(name)
-        if re.search(self._excluded_name_re, name) or \
-           name in self._excluded_names or \
-           self.is_internal_name(name):
-            return
-        dest = self.table_by_prefix.get(m.group(2))
-        if dest is None:
-            return
-        dest.add(name)
-        if m.group(3):
-            self.argspecs[name] = self._argument_split(m.group(3))
-
-    _nonascii_re = re.compile(rb'[^\x00-\x7f]+') #type: Pattern
-    def parse_header(self, filename: str) -> None:
-        """Parse a C header file, looking for "#define PSA_xxx"."""
-        with read_file_lines(filename, binary=True) as lines:
-            for line in lines:
-                line = re.sub(self._nonascii_re, rb'', line).decode('ascii')
-                self.parse_header_line(line)
-
-    _macro_identifier_re = re.compile(r'[A-Z]\w+')
-    def generate_undeclared_names(self, expr: str) -> Iterable[str]:
-        for name in re.findall(self._macro_identifier_re, expr):
-            if name not in self.all_declared:
-                yield name
-
-    def accept_test_case_line(self, function: str, argument: str) -> bool:
-        #pylint: disable=unused-argument
-        undeclared = list(self.generate_undeclared_names(argument))
-        if undeclared:
-            raise Exception('Undeclared names in test case', undeclared)
-        return True
-
-    @staticmethod
-    def normalize_argument(argument: str) -> str:
-        """Normalize whitespace in the given C expression.
-
-        The result uses the same whitespace as
-        ` PSAMacroEnumerator.distribute_arguments`.
-        """
-        return re.sub(r',', r', ', re.sub(r' +', r'', argument))
-
-    def add_test_case_line(self, function: str, argument: str) -> None:
-        """Parse a test case data line, looking for algorithm metadata tests."""
-        sets = []
-        if function.endswith('_algorithm'):
-            sets.append(self.algorithms)
-            if function == 'key_agreement_algorithm' and \
-               argument.startswith('PSA_ALG_KEY_AGREEMENT('):
-                # We only want *raw* key agreement algorithms as such, so
-                # exclude ones that are already chained with a KDF.
-                # Keep the expression as one to test as an algorithm.
-                function = 'other_algorithm'
-        sets += self.table_by_test_function[function]
-        if self.accept_test_case_line(function, argument):
-            for s in sets:
-                s.add(self.normalize_argument(argument))
-
-    # Regex matching a *.data line containing a test function call and
-    # its arguments. The actual definition is partly positional, but this
-    # regex is good enough in practice.
-    _test_case_line_re = re.compile(r'(?!depends_on:)(\w+):([^\n :][^:\n]*)')
-    def parse_test_cases(self, filename: str) -> None:
-        """Parse a test case file (*.data), looking for algorithm metadata tests."""
-        with read_file_lines(filename) as lines:
-            for line in lines:
-                m = re.match(self._test_case_line_re, line)
-                if m:
-                    self.add_test_case_line(m.group(1), m.group(2))
diff --git a/scripts/mbedtls_dev/psa_information.py b/scripts/mbedtls_dev/psa_information.py
deleted file mode 100644
index 6080386..0000000
--- a/scripts/mbedtls_dev/psa_information.py
+++ /dev/null
@@ -1,161 +0,0 @@
-"""Collect information about PSA cryptographic mechanisms.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-import re
-from collections import OrderedDict
-from typing import FrozenSet, List, Optional
-
-from . import macro_collector
-
-
-class Information:
-    """Gather information about PSA constructors."""
-
-    def __init__(self) -> None:
-        self.constructors = self.read_psa_interface()
-
-    @staticmethod
-    def remove_unwanted_macros(
-            constructors: macro_collector.PSAMacroEnumerator
-    ) -> None:
-        # Mbed TLS does not support finite-field DSA.
-        # Don't attempt to generate any related test case.
-        constructors.key_types.discard('PSA_KEY_TYPE_DSA_KEY_PAIR')
-        constructors.key_types.discard('PSA_KEY_TYPE_DSA_PUBLIC_KEY')
-
-    def read_psa_interface(self) -> macro_collector.PSAMacroEnumerator:
-        """Return the list of known key types, algorithms, etc."""
-        constructors = macro_collector.InputsForTest()
-        header_file_names = ['include/psa/crypto_values.h',
-                             'include/psa/crypto_extra.h']
-        test_suites = ['tests/suites/test_suite_psa_crypto_metadata.data']
-        for header_file_name in header_file_names:
-            constructors.parse_header(header_file_name)
-        for test_cases in test_suites:
-            constructors.parse_test_cases(test_cases)
-        self.remove_unwanted_macros(constructors)
-        constructors.gather_arguments()
-        return constructors
-
-
-def psa_want_symbol(name: str) -> str:
-    """Return the PSA_WANT_xxx symbol associated with a PSA crypto feature."""
-    if name.startswith('PSA_'):
-        return name[:4] + 'WANT_' + name[4:]
-    else:
-        raise ValueError('Unable to determine the PSA_WANT_ symbol for ' + name)
-
-def finish_family_dependency(dep: str, bits: int) -> str:
-    """Finish dep if it's a family dependency symbol prefix.
-
-    A family dependency symbol prefix is a PSA_WANT_ symbol that needs to be
-    qualified by the key size. If dep is such a symbol, finish it by adjusting
-    the prefix and appending the key size. Other symbols are left unchanged.
-    """
-    return re.sub(r'_FAMILY_(.*)', r'_\1_' + str(bits), dep)
-
-def finish_family_dependencies(dependencies: List[str], bits: int) -> List[str]:
-    """Finish any family dependency symbol prefixes.
-
-    Apply `finish_family_dependency` to each element of `dependencies`.
-    """
-    return [finish_family_dependency(dep, bits) for dep in dependencies]
-
-SYMBOLS_WITHOUT_DEPENDENCY = frozenset([
-    'PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG', # modifier, only in policies
-    'PSA_ALG_AEAD_WITH_SHORTENED_TAG', # modifier
-    'PSA_ALG_ANY_HASH', # only in policies
-    'PSA_ALG_AT_LEAST_THIS_LENGTH_MAC', # modifier, only in policies
-    'PSA_ALG_KEY_AGREEMENT', # chaining
-    'PSA_ALG_TRUNCATED_MAC', # modifier
-])
-def automatic_dependencies(*expressions: str) -> List[str]:
-    """Infer dependencies of a test case by looking for PSA_xxx symbols.
-
-    The arguments are strings which should be C expressions. Do not use
-    string literals or comments as this function is not smart enough to
-    skip them.
-    """
-    used = set()
-    for expr in expressions:
-        used.update(re.findall(r'PSA_(?:ALG|ECC_FAMILY|DH_FAMILY|KEY_TYPE)_\w+', expr))
-    used.difference_update(SYMBOLS_WITHOUT_DEPENDENCY)
-    return sorted(psa_want_symbol(name) for name in used)
-
-# Define set of regular expressions and dependencies to optionally append
-# extra dependencies for test case based on key description.
-
-# Skip AES test cases which require 192- or 256-bit key
-# if MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH defined
-AES_128BIT_ONLY_DEP_REGEX = re.compile(r'AES\s(192|256)')
-AES_128BIT_ONLY_DEP = ['!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH']
-# Skip AES/ARIA/CAMELLIA test cases which require decrypt operation in ECB mode
-# if MBEDTLS_BLOCK_CIPHER_NO_DECRYPT enabled.
-ECB_NO_PADDING_DEP_REGEX = re.compile(r'(AES|ARIA|CAMELLIA).*ECB_NO_PADDING')
-ECB_NO_PADDING_DEP = ['!MBEDTLS_BLOCK_CIPHER_NO_DECRYPT']
-
-DEPENDENCY_FROM_DESCRIPTION = OrderedDict()
-DEPENDENCY_FROM_DESCRIPTION[AES_128BIT_ONLY_DEP_REGEX] = AES_128BIT_ONLY_DEP
-DEPENDENCY_FROM_DESCRIPTION[ECB_NO_PADDING_DEP_REGEX] = ECB_NO_PADDING_DEP
-def generate_deps_from_description(
-        description: str
-    ) -> List[str]:
-    """Return additional dependencies based on test case description and REGEX.
-    """
-    dep_list = []
-    for regex, deps in DEPENDENCY_FROM_DESCRIPTION.items():
-        if re.search(regex, description):
-            dep_list += deps
-
-    return dep_list
-
-# A temporary hack: at the time of writing, not all dependency symbols
-# are implemented yet. Skip test cases for which the dependency symbols are
-# not available. Once all dependency symbols are available, this hack must
-# be removed so that a bug in the dependency symbols properly leads to a test
-# failure.
-def read_implemented_dependencies(filename: str) -> FrozenSet[str]:
-    return frozenset(symbol
-                     for line in open(filename)
-                     for symbol in re.findall(r'\bPSA_WANT_\w+\b', line))
-_implemented_dependencies = None #type: Optional[FrozenSet[str]] #pylint: disable=invalid-name
-def hack_dependencies_not_implemented(dependencies: List[str]) -> None:
-    global _implemented_dependencies #pylint: disable=global-statement,invalid-name
-    if _implemented_dependencies is None:
-        _implemented_dependencies = \
-            read_implemented_dependencies('include/psa/crypto_config.h')
-    if not all((dep.lstrip('!') in _implemented_dependencies or
-                not dep.lstrip('!').startswith('PSA_WANT'))
-               for dep in dependencies):
-        dependencies.append('DEPENDENCY_NOT_IMPLEMENTED_YET')
-
-def tweak_key_pair_dependency(dep: str, usage: str):
-    """
-    This helper function add the proper suffix to PSA_WANT_KEY_TYPE_xxx_KEY_PAIR
-    symbols according to the required usage.
-    """
-    ret_list = list()
-    if dep.endswith('KEY_PAIR'):
-        if usage == "BASIC":
-            # BASIC automatically includes IMPORT and EXPORT for test purposes (see
-            # config_psa.h).
-            ret_list.append(re.sub(r'KEY_PAIR', r'KEY_PAIR_BASIC', dep))
-            ret_list.append(re.sub(r'KEY_PAIR', r'KEY_PAIR_IMPORT', dep))
-            ret_list.append(re.sub(r'KEY_PAIR', r'KEY_PAIR_EXPORT', dep))
-        elif usage == "GENERATE":
-            ret_list.append(re.sub(r'KEY_PAIR', r'KEY_PAIR_GENERATE', dep))
-    else:
-        # No replacement to do in this case
-        ret_list.append(dep)
-    return ret_list
-
-def fix_key_pair_dependencies(dep_list: List[str], usage: str):
-    new_list = [new_deps
-                for dep in dep_list
-                for new_deps in tweak_key_pair_dependency(dep, usage)]
-
-    return new_list
diff --git a/scripts/mbedtls_dev/psa_storage.py b/scripts/mbedtls_dev/psa_storage.py
deleted file mode 100644
index b1fc377..0000000
--- a/scripts/mbedtls_dev/psa_storage.py
+++ /dev/null
@@ -1,206 +0,0 @@
-"""Knowledge about the PSA key store as implemented in Mbed TLS.
-
-Note that if you need to make a change that affects how keys are
-stored, this may indicate that the key store is changing in a
-backward-incompatible way! Think carefully about backward compatibility
-before changing how test data is constructed or validated.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-import re
-import struct
-from typing import Dict, List, Optional, Set, Union
-import unittest
-
-from . import c_build_helper
-from . import build_tree
-
-
-class Expr:
-    """Representation of a C expression with a known or knowable numerical value."""
-
-    def __init__(self, content: Union[int, str]):
-        if isinstance(content, int):
-            digits = 8 if content > 0xffff else 4
-            self.string = '{0:#0{1}x}'.format(content, digits + 2)
-            self.value_if_known = content #type: Optional[int]
-        else:
-            self.string = content
-            self.unknown_values.add(self.normalize(content))
-            self.value_if_known = None
-
-    value_cache = {} #type: Dict[str, int]
-    """Cache of known values of expressions."""
-
-    unknown_values = set() #type: Set[str]
-    """Expressions whose values are not present in `value_cache` yet."""
-
-    def update_cache(self) -> None:
-        """Update `value_cache` for expressions registered in `unknown_values`."""
-        expressions = sorted(self.unknown_values)
-        includes = ['include']
-        if build_tree.looks_like_tf_psa_crypto_root('.'):
-            includes.append('drivers/builtin/include')
-        values = c_build_helper.get_c_expression_values(
-            'unsigned long', '%lu',
-            expressions,
-            header="""
-            #include <psa/crypto.h>
-            """,
-            include_path=includes) #type: List[str]
-        for e, v in zip(expressions, values):
-            self.value_cache[e] = int(v, 0)
-        self.unknown_values.clear()
-
-    @staticmethod
-    def normalize(string: str) -> str:
-        """Put the given C expression in a canonical form.
-
-        This function is only intended to give correct results for the
-        relatively simple kind of C expression typically used with this
-        module.
-        """
-        return re.sub(r'\s+', r'', string)
-
-    def value(self) -> int:
-        """Return the numerical value of the expression."""
-        if self.value_if_known is None:
-            if re.match(r'([0-9]+|0x[0-9a-f]+)\Z', self.string, re.I):
-                return int(self.string, 0)
-            normalized = self.normalize(self.string)
-            if normalized not in self.value_cache:
-                self.update_cache()
-            self.value_if_known = self.value_cache[normalized]
-        return self.value_if_known
-
-Exprable = Union[str, int, Expr]
-"""Something that can be converted to a C expression with a known numerical value."""
-
-def as_expr(thing: Exprable) -> Expr:
-    """Return an `Expr` object for `thing`.
-
-    If `thing` is already an `Expr` object, return it. Otherwise build a new
-    `Expr` object from `thing`. `thing` can be an integer or a string that
-    contains a C expression.
-    """
-    if isinstance(thing, Expr):
-        return thing
-    else:
-        return Expr(thing)
-
-
-class Key:
-    """Representation of a PSA crypto key object and its storage encoding.
-    """
-
-    LATEST_VERSION = 0
-    """The latest version of the storage format."""
-
-    def __init__(self, *,
-                 version: Optional[int] = None,
-                 id: Optional[int] = None, #pylint: disable=redefined-builtin
-                 lifetime: Exprable = 'PSA_KEY_LIFETIME_PERSISTENT',
-                 type: Exprable, #pylint: disable=redefined-builtin
-                 bits: int,
-                 usage: Exprable, alg: Exprable, alg2: Exprable,
-                 material: bytes #pylint: disable=used-before-assignment
-                ) -> None:
-        self.version = self.LATEST_VERSION if version is None else version
-        self.id = id #pylint: disable=invalid-name #type: Optional[int]
-        self.lifetime = as_expr(lifetime) #type: Expr
-        self.type = as_expr(type) #type: Expr
-        self.bits = bits #type: int
-        self.usage = as_expr(usage) #type: Expr
-        self.alg = as_expr(alg) #type: Expr
-        self.alg2 = as_expr(alg2) #type: Expr
-        self.material = material #type: bytes
-
-    MAGIC = b'PSA\000KEY\000'
-
-    @staticmethod
-    def pack(
-            fmt: str,
-            *args: Union[int, Expr]
-    ) -> bytes: #pylint: disable=used-before-assignment
-        """Pack the given arguments into a byte string according to the given format.
-
-        This function is similar to `struct.pack`, but with the following differences:
-        * All integer values are encoded with standard sizes and in
-          little-endian representation. `fmt` must not include an endianness
-          prefix.
-        * Arguments can be `Expr` objects instead of integers.
-        * Only integer-valued elements are supported.
-        """
-        return struct.pack('<' + fmt, # little-endian, standard sizes
-                           *[arg.value() if isinstance(arg, Expr) else arg
-                             for arg in args])
-
-    def bytes(self) -> bytes:
-        """Return the representation of the key in storage as a byte array.
-
-        This is the content of the PSA storage file. When PSA storage is
-        implemented over stdio files, this does not include any wrapping made
-        by the PSA-storage-over-stdio-file implementation.
-
-        Note that if you need to make a change in this function,
-        this may indicate that the key store is changing in a
-        backward-incompatible way! Think carefully about backward
-        compatibility before making any change here.
-        """
-        header = self.MAGIC + self.pack('L', self.version)
-        if self.version == 0:
-            attributes = self.pack('LHHLLL',
-                                   self.lifetime, self.type, self.bits,
-                                   self.usage, self.alg, self.alg2)
-            material = self.pack('L', len(self.material)) + self.material
-        else:
-            raise NotImplementedError
-        return header + attributes + material
-
-    def hex(self) -> str:
-        """Return the representation of the key as a hexadecimal string.
-
-        This is the hexadecimal representation of `self.bytes`.
-        """
-        return self.bytes().hex()
-
-    def location_value(self) -> int:
-        """The numerical value of the location encoded in the key's lifetime."""
-        return self.lifetime.value() >> 8
-
-
-class TestKey(unittest.TestCase):
-    # pylint: disable=line-too-long
-    """A few smoke tests for the functionality of the `Key` class."""
-
-    def test_numerical(self):
-        key = Key(version=0,
-                  id=1, lifetime=0x00000001,
-                  type=0x2400, bits=128,
-                  usage=0x00000300, alg=0x05500200, alg2=0x04c01000,
-                  material=b'@ABCDEFGHIJKLMNO')
-        expected_hex = '505341004b45590000000000010000000024800000030000000250050010c00410000000404142434445464748494a4b4c4d4e4f'
-        self.assertEqual(key.bytes(), bytes.fromhex(expected_hex))
-        self.assertEqual(key.hex(), expected_hex)
-
-    def test_names(self):
-        length = 0xfff8 // 8 # PSA_MAX_KEY_BITS in bytes
-        key = Key(version=0,
-                  id=1, lifetime='PSA_KEY_LIFETIME_PERSISTENT',
-                  type='PSA_KEY_TYPE_RAW_DATA', bits=length*8,
-                  usage=0, alg=0, alg2=0,
-                  material=b'\x00' * length)
-        expected_hex = '505341004b45590000000000010000000110f8ff000000000000000000000000ff1f0000' + '00' * length
-        self.assertEqual(key.bytes(), bytes.fromhex(expected_hex))
-        self.assertEqual(key.hex(), expected_hex)
-
-    def test_defaults(self):
-        key = Key(type=0x1001, bits=8,
-                  usage=0, alg=0, alg2=0,
-                  material=b'\x2a')
-        expected_hex = '505341004b455900000000000100000001100800000000000000000000000000010000002a'
-        self.assertEqual(key.bytes(), bytes.fromhex(expected_hex))
-        self.assertEqual(key.hex(), expected_hex)
diff --git a/scripts/mbedtls_dev/test_case.py b/scripts/mbedtls_dev/test_case.py
deleted file mode 100644
index 6ed5e84..0000000
--- a/scripts/mbedtls_dev/test_case.py
+++ /dev/null
@@ -1,91 +0,0 @@
-"""Library for constructing an Mbed TLS test case.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-import binascii
-import os
-import sys
-from typing import Iterable, List, Optional
-
-from . import typing_util
-
-def hex_string(data: bytes) -> str:
-    return '"' + binascii.hexlify(data).decode('ascii') + '"'
-
-
-class MissingDescription(Exception):
-    pass
-
-class MissingFunction(Exception):
-    pass
-
-class TestCase:
-    """An Mbed TLS test case."""
-
-    def __init__(self, description: Optional[str] = None):
-        self.comments = [] #type: List[str]
-        self.description = description #type: Optional[str]
-        self.dependencies = [] #type: List[str]
-        self.function = None #type: Optional[str]
-        self.arguments = [] #type: List[str]
-
-    def add_comment(self, *lines: str) -> None:
-        self.comments += lines
-
-    def set_description(self, description: str) -> None:
-        self.description = description
-
-    def set_dependencies(self, dependencies: List[str]) -> None:
-        self.dependencies = dependencies
-
-    def set_function(self, function: str) -> None:
-        self.function = function
-
-    def set_arguments(self, arguments: List[str]) -> None:
-        self.arguments = arguments
-
-    def check_completeness(self) -> None:
-        if self.description is None:
-            raise MissingDescription
-        if self.function is None:
-            raise MissingFunction
-
-    def write(self, out: typing_util.Writable) -> None:
-        """Write the .data file paragraph for this test case.
-
-        The output starts and ends with a single newline character. If the
-        surrounding code writes lines (consisting of non-newline characters
-        and a final newline), you will end up with a blank line before, but
-        not after the test case.
-        """
-        self.check_completeness()
-        assert self.description is not None # guide mypy
-        assert self.function is not None # guide mypy
-        out.write('\n')
-        for line in self.comments:
-            out.write('# ' + line + '\n')
-        out.write(self.description + '\n')
-        if self.dependencies:
-            out.write('depends_on:' + ':'.join(self.dependencies) + '\n')
-        out.write(self.function + ':' + ':'.join(self.arguments) + '\n')
-
-def write_data_file(filename: str,
-                    test_cases: Iterable[TestCase],
-                    caller: Optional[str] = None) -> None:
-    """Write the test cases to the specified file.
-
-    If the file already exists, it is overwritten.
-    """
-    if caller is None:
-        caller = os.path.basename(sys.argv[0])
-    tempfile = filename + '.new'
-    with open(tempfile, 'w') as out:
-        out.write('# Automatically generated by {}. Do not edit!\n'
-                  .format(caller))
-        for tc in test_cases:
-            tc.write(out)
-        out.write('\n# End of automatically generated file.\n')
-    os.replace(tempfile, filename)
diff --git a/scripts/mbedtls_dev/test_data_generation.py b/scripts/mbedtls_dev/test_data_generation.py
deleted file mode 100644
index a84f7dd..0000000
--- a/scripts/mbedtls_dev/test_data_generation.py
+++ /dev/null
@@ -1,224 +0,0 @@
-"""Common code for test data generation.
-
-This module defines classes that are of general use to automatically
-generate .data files for unit tests, as well as a main function.
-
-These are used both by generate_psa_tests.py and generate_bignum_tests.py.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-import argparse
-import os
-import posixpath
-import re
-import inspect
-
-from abc import ABCMeta, abstractmethod
-from typing import Callable, Dict, Iterable, Iterator, List, Type, TypeVar
-
-from . import build_tree
-from . import test_case
-
-T = TypeVar('T') #pylint: disable=invalid-name
-
-
-class BaseTest(metaclass=ABCMeta):
-    """Base class for test case generation.
-
-    Attributes:
-        count: Counter for test cases from this class.
-        case_description: Short description of the test case. This may be
-            automatically generated using the class, or manually set.
-        dependencies: A list of dependencies required for the test case.
-        show_test_count: Toggle for inclusion of `count` in the test description.
-        test_function: Test function which the class generates cases for.
-        test_name: A common name or description of the test function. This can
-            be `test_function`, a clearer equivalent, or a short summary of the
-            test function's purpose.
-    """
-    count = 0
-    case_description = ""
-    dependencies = [] # type: List[str]
-    show_test_count = True
-    test_function = ""
-    test_name = ""
-
-    def __new__(cls, *args, **kwargs):
-        # pylint: disable=unused-argument
-        cls.count += 1
-        return super().__new__(cls)
-
-    @abstractmethod
-    def arguments(self) -> List[str]:
-        """Get the list of arguments for the test case.
-
-        Override this method to provide the list of arguments required for
-        the `test_function`.
-
-        Returns:
-            List of arguments required for the test function.
-        """
-        raise NotImplementedError
-
-    def description(self) -> str:
-        """Create a test case description.
-
-        Creates a description of the test case, including a name for the test
-        function, an optional case count, and a description of the specific
-        test case. This should inform a reader what is being tested, and
-        provide context for the test case.
-
-        Returns:
-            Description for the test case.
-        """
-        if self.show_test_count:
-            return "{} #{} {}".format(
-                self.test_name, self.count, self.case_description
-                ).strip()
-        else:
-            return "{} {}".format(self.test_name, self.case_description).strip()
-
-
-    def create_test_case(self) -> test_case.TestCase:
-        """Generate TestCase from the instance."""
-        tc = test_case.TestCase()
-        tc.set_description(self.description())
-        tc.set_function(self.test_function)
-        tc.set_arguments(self.arguments())
-        tc.set_dependencies(self.dependencies)
-
-        return tc
-
-    @classmethod
-    @abstractmethod
-    def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
-        """Generate test cases for the class test function.
-
-        This will be called in classes where `test_function` is set.
-        Implementations should yield TestCase objects, by creating instances
-        of the class with appropriate input data, and then calling
-        `create_test_case()` on each.
-        """
-        raise NotImplementedError
-
-
-class BaseTarget:
-    #pylint: disable=too-few-public-methods
-    """Base target for test case generation.
-
-    Child classes of this class represent an output file, and can be referred
-    to as file targets. These indicate where test cases will be written to for
-    all subclasses of the file target, which is set by `target_basename`.
-
-    Attributes:
-        target_basename: Basename of file to write generated tests to. This
-            should be specified in a child class of BaseTarget.
-    """
-    target_basename = ""
-
-    @classmethod
-    def generate_tests(cls) -> Iterator[test_case.TestCase]:
-        """Generate test cases for the class and its subclasses.
-
-        In classes with `test_function` set, `generate_function_tests()` is
-        called to generate test cases first.
-
-        In all classes, this method will iterate over its subclasses, and
-        yield from `generate_tests()` in each. Calling this method on a class X
-        will yield test cases from all classes derived from X.
-        """
-        if issubclass(cls, BaseTest) and not inspect.isabstract(cls):
-            #pylint: disable=no-member
-            yield from cls.generate_function_tests()
-        for subclass in sorted(cls.__subclasses__(), key=lambda c: c.__name__):
-            yield from subclass.generate_tests()
-
-
-class TestGenerator:
-    """Generate test cases and write to data files."""
-    def __init__(self, options) -> None:
-        self.test_suite_directory = options.directory
-        # Update `targets` with an entry for each child class of BaseTarget.
-        # Each entry represents a file generated by the BaseTarget framework,
-        # and enables generating the .data files using the CLI.
-        self.targets.update({
-            subclass.target_basename: subclass.generate_tests
-            for subclass in BaseTarget.__subclasses__()
-            if subclass.target_basename
-        })
-
-    def filename_for(self, basename: str) -> str:
-        """The location of the data file with the specified base name."""
-        return posixpath.join(self.test_suite_directory, basename + '.data')
-
-    def write_test_data_file(self, basename: str,
-                             test_cases: Iterable[test_case.TestCase]) -> None:
-        """Write the test cases to a .data file.
-
-        The output file is ``basename + '.data'`` in the test suite directory.
-        """
-        filename = self.filename_for(basename)
-        test_case.write_data_file(filename, test_cases)
-
-    # Note that targets whose names contain 'test_format' have their content
-    # validated by `abi_check.py`.
-    targets = {} # type: Dict[str, Callable[..., Iterable[test_case.TestCase]]]
-
-    def generate_target(self, name: str, *target_args) -> None:
-        """Generate cases and write to data file for a target.
-
-        For target callables which require arguments, override this function
-        and pass these arguments using super() (see PSATestGenerator).
-        """
-        test_cases = self.targets[name](*target_args)
-        self.write_test_data_file(name, test_cases)
-
-def main(args, description: str, generator_class: Type[TestGenerator] = TestGenerator):
-    """Command line entry point."""
-    parser = argparse.ArgumentParser(description=description)
-    parser.add_argument('--list', action='store_true',
-                        help='List available targets and exit')
-    parser.add_argument('--list-for-cmake', action='store_true',
-                        help='Print \';\'-separated list of available targets and exit')
-    # If specified explicitly, this option may be a path relative to the
-    # current directory when the script is invoked. The default value
-    # is relative to the mbedtls root, which we don't know yet. So we
-    # can't set a string as the default value here.
-    parser.add_argument('--directory', metavar='DIR',
-                        help='Output directory (default: tests/suites)')
-    parser.add_argument('targets', nargs='*', metavar='TARGET',
-                        help='Target file to generate (default: all; "-": none)')
-    options = parser.parse_args(args)
-
-    # Change to the mbedtls root, to keep things simple. But first, adjust
-    # command line options that might be relative paths.
-    if options.directory is None:
-        options.directory = 'tests/suites'
-    else:
-        options.directory = os.path.abspath(options.directory)
-    build_tree.chdir_to_root()
-
-    generator = generator_class(options)
-    if options.list:
-        for name in sorted(generator.targets):
-            print(generator.filename_for(name))
-        return
-    # List in a cmake list format (i.e. ';'-separated)
-    if options.list_for_cmake:
-        print(';'.join(generator.filename_for(name)
-                       for name in sorted(generator.targets)), end='')
-        return
-    if options.targets:
-        # Allow "-" as a special case so you can run
-        # ``generate_xxx_tests.py - $targets`` and it works uniformly whether
-        # ``$targets`` is empty or not.
-        options.targets = [os.path.basename(re.sub(r'\.data\Z', r'', target))
-                           for target in options.targets
-                           if target != '-']
-    else:
-        options.targets = sorted(generator.targets)
-    for target in options.targets:
-        generator.generate_target(target)
diff --git a/scripts/mbedtls_dev/typing_util.py b/scripts/mbedtls_dev/typing_util.py
deleted file mode 100644
index 2ec448d..0000000
--- a/scripts/mbedtls_dev/typing_util.py
+++ /dev/null
@@ -1,28 +0,0 @@
-"""Auxiliary definitions used in type annotations.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-from typing import Any
-
-# The typing_extensions module is necessary for type annotations that are
-# checked with mypy. It is only used for type annotations or to define
-# things that are themselves only used for type annotations. It is not
-# available on a default Python installation. Therefore, try loading
-# what we need from it for the sake of mypy (which depends on, or comes
-# with, typing_extensions), and if not define substitutes that lack the
-# static type information but are good enough at runtime.
-try:
-    from typing_extensions import Protocol #pylint: disable=import-error
-except ImportError:
-    class Protocol: #type: ignore
-        #pylint: disable=too-few-public-methods
-        pass
-
-class Writable(Protocol):
-    """Abstract class for typing hints."""
-    # pylint: disable=no-self-use,too-few-public-methods,unused-argument
-    def write(self, text: str) -> Any:
-        ...
diff --git a/scripts/min_requirements.py b/scripts/min_requirements.py
index 9888abe..b36f906 100755
--- a/scripts/min_requirements.py
+++ b/scripts/min_requirements.py
@@ -14,7 +14,9 @@
 import typing
 
 from typing import List, Optional
-from mbedtls_dev import typing_util
+
+import framework_scripts_path # pylint: disable=unused-import
+from mbedtls_framework import typing_util
 
 def pylint_doesn_t_notice_that_certain_types_are_used_in_annotations(
         _list: List[typing.Any],
diff --git a/tests/.gitignore b/tests/.gitignore
index 973ebb5..838ea69 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -21,4 +21,6 @@
 /suites/*.generated.data
 /suites/test_suite_psa_crypto_storage_format.v[0-9]*.data
 /suites/test_suite_psa_crypto_storage_format.current.data
+/src/test_keys.h
+/src/test_certs.h
 ###END_GENERATED_FILES###
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 589643a..5bc38b4 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -21,7 +21,7 @@
 execute_process(
     COMMAND
         ${MBEDTLS_PYTHON_EXECUTABLE}
-        ${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_bignum_tests.py
+        ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_bignum_tests.py
         --list-for-cmake
     WORKING_DIRECTORY
         ${CMAKE_CURRENT_SOURCE_DIR}/..
@@ -33,7 +33,7 @@
 execute_process(
     COMMAND
         ${MBEDTLS_PYTHON_EXECUTABLE}
-        ${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_ecp_tests.py
+        ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_ecp_tests.py
         --list-for-cmake
     WORKING_DIRECTORY
         ${CMAKE_CURRENT_SOURCE_DIR}/..
@@ -45,7 +45,7 @@
 execute_process(
     COMMAND
         ${MBEDTLS_PYTHON_EXECUTABLE}
-        ${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_psa_tests.py
+        ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_psa_tests.py
         --list-for-cmake
     WORKING_DIRECTORY
         ${CMAKE_CURRENT_SOURCE_DIR}/..
@@ -81,16 +81,16 @@
             ${CMAKE_CURRENT_SOURCE_DIR}/..
         COMMAND
             ${MBEDTLS_PYTHON_EXECUTABLE}
-            ${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_bignum_tests.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_bignum_tests.py
             --directory ${CMAKE_CURRENT_BINARY_DIR}/suites
         DEPENDS
-            ${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_bignum_tests.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/bignum_common.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/bignum_core.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/bignum_mod_raw.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/bignum_mod.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_case.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_data_generation.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_bignum_tests.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/bignum_common.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/bignum_core.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/bignum_mod_raw.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/bignum_mod.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/test_case.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/test_data_generation.py
     )
     add_custom_command(
         OUTPUT
@@ -99,14 +99,14 @@
             ${CMAKE_CURRENT_SOURCE_DIR}/..
         COMMAND
             ${MBEDTLS_PYTHON_EXECUTABLE}
-            ${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_ecp_tests.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_ecp_tests.py
             --directory ${CMAKE_CURRENT_BINARY_DIR}/suites
         DEPENDS
-            ${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_ecp_tests.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/bignum_common.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/ecp.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_case.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_data_generation.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_ecp_tests.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/bignum_common.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/ecp.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/test_case.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/test_data_generation.py
     )
     add_custom_command(
         OUTPUT
@@ -115,17 +115,17 @@
             ${CMAKE_CURRENT_SOURCE_DIR}/..
         COMMAND
             ${MBEDTLS_PYTHON_EXECUTABLE}
-            ${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_psa_tests.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_psa_tests.py
             --directory ${CMAKE_CURRENT_BINARY_DIR}/suites
         DEPENDS
-            ${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_psa_tests.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/crypto_data_tests.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/crypto_knowledge.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/macro_collector.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/psa_information.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/psa_storage.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_case.py
-            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_data_generation.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_psa_tests.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/crypto_data_tests.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/crypto_knowledge.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/macro_collector.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/psa_information.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/psa_storage.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/test_case.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/mbedtls_framework/test_data_generation.py
             ${CMAKE_CURRENT_SOURCE_DIR}/../include/psa/crypto_config.h
             ${CMAKE_CURRENT_SOURCE_DIR}/../include/psa/crypto_values.h
             ${CMAKE_CURRENT_SOURCE_DIR}/../include/psa/crypto_extra.h
@@ -220,7 +220,7 @@
             test_suite_${data_name}.c
         COMMAND
             ${MBEDTLS_PYTHON_EXECUTABLE}
-            ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_test_code.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_test_code.py
             -f ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function
             -d ${data_file}
             -t ${CMAKE_CURRENT_SOURCE_DIR}/suites/main_test.function
@@ -229,7 +229,7 @@
             --helpers-file ${CMAKE_CURRENT_SOURCE_DIR}/suites/helpers.function
             -o .
         DEPENDS
-            ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_test_code.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../framework/scripts/generate_test_code.py
             ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function
             ${data_file}
             ${CMAKE_CURRENT_SOURCE_DIR}/suites/main_test.function
diff --git a/tests/Makefile b/tests/Makefile
index c2a0b84..1d5c768 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -18,28 +18,28 @@
 
 .PHONY: generated_files
 GENERATED_BIGNUM_DATA_FILES := $(patsubst tests/%,%,$(shell \
-	$(PYTHON) scripts/generate_bignum_tests.py --list || \
+	$(PYTHON) ../framework/scripts/generate_bignum_tests.py --list || \
 	echo FAILED \
 ))
 ifeq ($(GENERATED_BIGNUM_DATA_FILES),FAILED)
-$(error "$(PYTHON) scripts/generate_bignum_tests.py --list" failed)
+$(error "$(PYTHON) ../framework/scripts/generate_bignum_tests.py --list" failed)
 endif
 GENERATED_ECP_DATA_FILES := $(patsubst tests/%,%,$(shell \
-	$(PYTHON) scripts/generate_ecp_tests.py --list || \
+	$(PYTHON) ../framework/scripts/generate_ecp_tests.py --list || \
 	echo FAILED \
 ))
 ifeq ($(GENERATED_ECP_DATA_FILES),FAILED)
-$(error "$(PYTHON) scripts/generate_ecp_tests.py --list" failed)
+$(error "$(PYTHON) ../framework/scripts/generate_ecp_tests.py --list" failed)
 endif
 GENERATED_PSA_DATA_FILES := $(patsubst tests/%,%,$(shell \
-	$(PYTHON) scripts/generate_psa_tests.py --list || \
+	$(PYTHON) ../framework/scripts/generate_psa_tests.py --list || \
 	echo FAILED \
 ))
 ifeq ($(GENERATED_PSA_DATA_FILES),FAILED)
-$(error "$(PYTHON) scripts/generate_psa_tests.py --list" failed)
+$(error "$(PYTHON) ../framework/scripts/generate_psa_tests.py --list" failed)
 endif
 GENERATED_FILES := $(GENERATED_PSA_DATA_FILES) $(GENERATED_ECP_DATA_FILES) $(GENERATED_BIGNUM_DATA_FILES)
-generated_files: $(GENERATED_FILES)
+generated_files: $(GENERATED_FILES) src/test_keys.h src/test_certs.h
 
 # generate_bignum_tests.py and generate_psa_tests.py spend more time analyzing
 # inputs than generating outputs. Its inputs are the same no matter which files
@@ -49,36 +49,36 @@
 # a separate instance of the recipe for each output file.
 .SECONDARY: generated_bignum_test_data generated_ecp_test_data generated_psa_test_data
 $(GENERATED_BIGNUM_DATA_FILES): $(gen_file_dep) generated_bignum_test_data
-generated_bignum_test_data: scripts/generate_bignum_tests.py
-generated_bignum_test_data: ../scripts/mbedtls_dev/bignum_common.py
-generated_bignum_test_data: ../scripts/mbedtls_dev/bignum_core.py
-generated_bignum_test_data: ../scripts/mbedtls_dev/bignum_mod_raw.py
-generated_bignum_test_data: ../scripts/mbedtls_dev/bignum_mod.py
-generated_bignum_test_data: ../scripts/mbedtls_dev/test_case.py
-generated_bignum_test_data: ../scripts/mbedtls_dev/test_data_generation.py
+generated_bignum_test_data: ../framework/scripts/generate_bignum_tests.py
+generated_bignum_test_data: ../framework/scripts/mbedtls_framework/bignum_common.py
+generated_bignum_test_data: ../framework/scripts/mbedtls_framework/bignum_core.py
+generated_bignum_test_data: ../framework/scripts/mbedtls_framework/bignum_mod_raw.py
+generated_bignum_test_data: ../framework/scripts/mbedtls_framework/bignum_mod.py
+generated_bignum_test_data: ../framework/scripts/mbedtls_framework/test_case.py
+generated_bignum_test_data: ../framework/scripts/mbedtls_framework/test_data_generation.py
 generated_bignum_test_data:
 	echo "  Gen   $(GENERATED_BIGNUM_DATA_FILES)"
-	$(PYTHON) scripts/generate_bignum_tests.py
+	$(PYTHON) ../framework/scripts/generate_bignum_tests.py
 
 $(GENERATED_ECP_DATA_FILES): $(gen_file_dep) generated_ecp_test_data
-generated_ecp_test_data: scripts/generate_ecp_tests.py
-generated_ecp_test_data: ../scripts/mbedtls_dev/bignum_common.py
-generated_ecp_test_data: ../scripts/mbedtls_dev/ecp.py
-generated_ecp_test_data: ../scripts/mbedtls_dev/test_case.py
-generated_ecp_test_data: ../scripts/mbedtls_dev/test_data_generation.py
+generated_ecp_test_data: ../framework/scripts/generate_ecp_tests.py
+generated_ecp_test_data: ../framework/scripts/mbedtls_framework/bignum_common.py
+generated_ecp_test_data: ../framework/scripts/mbedtls_framework/ecp.py
+generated_ecp_test_data: ../framework/scripts/mbedtls_framework/test_case.py
+generated_ecp_test_data: ../framework/scripts/mbedtls_framework/test_data_generation.py
 generated_ecp_test_data:
 	echo "  Gen   $(GENERATED_ECP_DATA_FILES)"
-	$(PYTHON) scripts/generate_ecp_tests.py
+	$(PYTHON) ../framework/scripts/generate_ecp_tests.py
 
 $(GENERATED_PSA_DATA_FILES): $(gen_file_dep) generated_psa_test_data
-generated_psa_test_data: scripts/generate_psa_tests.py
-generated_psa_test_data: ../scripts/mbedtls_dev/crypto_data_tests.py
-generated_psa_test_data: ../scripts/mbedtls_dev/crypto_knowledge.py
-generated_psa_test_data: ../scripts/mbedtls_dev/macro_collector.py
-generated_psa_test_data: ../scripts/mbedtls_dev/psa_information.py
-generated_psa_test_data: ../scripts/mbedtls_dev/psa_storage.py
-generated_psa_test_data: ../scripts/mbedtls_dev/test_case.py
-generated_psa_test_data: ../scripts/mbedtls_dev/test_data_generation.py
+generated_psa_test_data: ../framework/scripts/generate_psa_tests.py
+generated_psa_test_data: ../framework/scripts/mbedtls_framework/crypto_data_tests.py
+generated_psa_test_data: ../framework/scripts/mbedtls_framework/crypto_knowledge.py
+generated_psa_test_data: ../framework/scripts/mbedtls_framework/macro_collector.py
+generated_psa_test_data: ../framework/scripts/mbedtls_framework/psa_information.py
+generated_psa_test_data: ../framework/scripts/mbedtls_framework/psa_storage.py
+generated_psa_test_data: ../framework/scripts/mbedtls_framework/test_case.py
+generated_psa_test_data: ../framework/scripts/mbedtls_framework/test_data_generation.py
 ## The generated file only depends on the options that are present in
 ## crypto_config.h, not on which options are set. To avoid regenerating this
 ## file all the time when switching between configurations, don't declare
@@ -90,7 +90,7 @@
 generated_psa_test_data: suites/test_suite_psa_crypto_metadata.data
 generated_psa_test_data:
 	echo "  Gen   $(GENERATED_PSA_DATA_FILES) ..."
-	$(PYTHON) scripts/generate_psa_tests.py
+	$(PYTHON) ../framework/scripts/generate_psa_tests.py
 
 # A test application is built for each suites/test_suite_*.data file.
 # Application name is same as .data file's base name and can be
@@ -112,6 +112,13 @@
 
 mbedtls_test: $(MBEDTLS_TEST_OBJS)
 
+src/test_certs.h: ../framework/scripts/generate_test_cert_macros.py \
+				  $($(PYTHON) ../framework/scripts/generate_test_cert_macros.py --list-dependencies)
+	$(PYTHON) ../framework/scripts/generate_test_cert_macros.py --output $@
+
+src/test_keys.h: ../framework/scripts/generate_test_keys.py
+	$(PYTHON) ../framework/scripts/generate_test_keys.py --output $@
+
 TEST_OBJS_DEPS = $(wildcard include/test/*.h include/test/*/*.h)
 ifdef RECORD_PSA_STATUS_COVERAGE_LOG
 # Explicitly depend on this header because on a clean copy of the source tree,
@@ -119,6 +126,7 @@
 # therefore the wildcard enumeration above doesn't include it.
 TEST_OBJS_DEPS += include/test/instrument_record_status.h
 endif
+TEST_OBJS_DEPS += src/test_certs.h src/test_keys.h
 
 # Rule to compile common test C files in src folder
 src/%.o : src/%.c $(TEST_OBJS_DEPS)
@@ -151,9 +159,9 @@
 # dot in .c file's base name.
 #
 .SECONDEXPANSION:
-%.c: suites/$$(firstword $$(subst ., ,$$*)).function suites/%.data scripts/generate_test_code.py suites/helpers.function suites/main_test.function suites/host_test.function
+%.c: suites/$$(firstword $$(subst ., ,$$*)).function suites/%.data ../framework/scripts/generate_test_code.py suites/helpers.function suites/main_test.function suites/host_test.function
 	echo "  Gen   $@"
-	$(PYTHON) scripts/generate_test_code.py -f suites/$(firstword $(subst ., ,$*)).function \
+	$(PYTHON) ../framework/scripts/generate_test_code.py -f suites/$(firstword $(subst ., ,$*)).function \
 		-d suites/$*.data \
 		-t suites/main_test.function \
 		-p suites/host_test.function \
@@ -169,10 +177,12 @@
 clean:
 ifndef WINDOWS
 	rm -rf $(BINARIES) *.c *.datax
-	rm -f src/*.o src/drivers/*.o src/test_helpers/*.o src/libmbed*
+	rm -f src/*.o src/drivers/*.o src/test_helpers/*.o src/libmbed* src/test_keys.h src/test_certs.h
+	rm -f src/test_keys.h src/test_certs.h
 	rm -f include/test/instrument_record_status.h
 	rm -f include/alt-extra/*/*_alt.h
 	rm -rf libtestdriver1
+	rm -rf libpsaclient libpsaserver
 	rm -f ../library/libtestdriver1.a
 else
 	if exist *.c del /Q /F *.c
@@ -180,6 +190,8 @@
 	if exist *.datax del /Q /F *.datax
 	if exist src/*.o del /Q /F src/*.o
 	if exist src/drivers/*.o del /Q /F src/drivers/*.o
+	if exist src/test_keys.h del /Q /F src/test_keys.h
+	if exist src/test_certs.h del /Q /F src/test_cers.h
 	if exist src/test_helpers/*.o del /Q /F src/test_helpers/*.o
 	if exist src/libmbed* del /Q /F src/libmed*
 	if exist include/test/instrument_record_status.h del /Q /F include/test/instrument_record_status.h
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index 01d2379..6dae31d 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -706,17 +706,43 @@
 ### Password used for PKCS8-encoded encrypted RSA keys
 keys_rsa_pkcs8_pwd = PolarSSLTest
 
-### Basic 1024-, 2048- and 4096-bit unencrypted RSA keys from which
+### Basic unencrypted RSA keys from which
 ### all other encrypted RSA keys are derived.
+keys_rsa_base =
+### TODO: the commands require OpenSSL 1.x to work as desired. With
+### OpenSSL 3.x, they produce pkcs8 files.
+rsa_pkcs1_768_clear.pem:
+	$(OPENSSL) genrsa -out $@ 768
+keys_rsa_base += rsa_pkcs1_768_clear.pem
+rsa_pkcs1_769_clear.pem:
+	$(OPENSSL) genrsa -out $@ 769
+keys_rsa_base += rsa_pkcs1_769_clear.pem
+rsa_pkcs1_770_clear.pem:
+	$(OPENSSL) genrsa -out $@ 770
+keys_rsa_base += rsa_pkcs1_770_clear.pem
+rsa_pkcs1_776_clear.pem:
+	$(OPENSSL) genrsa -out $@ 776
+keys_rsa_base += rsa_pkcs1_776_clear.pem
+rsa_pkcs1_784_clear.pem:
+	$(OPENSSL) genrsa -out $@ 784
+keys_rsa_base += rsa_pkcs1_784_clear.pem
 rsa_pkcs1_1024_clear.pem:
 	$(OPENSSL) genrsa -out $@ 1024
-all_final += rsa_pkcs1_1024_clear.pem
+keys_rsa_base += rsa_pkcs1_1024_clear.pem
 rsa_pkcs1_2048_clear.pem:
 	$(OPENSSL) genrsa -out $@ 2048
-all_final += rsa_pkcs1_2048_clear.pem
+keys_rsa_base += rsa_pkcs1_2048_clear.pem
 rsa_pkcs1_4096_clear.pem:
 	$(OPENSSL) genrsa -out $@ 4096
-all_final += rsa_pkcs1_4096_clear.pem
+keys_rsa_base += rsa_pkcs1_4096_clear.pem
+
+all_final += $(keys_rsa_base)
+
+### PKCS1-encoded, plaintext RSA keys in derived forms
+
+rsa_pkcs1_%.der: rsa_pkcs1_%.pem
+	$(OPENSSL) pkey -inform PEM -in $< -outform DER -out $@
+all_final += $(keys_rsa_base:.pem=.der)
 
 ###
 ### PKCS1-encoded, encrypted RSA keys
@@ -1170,8 +1196,8 @@
 ### Rules to generate all RSA keys from a particular class
 ###
 
-### Generate basic unencrypted RSA keys
-keys_rsa_unenc: rsa_pkcs1_1024_clear.pem rsa_pkcs1_2048_clear.pem rsa_pkcs1_4096_clear.pem
+### Generate cleartext RSA keys in derived formats
+keys_rsa_cleartext: $(keys_rsa_base) $(keys_rsa_base:.pem=.der)
 
 ### Generate PKCS1-encoded encrypted RSA keys
 keys_rsa_enc_basic: keys_rsa_enc_basic_1024 keys_rsa_enc_basic_2048 keys_rsa_enc_basic_4096
@@ -1183,7 +1209,8 @@
 keys_rsa_enc_pkcs8_v2: keys_rsa_enc_pkcs8_v2_1024 keys_rsa_enc_pkcs8_v2_2048 keys_rsa_enc_pkcs8_v2_4096 keys_rsa_enc_pkcs8_v2_1024_sha224 keys_rsa_enc_pkcs8_v2_2048_sha224 keys_rsa_enc_pkcs8_v2_4096_sha224 keys_rsa_enc_pkcs8_v2_1024_sha256 keys_rsa_enc_pkcs8_v2_2048_sha256 keys_rsa_enc_pkcs8_v2_4096_sha256 keys_rsa_enc_pkcs8_v2_1024_sha384 keys_rsa_enc_pkcs8_v2_2048_sha384 keys_rsa_enc_pkcs8_v2_4096_sha384 keys_rsa_enc_pkcs8_v2_1024_sha512 keys_rsa_enc_pkcs8_v2_2048_sha512 keys_rsa_enc_pkcs8_v2_4096_sha512
 
 ### Generate all RSA keys
-keys_rsa_all: keys_rsa_unenc keys_rsa_enc_basic keys_rsa_enc_pkcs8_v1 keys_rsa_enc_pkcs8_v2
+keys_rsa_all: keys_rsa_base keys_rsa_cleartext
+keys_rsa_all: keys_rsa_enc_basic keys_rsa_enc_pkcs8_v1 keys_rsa_enc_pkcs8_v2
 
 ################################################################
 #### Generate various EC keys
@@ -2092,72 +2119,6 @@
 	cat $^ > $@
 
 ################################################################
-#### Generate C format test certs header
-################################################################
-
-TEST_CERTS_H_INPUT_FILES=test-ca2.crt \
-					test-ca2.crt.der \
-					test-ca2.key.enc \
-					test-ca2.key.der \
-					test-ca-sha256.crt \
-					test-ca-sha256.crt.der \
-					test-ca-sha1.crt \
-					test-ca-sha1.crt.der \
-					test-ca.key \
-					test-ca.key.der \
-					server5.crt \
-					server5.crt.der \
-					server5.key \
-					server5.key.der \
-					server2-sha256.crt \
-					server2-sha256.crt.der \
-					server2.crt \
-					server2.crt.der \
-					server2.key \
-					server2.key.der \
-					cli2.crt \
-					cli2.crt.der \
-					cli2.key \
-					cli2.key.der \
-					cli-rsa-sha256.crt \
-					cli-rsa-sha256.crt.der \
-					cli-rsa.key \
-					cli-rsa.key.der
-../src/test_certs.h: ../scripts/generate_test_cert_macros.py \
-					 $(TEST_CERTS_H_INPUT_FILES)
-	../scripts/generate_test_cert_macros.py --output $@ \
-				--string TEST_CA_CRT_EC_PEM=test-ca2.crt \
-				--binary TEST_CA_CRT_EC_DER=test-ca2.crt.der \
-				--string TEST_CA_KEY_EC_PEM=test-ca2.key.enc \
-				--password TEST_CA_PWD_EC_PEM=PolarSSLTest \
-				--binary TEST_CA_KEY_EC_DER=test-ca2.key.der \
-				--string TEST_CA_CRT_RSA_SHA256_PEM=test-ca-sha256.crt \
-				--binary TEST_CA_CRT_RSA_SHA256_DER=test-ca-sha256.crt.der \
-				--string TEST_CA_CRT_RSA_SHA1_PEM=test-ca-sha1.crt \
-				--binary TEST_CA_CRT_RSA_SHA1_DER=test-ca-sha1.crt.der \
-				--string TEST_CA_KEY_RSA_PEM=test-ca.key \
-				--password TEST_CA_PWD_RSA_PEM=PolarSSLTest \
-				--binary TEST_CA_KEY_RSA_DER=test-ca.key.der \
-				--string TEST_SRV_CRT_EC_PEM=server5.crt \
-				--binary TEST_SRV_CRT_EC_DER=server5.crt.der \
-				--string TEST_SRV_KEY_EC_PEM=server5.key \
-				--binary TEST_SRV_KEY_EC_DER=server5.key.der \
-				--string TEST_SRV_CRT_RSA_SHA256_PEM=server2-sha256.crt \
-				--binary TEST_SRV_CRT_RSA_SHA256_DER=server2-sha256.crt.der \
-				--string TEST_SRV_CRT_RSA_SHA1_PEM=server2.crt \
-				--binary TEST_SRV_CRT_RSA_SHA1_DER=server2.crt.der \
-				--string TEST_SRV_KEY_RSA_PEM=server2.key \
-				--binary TEST_SRV_KEY_RSA_DER=server2.key.der \
-				--string TEST_CLI_CRT_EC_PEM=cli2.crt \
-				--binary TEST_CLI_CRT_EC_DER=cli2.crt.der \
-				--string TEST_CLI_KEY_EC_PEM=cli2.key \
-				--binary TEST_CLI_KEY_EC_DER=cli2.key.der \
-				--string TEST_CLI_CRT_RSA_PEM=cli-rsa-sha256.crt \
-				--binary TEST_CLI_CRT_RSA_DER=cli-rsa-sha256.crt.der \
-				--string TEST_CLI_KEY_RSA_PEM=cli-rsa.key \
-				--binary TEST_CLI_KEY_RSA_DER=cli-rsa.key.der
-
-################################################################
 #### Diffie-Hellman parameters
 ################################################################
 
@@ -2177,7 +2138,7 @@
 
 .PHONY: default all_final all
 .PHONY: keys_rsa_all
-.PHONY: keys_rsa_unenc keys_rsa_enc_basic
+.PHONY: keys_rsa_enc_basic
 .PHONY: keys_rsa_enc_pkcs8_v1 keys_rsa_enc_pkcs8_v2
 .PHONY: keys_rsa_enc_basic_1024 keys_rsa_enc_basic_2048 keys_rsa_enc_basic_4096
 .PHONY: keys_rsa_enc_pkcs8_v1_1024 keys_rsa_enc_pkcs8_v2_1024
diff --git a/tests/data_files/rsa_pkcs1_1024_clear.der b/tests/data_files/rsa_pkcs1_1024_clear.der
new file mode 100644
index 0000000..cec2c30
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_1024_clear.der
Binary files differ
diff --git a/tests/data_files/rsa_pkcs1_2048_clear.der b/tests/data_files/rsa_pkcs1_2048_clear.der
new file mode 100644
index 0000000..667051b
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_2048_clear.der
Binary files differ
diff --git a/tests/data_files/rsa_pkcs1_4096_clear.der b/tests/data_files/rsa_pkcs1_4096_clear.der
new file mode 100644
index 0000000..9dc971e
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_4096_clear.der
Binary files differ
diff --git a/tests/data_files/rsa_pkcs1_768_clear.der b/tests/data_files/rsa_pkcs1_768_clear.der
new file mode 100644
index 0000000..a80b891
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_768_clear.der
Binary files differ
diff --git a/tests/data_files/rsa_pkcs1_768_clear.pem b/tests/data_files/rsa_pkcs1_768_clear.pem
new file mode 100644
index 0000000..33140c3
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_768_clear.pem
@@ -0,0 +1,12 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBywIBAAJhANmJY6FPDF0oqQEJCSrTx+ezfCU8qB6NwF2SqrphhhRFCYaMiKeg
+bRVB4pCxjGrDM2iuwlMy2QqJo4TST4MgMbK44fG7fHip+IhD/lJAfSsL56ZKz3T9
+tlog4VFGynJL1wIDAQABAmEAjB02Etw7dnWOBaCwSumFxPOSbtmW37clxB+H3+yY
+081zyToTewSVvi9loxT5AHshHYt2P+c6ylbUUEV6ZhC3mDqYMcuQmX5pJ2MhaK4T
+cCihi9eBhROPzudJ27Jx84wBAjEA9CKkG30d9+PgbUp+KnMxZuavEG4U45EDEUOG
+5+MRgSnRlPz8JsiY+Q6ReeBaEZiBAjEA5BvToGaPFSkbFT1HiV4zEEDQoXrNUO/l
+vAP6p7fCLh2nnaIRIwuHwxTUhG8pe3hXAjEAzKJAtj3gockjc9ht+n0F2r/f28C5
+x6nkTVMxwCsHoCGCaATKAmRAPPrmG6dfN8KBAjAcwNkzPdpJW44bZkcPLL2ZDeJ+
+iGE7E5JM2d+Npp8mevx25Uftt/VcBNMpAm4jLy8CMHCcVdhdVFydsL8DSYRnWD8x
+1tn1npbAeyiMHBxyhDF9EP1me7rEHvJ4Wl61HSXQNA==
+-----END RSA PRIVATE KEY-----
diff --git a/tests/data_files/rsa_pkcs1_769_clear.der b/tests/data_files/rsa_pkcs1_769_clear.der
new file mode 100644
index 0000000..c4bfe6c
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_769_clear.der
Binary files differ
diff --git a/tests/data_files/rsa_pkcs1_769_clear.pem b/tests/data_files/rsa_pkcs1_769_clear.pem
new file mode 100644
index 0000000..25e12bd
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_769_clear.pem
@@ -0,0 +1,12 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBzAIBAAJhAbUzqda7ne4UGzC60NkNAXxewl/l7X5W1scvWQVKbshsSQoHcOPj
+12RmuuA2sR6MzTNxBxsb52HNbrlqZYN5L07uanwM2bio5xl1SFXN2p3hzE2EHlM1
+nBq0sSXbX4Ua+QIDAQABAmEA1RgMVPx3Wp50LkkwGErtiXgKV4GTQzwCTW13f0ur
+OYcGBpxf2sOnrWkg9r3RkKlg25cI5IVMb8HhHtmwqGxbmF08zu5e4Jb3zaR59lTs
+uOEhVudWBtSRsid6qZug0Pt9AjEBvN2EO7Vn0xMQPphOwMR7htVzxxsADRBHmS+1
+pppCFLOpwqVDObcnl3pVw2wGd3PTAjEA+5cKqX6tfKUwNR88/urAGg+T3YsqNs4t
+5t5HuGs7AsYj0xDTTvHEsIwaovCEwBKDAjBSTDiWQyz941zx94M6Lh8cBojwoJIV
+2JkmQak9NPRcmBAjricNmlB8uWj8ShO4LXkCMQDj0c0c2JIeibLSl7vzFf3oW2zJ
+M6iBQkh8g5GsZKVmCKgOC3FdTj6Oo//GxkdfaiMCMQGsQWYVeZ43Eqn+ZYSeX7Sz
+Fol0BMyjvKXTpCznqk9+c1T86c9Cw2Rd/7NLJmPmGR4=
+-----END RSA PRIVATE KEY-----
diff --git a/tests/data_files/rsa_pkcs1_770_clear.der b/tests/data_files/rsa_pkcs1_770_clear.der
new file mode 100644
index 0000000..89e140f
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_770_clear.der
Binary files differ
diff --git a/tests/data_files/rsa_pkcs1_770_clear.pem b/tests/data_files/rsa_pkcs1_770_clear.pem
new file mode 100644
index 0000000..0a707a8
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_770_clear.pem
@@ -0,0 +1,12 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBzQIBAAJhA0tr23/I4PgNNhnJdvdVGlg2hiAKKWD7kYcXGEZgPqTyY1rVND8q
+oqI7n9IJiC4A0l+N7lZceGVotMj/dPY1DTMWT01NsEJXh47lQJNdHhpJysZyodmF
++N71sstc2iynMQIDAQABAmEBGOm/nfwGEhg0YLpdSVuq/p6KZbl8trSTb+8dQrNj
+qgShWuuQD0ngCTDatlY+aTQTp82hyjT7+EtGfxzofA8pWHSV1uvuJVWamKy8AtV1
+YXo5lREZyjTgdJzuKjwIx00BAjEB4XPP3C/etfJzmCcCYoK+TYjSCdYdIbVIZZTR
+8xgarUBu2KzedKfcdR0H8yklRpxpAjEBwHe8tsyXpzbX8E0fe+qKGrp/hWeosThd
+3LbhYN+6NVs7YUkthICJa4TZfC5qyPuJAjEBxOtjTvvFoxsL/cYs6ymeB2jAVzqT
+O0PEcLOY8vzpE7V60eGGgO3taks+UFWT2KKJAjEAhCGDI2SiJe0dsDo41Xyj1f4u
+xjJlXFmcJgRn4O/p4ACSPTafR5PLaTdKELFoWvDpAjEBeGO+jrDgz6aoJ7eka8JM
+xAWHubm0UPsr7JILYSsxViJFWIVGwIgnJU4Ny8U5LhfS
+-----END RSA PRIVATE KEY-----
diff --git a/tests/data_files/rsa_pkcs1_776_clear.der b/tests/data_files/rsa_pkcs1_776_clear.der
new file mode 100644
index 0000000..a311c67
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_776_clear.der
Binary files differ
diff --git a/tests/data_files/rsa_pkcs1_776_clear.pem b/tests/data_files/rsa_pkcs1_776_clear.pem
new file mode 100644
index 0000000..e62f7b1
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_776_clear.pem
@@ -0,0 +1,12 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBzgIBAAJiANnXRUGM65e+JIE48z8L9fxWiIrBffeFynsFih4lhFrIliTf++Jy
+R98lR8TGLO0x2Cosfb+vPcX7+bNdvqOn3q53NcYYFnih7GuNHeC/BAsI6c5H2HT3
+Rw3LCJPBk/yXhFsCAwEAAQJhP/xdWV29LbsqGdLSkChBPrdkL+2ZxITF7tC3uxcm
+A0x73aT05ZTPy5m1tPTI6XsEjOHlZNkYUkqebCSAk+Jwoi8eMjqkejry7R92SBEx
+vRxhSxYkFiY3M1AxUO1km9QZYQIxDz25KT5pjdnXmcXon4wjsplmKlVXRoy11Cju
+kLLZLIM+wLW0nhiks0CsrNY6VTcL0wIxDksBCJ3sMRKQcUW/MLmorTHTvV5iraKr
+YS5A0e37Y4i/g3VEJrzWaTr1FpKMMwD4WQIxCO9w3KNAku9CHV8P8Gnii9SvNuZt
+kmjwOP/+TUrtU9FmOujMiVt9Q7IJChNWg5sQDQIxBMin1Ol+d0I+ZBszDazmPumx
+c+1WW8VZVRJ1EY50mHDZoLcsE0cbAGeCRobQM/X8KQIxAbOSOWnQiL+4QuY5rQ05
+W2BL3qSET7u75RcT3ePnaZsJf5CweulDtVOVy8cq2sXQWw==
+-----END RSA PRIVATE KEY-----
diff --git a/tests/data_files/rsa_pkcs1_784_clear.der b/tests/data_files/rsa_pkcs1_784_clear.der
new file mode 100644
index 0000000..94f3d3b
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_784_clear.der
Binary files differ
diff --git a/tests/data_files/rsa_pkcs1_784_clear.pem b/tests/data_files/rsa_pkcs1_784_clear.pem
new file mode 100644
index 0000000..b7b424b
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_784_clear.pem
@@ -0,0 +1,12 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIB0wIBAAJjAL2x2bcoZLRL21gXcWsVJpjy65T7t6lsg/7loYbeZoIM1YCbgOaw
+j3c2bkiToc53k1siXpXSLzdIyPCvs7Tm9q1mNHi4pMmiOU/49wXKZzEr8+iIMHXf
+GVxysbIsch/1m/yTAgMBAAECYhsXm5CdJETb0Kf0MS6qBqkxiJPun3yDExcElN0+
+RkWsr5F+pBpOfS75hya2bxWd3l2WyEA3JTTkveghmsOy3UzPC/IhQLGFYOsRg6ia
+yflUVObDrrdmXL0ysI2V4a0770MBAjIA3fXqP6Q8rg5WE2RddFeAGYTmfaDU9RGH
+8ee4w0kITTXOr23WHEgIYuspKMB01gvg+QIyANrJMJ8VzwJdeq28KSBTCtQawLGH
+mXzzsaSiD14hjEDQnVTkBEWMhtbyudm0NXjuOOsCMXj2gAbW9srUvUwsMlIpLYK6
+zvJAKE62kyPeaO7kakXJwS4R6dHX39oo1nGDESllp+ECMgDKEvcgiHEZuyNbIiZO
+H8UpoMgHcLn4adDSwYg2JgA3wTb/uFalsiS8lZXImSSmXEkfAjE3y7xpVjmzp3W2
+/iNSKwBWTOLyu06KQ03gQEtvuXyEk6Nx+8siz9RHyjKnRL4HzRM9
+-----END RSA PRIVATE KEY-----
diff --git a/tests/data_files/test_certs.h.jinja2 b/tests/data_files/test_certs.h.jinja2
index 4a64b3a..c420c79 100644
--- a/tests/data_files/test_certs.h.jinja2
+++ b/tests/data_files/test_certs.h.jinja2
@@ -5,7 +5,7 @@
  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
-/* THIS FILE is generated by `tests/scripts/generate_test_cert_macros.py` */
+/* THIS FILE is generated by `framework/scripts/generate_test_cert_macros.py` */
 /* *INDENT-OFF* */
 
 {% for mode, name, value in macros %}
@@ -40,3 +40,4 @@
     {% endif %}
 
 {% endfor %}
+/* End of generated file */
diff --git a/tests/psa-client-server/README.md b/tests/psa-client-server/README.md
new file mode 100644
index 0000000..e6d9c87
--- /dev/null
+++ b/tests/psa-client-server/README.md
@@ -0,0 +1,6 @@
+### PSA Crypto Client-Server Testing
+
+Everything in this directory should currently be considered experimental. We are adding features and extending CI support for it.
+
+Once stable, of production quality, and being tested by the CI, it will eventually be migrated into
+the [MbedTLS framework repository](https://github.com/Mbed-TLS/mbedtls-framework).
diff --git a/tests/psa-client-server/psasim/.gitignore b/tests/psa-client-server/psasim/.gitignore
new file mode 100644
index 0000000..4065abf
--- /dev/null
+++ b/tests/psa-client-server/psasim/.gitignore
@@ -0,0 +1,12 @@
+bin/*
+*.o
+*.so
+test/psa_ff_bootstrap.c
+test/psa_manifest/*
+test/client
+test/partition
+cscope.out
+*.orig
+*.swp
+*.DS_Store
+*psa_ff_bootstrap_*
diff --git a/tests/psa-client-server/psasim/Makefile b/tests/psa-client-server/psasim/Makefile
new file mode 100644
index 0000000..06d3059
--- /dev/null
+++ b/tests/psa-client-server/psasim/Makefile
@@ -0,0 +1,68 @@
+MAIN ?= src/client.c
+
+CFLAGS += -Wall -Werror -std=c99 -D_XOPEN_SOURCE=1 -D_POSIX_C_SOURCE=200809L
+
+ifeq ($(DEBUG),1)
+CFLAGS += -DDEBUG -O0 -g
+endif
+
+LIBPSACLIENT := -Llibpsaclient/ -lmbedcrypto -lmbedx509 -lmbedtls
+LIBPSASERVER := -Llibpsaserver/ -lmbedcrypto
+
+MBEDTLS_ROOT_PATH = ../../..
+COMMON_INCLUDE := -I./include -I$(MBEDTLS_ROOT_PATH)/include
+
+TEST_BIN = 	test/psa_client \
+			test/psa_partition
+
+GENERATED_H_FILES =	include/psa_manifest/manifest.h \
+					include/psa_manifest/pid.h \
+					include/psa_manifest/sid.h
+
+PSA_CLIENT_SRC = src/psa_ff_client.c \
+		 $(MAIN) \
+		 src/psa_sim_crypto_client.c \
+		 src/psa_sim_serialise.c
+
+PARTITION_SERVER_BOOTSTRAP = src/psa_ff_bootstrap_TEST_PARTITION.c
+
+PSA_SERVER_SRC = $(PARTITION_SERVER_BOOTSTRAP) \
+				 src/psa_ff_server.c \
+				 src/psa_sim_crypto_server.c \
+				 src/psa_sim_serialise.c
+
+.PHONY: all clean libpsaclient libpsaserver
+
+all: $(TEST_BIN)
+
+test/seedfile:
+	dd if=/dev/urandom of=./test/seedfile bs=64 count=1
+
+test/psa_client: $(PSA_CLIENT_SRC) $(GENERATED_H_FILES)
+	$(CC) $(COMMON_INCLUDE) $(CFLAGS) $(PSA_CLIENT_SRC) $(LIBPSACLIENT) $(LDFLAGS) -o $@
+
+test/psa_partition: $(PSA_SERVER_SRC) $(GENERATED_H_FILES) test/seedfile
+	$(CC) $(COMMON_INCLUDE) $(CFLAGS) $(PSA_SERVER_SRC) $(LIBPSASERVER) $(LDFLAGS) -o $@
+
+$(PARTITION_SERVER_BOOTSTRAP) $(GENERATED_H_FILES): src/manifest.json src/server.c
+	tools/psa_autogen.py src/manifest.json
+
+# Build MbedTLS libraries (crypto, x509 and tls) and copy them locally to
+# build client/server applications.
+#
+# Note: these rules assume that mbedtls_config.h is already configured by all.sh.
+# If not using all.sh then the user must do it manually.
+libpsaclient libpsaserver:
+	$(MAKE) -C $(MBEDTLS_ROOT_PATH)/library CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" libmbedcrypto.a libmbedx509.a libmbedtls.a
+	mkdir -p $@
+	cp $(MBEDTLS_ROOT_PATH)/library/libmbed*.a $@/
+	$(MAKE) -C $(MBEDTLS_ROOT_PATH) clean
+
+clean:
+	rm -f $(TEST_BIN)
+	rm -f $(PARTITION_SERVER_BOOTSTRAP)
+	rm -rf libpsaclient libpsaserver
+	rm -rf include/psa_manifest
+	rm -f test/psa_service_* test/psa_notify_*
+	rm -f test/*.log
+	rm -f test/seedfile
diff --git a/tests/psa-client-server/psasim/README.md b/tests/psa-client-server/psasim/README.md
new file mode 100644
index 0000000..1b950d6
--- /dev/null
+++ b/tests/psa-client-server/psasim/README.md
@@ -0,0 +1,61 @@
+# psasim
+
+This tool simulates a PSA Firmware Framework implementation.
+It allows you to develop secure partitions and their clients on a desktop computer.
+It should be able to run on all systems that support POSIX and System V IPC:
+e.g. macOS, Linux, FreeBSD, and perhaps Windows 10 WSL2.
+
+Please note that the code in this directory is maintained by the Mbed TLS / PSA Crypto project solely for the purpose of testing the use of Mbed TLS with client/service separation. We do not recommend using this code for any other purpose. In particular:
+
+* This simulator is not intended to pass or demonstrate compliance.
+* This code is only intended for simulation and does not have any security goals. It does not isolate services from clients.
+
+## Building
+
+To build and run the test program make sure you have `make`, `python` and a
+C compiler installed and then enter the following commands:
+
+```sh
+make run
+```
+
+Optionally the `DEBUG=1` command line option can be enabled to increase verbosity:
+
+```sh
+make DEBUG=1 run
+```
+
+Once done with the test, it is possible to clean all the generated files with:
+
+```sh
+make clean
+```
+
+## Features
+
+The implemented API is intended to be compliant with PSA-FF 1.0.0 with the exception of a couple of things that are a work in progress:
+
+* `psa_notify` support
+* "strict" policy in manifest
+
+The only supported "interrupts" are POSIX signals, which act
+as a "virtual interrupt".
+
+The standard PSA RoT APIs are not included (e.g. cryptography, attestation, lifecycle etc).
+
+## Design
+
+The code is designed to be readable rather than fast or secure.
+In this implementation only one message is delivered to a
+RoT service at a time.
+The code is not thread-safe.
+
+## Unsupported features
+
+Because this is a simulator there are a few things that
+can't be reasonably emulated:
+
+* Manifest MMIO regions are unsupported
+* Manifest priority field is ignored
+* Partition IDs are in fact POSIX `pid_t`, which are only assigned at runtime,
+  making it infeasible to populate pid.h with correct values.
diff --git a/tests/psa-client-server/psasim/include/client.h b/tests/psa-client-server/psasim/include/client.h
new file mode 100644
index 0000000..d48498e
--- /dev/null
+++ b/tests/psa-client-server/psasim/include/client.h
@@ -0,0 +1,75 @@
+/* PSA Firmware Framework client header for psasim. */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef __PSA_CLIENT_H__
+#define __PSA_CLIENT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "psa/crypto.h"
+
+#include "error_ext.h"
+/*********************** PSA Client Macros and Types *************************/
+
+#define PSA_FRAMEWORK_VERSION  (0x0100)
+
+#define PSA_VERSION_NONE       (0)
+
+/* PSA response types */
+#define PSA_CONNECTION_REFUSED PSA_ERROR_CONNECTION_REFUSED
+#define PSA_CONNECTION_BUSY    PSA_ERROR_CONNECTION_BUSY
+#define PSA_DROP_CONNECTION    PSA_ERROR_PROGRAMMER_ERROR
+
+/* PSA message handles */
+#define PSA_NULL_HANDLE        ((psa_handle_t) 0)
+
+#define PSA_HANDLE_IS_VALID(handle) ((psa_handle_t) (handle) > 0)
+#define PSA_HANDLE_TO_ERROR(handle) ((psa_status_t) (handle))
+
+/**
+ * A read-only input memory region provided to an RoT Service.
+ */
+typedef struct psa_invec {
+    const void *base;
+    size_t len;
+} psa_invec;
+
+/**
+ * A writable output memory region provided to an RoT Service.
+ */
+typedef struct psa_outvec {
+    void *base;
+    size_t len;
+} psa_outvec;
+
+/*************************** PSA Client API **********************************/
+
+uint32_t psa_framework_version(void);
+
+uint32_t psa_version(uint32_t sid);
+
+psa_handle_t psa_connect(uint32_t sid, uint32_t version);
+
+psa_status_t psa_call(psa_handle_t handle,
+                      int32_t type,
+                      const psa_invec *in_vec,
+                      size_t in_len,
+                      psa_outvec *out_vec,
+                      size_t out_len);
+
+void psa_close(psa_handle_t handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PSA_CLIENT_H__ */
diff --git a/tests/psa-client-server/psasim/include/common.h b/tests/psa-client-server/psasim/include/common.h
new file mode 100644
index 0000000..ee5b5a3
--- /dev/null
+++ b/tests/psa-client-server/psasim/include/common.h
@@ -0,0 +1,52 @@
+/* Common definitions used for clients and services */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+#include <stdint.h>
+#include <stddef.h>
+
+/* Increasing this might break on some platforms */
+#define MAX_FRAGMENT_SIZE 200
+
+#define CONNECT_REQUEST 1
+#define CALL_REQUEST 2
+#define CLOSE_REQUEST 3
+#define VERSION_REQUEST 4
+#define READ_REQUEST    5
+#define READ_RESPONSE   6
+#define WRITE_REQUEST   7
+#define WRITE_RESPONSE  8
+#define SKIP_REQUEST    9
+#define PSA_REPLY       10
+
+#define NON_SECURE (1 << 30)
+
+typedef int32_t psa_handle_t;
+
+#define PSA_MAX_IOVEC (4u)
+
+#define PSA_IPC_CALL (0)
+
+struct message_text {
+    int qid;
+    int32_t psa_type;
+    char buf[MAX_FRAGMENT_SIZE];
+};
+
+struct message {
+    long message_type;
+    struct message_text message_text;
+};
+
+typedef struct vector_sizes {
+    size_t invec_sizes[PSA_MAX_IOVEC];
+    size_t outvec_sizes[PSA_MAX_IOVEC];
+} vector_sizes_t;
+
+#endif /* _COMMON_H_ */
diff --git a/tests/psa-client-server/psasim/include/error_ext.h b/tests/psa-client-server/psasim/include/error_ext.h
new file mode 100644
index 0000000..6c82b8a
--- /dev/null
+++ b/tests/psa-client-server/psasim/include/error_ext.h
@@ -0,0 +1,19 @@
+/* PSA status codes used by psasim. */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_ERROR_H
+#define PSA_ERROR_H
+
+#include <stdint.h>
+
+#include "common.h"
+
+#define PSA_ERROR_PROGRAMMER_ERROR      ((psa_status_t) -129)
+#define PSA_ERROR_CONNECTION_REFUSED    ((psa_status_t) -130)
+#define PSA_ERROR_CONNECTION_BUSY       ((psa_status_t) -131)
+
+#endif
diff --git a/tests/psa-client-server/psasim/include/init.h b/tests/psa-client-server/psasim/include/init.h
new file mode 100644
index 0000000..de95d90
--- /dev/null
+++ b/tests/psa-client-server/psasim/include/init.h
@@ -0,0 +1,15 @@
+/* Declarations of internal functions. */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include <stdint.h>
+#include <service.h>
+void raise_signal(psa_signal_t signal);
+void __init_psasim(const char **array,
+                   int size,
+                   const int allow_ns_clients_array[32],
+                   const uint32_t versions[32],
+                   const int strict_policy_array[32]);
diff --git a/tests/psa-client-server/psasim/include/lifecycle.h b/tests/psa-client-server/psasim/include/lifecycle.h
new file mode 100644
index 0000000..1148397
--- /dev/null
+++ b/tests/psa-client-server/psasim/include/lifecycle.h
@@ -0,0 +1,17 @@
+/* PSA lifecycle states used by psasim. */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#define PSA_LIFECYCLE_PSA_STATE_MASK (0xff00u)
+#define PSA_LIFECYCLE_IMP_STATE_MASK (0x00ffu)
+#define PSA_LIFECYCLE_UNKNOWN (0x0000u)
+#define PSA_LIFECYCLE_ASSEMBLY_AND_TEST (0x1000u)
+#define PSA_LIFECYCLE_PSA_ROT_PROVISIONING (0x2000u)
+#define PSA_LIFECYCLE_SECURED (0x3000u)
+#define PSA_LIFECYCLE_NON_PSA_ROT_DEBUG (0x4000u)
+#define PSA_LIFECYCLE_RECOVERABLE_PSA_ROT_DEBUG (0x5000u)
+#define PSA_LIFECYCLE_DECOMMISSIONED (0x6000u)
+#define psa_rot_lifecycle_state(void) PSA_LIFECYCLE_UNKNOWN
diff --git a/tests/psa-client-server/psasim/include/service.h b/tests/psa-client-server/psasim/include/service.h
new file mode 100644
index 0000000..cbcb918
--- /dev/null
+++ b/tests/psa-client-server/psasim/include/service.h
@@ -0,0 +1,253 @@
+/* PSA Firmware Framework service header for psasim. */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef __PSA_SERVICE_H__
+#define __PSA_SERVICE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <stdlib.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#include "common.h"
+
+#include "psa/crypto.h"
+
+/********************** PSA Secure Partition Macros and Types ****************/
+
+/* PSA wait timeouts */
+#define PSA_POLL                (0x00000000u)
+#define PSA_BLOCK               (0x80000000u)
+
+/* A mask value that includes all Secure Partition signals */
+#define PSA_WAIT_ANY            (~0u)
+
+/* Doorbell signal */
+#define PSA_DOORBELL            (0x00000008u)
+
+/* PSA message types */
+#define PSA_IPC_CONNECT         (-1)
+#define PSA_IPC_DISCONNECT      (-2)
+
+/* Return code from psa_get() */
+#define PSA_ERR_NOMSG           (INT32_MIN + 3)
+
+/* Store a set of one or more Secure Partition signals */
+typedef uint32_t psa_signal_t;
+
+/**
+ * Describe a message received by an RoT Service after calling \ref psa_get().
+ */
+typedef struct psa_msg_t {
+    uint32_t type;              /* One of the following values:
+                                 * \ref PSA_IPC_CONNECT
+                                 * \ref PSA_IPC_CALL
+                                 * \ref PSA_IPC_DISCONNECT
+                                 */
+    psa_handle_t handle;        /* A reference generated by the SPM to the
+                                 * message returned by psa_get().
+                                 */
+    int32_t client_id;          /* Partition ID of the sender of the message */
+    void *rhandle;              /* Be useful for binding a connection to some
+                                 * application-specific data or function
+                                 * pointer within the RoT Service
+                                 * implementation.
+                                 */
+    size_t in_size[PSA_MAX_IOVEC]; /* Provide the size of each client input
+                                    * vector in bytes.
+                                    */
+    size_t out_size[PSA_MAX_IOVEC];/* Provide the size of each client output
+                                    * vector in bytes.
+                                    */
+} psa_msg_t;
+
+/************************* PSA Secure Partition API **************************/
+
+/**
+ * \brief Return the Secure Partition interrupt signals that have been asserted
+ *        from a subset of signals provided by the caller.
+ *
+ * \param[in] signal_mask       A set of signals to query. Signals that are not
+ *                              in this set will be ignored.
+ * \param[in] timeout           Specify either blocking \ref PSA_BLOCK or
+ *                              polling \ref PSA_POLL operation.
+ *
+ * \retval >0                   At least one signal is asserted.
+ * \retval 0                    No signals are asserted. This is only seen when
+ *                              a polling timeout is used.
+ */
+psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout);
+
+/**
+ * \brief Retrieve the message which corresponds to a given RoT Service signal
+ *        and remove the message from the RoT Service queue.
+ *
+ * \param[in] signal            The signal value for an asserted RoT Service.
+ * \param[out] msg              Pointer to \ref psa_msg_t object for receiving
+ *                              the message.
+ *
+ * \retval PSA_SUCCESS          Success, *msg will contain the delivered
+ *                              message.
+ * \retval PSA_ERR_NOMSG        Message could not be delivered.
+ * \retval "Does not return"    The call is invalid because one or more of the
+ *                              following are true:
+ * \arg                           signal has more than a single bit set.
+ * \arg                           signal does not correspond to an RoT Service.
+ * \arg                           The RoT Service signal is not currently
+ *                                asserted.
+ * \arg                           The msg pointer provided is not a valid memory
+ *                                reference.
+ */
+psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg);
+
+/**
+ * \brief Associate some RoT Service private data with a client connection.
+ *
+ * \param[in] msg_handle        Handle for the client's message.
+ * \param[in] rhandle           Reverse handle allocated by the RoT Service.
+ *
+ * \retval void                 Success, rhandle will be provided with all
+ *                              subsequent messages delivered on this
+ *                              connection.
+ * \retval "Does not return"    msg_handle is invalid.
+ */
+void psa_set_rhandle(psa_handle_t msg_handle, void *rhandle);
+
+/**
+ * \brief Read a message parameter or part of a message parameter from a client
+ *        input vector.
+ *
+ * \param[in] msg_handle        Handle for the client's message.
+ * \param[in] invec_idx         Index of the input vector to read from. Must be
+ *                              less than \ref PSA_MAX_IOVEC.
+ * \param[out] buffer           Buffer in the Secure Partition to copy the
+ *                              requested data to.
+ * \param[in] num_bytes         Maximum number of bytes to be read from the
+ *                              client input vector.
+ *
+ * \retval >0                   Number of bytes copied.
+ * \retval 0                    There was no remaining data in this input
+ *                              vector.
+ * \retval "Does not return"    The call is invalid, one or more of the
+ *                              following are true:
+ * \arg                           msg_handle is invalid.
+ * \arg                           msg_handle does not refer to a
+ *                                \ref PSA_IPC_CALL message.
+ * \arg                           invec_idx is equal to or greater than
+ *                                \ref PSA_MAX_IOVEC.
+ * \arg                           the memory reference for buffer is invalid or
+ *                                not writable.
+ */
+size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
+                void *buffer, size_t num_bytes);
+
+/**
+ * \brief Skip over part of a client input vector.
+ *
+ * \param[in] msg_handle        Handle for the client's message.
+ * \param[in] invec_idx         Index of input vector to skip from. Must be
+ *                              less than \ref PSA_MAX_IOVEC.
+ * \param[in] num_bytes         Maximum number of bytes to skip in the client
+ *                              input vector.
+ *
+ * \retval >0                   Number of bytes skipped.
+ * \retval 0                    There was no remaining data in this input
+ *                              vector.
+ * \retval "Does not return"    The call is invalid, one or more of the
+ *                              following are true:
+ * \arg                           msg_handle is invalid.
+ * \arg                           msg_handle does not refer to a
+ *                                \ref PSA_IPC_CALL message.
+ * \arg                           invec_idx is equal to or greater than
+ *                                \ref PSA_MAX_IOVEC.
+ */
+size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes);
+
+/**
+ * \brief Write a message response to a client output vector.
+ *
+ * \param[in] msg_handle        Handle for the client's message.
+ * \param[out] outvec_idx       Index of output vector in message to write to.
+ *                              Must be less than \ref PSA_MAX_IOVEC.
+ * \param[in] buffer            Buffer with the data to write.
+ * \param[in] num_bytes         Number of bytes to write to the client output
+ *                              vector.
+ *
+ * \retval void                 Success
+ * \retval "Does not return"    The call is invalid, one or more of the
+ *                              following are true:
+ * \arg                           msg_handle is invalid.
+ * \arg                           msg_handle does not refer to a
+ *                                \ref PSA_IPC_CALL message.
+ * \arg                           outvec_idx is equal to or greater than
+ *                                \ref PSA_MAX_IOVEC.
+ * \arg                           The memory reference for buffer is invalid.
+ * \arg                           The call attempts to write data past the end
+ *                                of the client output vector.
+ */
+void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
+               const void *buffer, size_t num_bytes);
+
+/**
+ * \brief Complete handling of a specific message and unblock the client.
+ *
+ * \param[in] msg_handle        Handle for the client's message.
+ * \param[in] status            Message result value to be reported to the
+ *                              client.
+ *
+ * \retval void                 Success.
+ * \retval "Does not return"    The call is invalid, one or more of the
+ *                              following are true:
+ * \arg                         msg_handle is invalid.
+ * \arg                         An invalid status code is specified for the
+ *                              type of message.
+ */
+void psa_reply(psa_handle_t msg_handle, psa_status_t status);
+
+/**
+ * \brief Send a PSA_DOORBELL signal to a specific Secure Partition.
+ *
+ * \param[in] partition_id      Secure Partition ID of the target partition.
+ *
+ * \retval void                 Success.
+ * \retval "Does not return"    partition_id does not correspond to a Secure
+ *                              Partition.
+ */
+void psa_notify(int32_t partition_id);
+
+/**
+ * \brief Clear the PSA_DOORBELL signal.
+ *
+ * \retval void                 Success.
+ * \retval "Does not return"    The Secure Partition's doorbell signal is not
+ *                              currently asserted.
+ */
+void psa_clear(void);
+
+/**
+ * \brief Inform the SPM that an interrupt has been handled (end of interrupt).
+ *
+ * \param[in] irq_signal        The interrupt signal that has been processed.
+ *
+ * \retval void                 Success.
+ * \retval "Does not return"    The call is invalid, one or more of the
+ *                              following are true:
+ * \arg                           irq_signal is not an interrupt signal.
+ * \arg                           irq_signal indicates more than one signal.
+ * \arg                           irq_signal is not currently asserted.
+ */
+void psa_eoi(psa_signal_t irq_signal);
+
+#define psa_panic(X) abort();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PSA_SERVICE_H__ */
diff --git a/tests/psa-client-server/psasim/include/util.h b/tests/psa-client-server/psasim/include/util.h
new file mode 100644
index 0000000..558149f
--- /dev/null
+++ b/tests/psa-client-server/psasim/include/util.h
@@ -0,0 +1,33 @@
+/* Common definitions used for clients and services */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "service.h"
+
+#define PRINT(fmt, ...) \
+    fprintf(stdout, fmt "\n", ##__VA_ARGS__)
+
+#if defined(DEBUG)
+#define INFO(fmt, ...) \
+    fprintf(stdout, "Info (%s - %d): " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
+
+#define ERROR(fmt, ...) \
+    fprintf(stdout, "Error (%s - %d): " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
+
+#define FATAL(fmt, ...) \
+    { \
+        fprintf(stdout, "Fatal (%s - %d): " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
+        abort(); \
+    }
+#else /* DEBUG */
+#define INFO(...)
+#define ERROR(...)
+#define FATAL(...)
+#endif /* DEBUG*/
+
+#define PROJECT_ID              'M'
+#define PATHNAMESIZE            256
+#define TMP_FILE_BASE_PATH      "./"
diff --git a/tests/psa-client-server/psasim/src/aut_psa_hash_compute.c b/tests/psa-client-server/psasim/src/aut_psa_hash_compute.c
new file mode 100644
index 0000000..519c072
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/aut_psa_hash_compute.c
@@ -0,0 +1,112 @@
+/*
+ *  API(s) under test: psa_hash_compute()
+ *
+ *  Taken from programs/psa/psa_hash.c, and calls to all hash APIs
+ *  but psa_hash_compute() removed.
+ *
+ *  Example computing a SHA-256 hash using the PSA Crypto API
+ *
+ *  The example computes the SHA-256 hash of a test string using the
+ *  one-shot API call psa_hash_compute().
+ *
+ *
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "psa/crypto.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mbedtls/build_info.h"
+#include "mbedtls/platform.h"
+
+/* Information about hashing with the PSA API can be
+ * found here:
+ * https://arm-software.github.io/psa-api/crypto/1.1/api/ops/hashes.html
+ *
+ * The algorithm used by this demo is SHA 256.
+ * Please see include/psa/crypto_values.h to see the other
+ * algorithms that are supported by Mbed TLS.
+ * If you switch to a different algorithm you will need to update
+ * the hash data in the EXAMPLE_HASH_VALUE macro below. */
+
+#if !defined(MBEDTLS_PSA_CRYPTO_C) || !defined(PSA_WANT_ALG_SHA_256)
+int main(void)
+{
+    mbedtls_printf("MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256"
+                   "not defined.\r\n");
+    return EXIT_SUCCESS;
+}
+#else
+
+#define HASH_ALG PSA_ALG_SHA_256
+
+const uint8_t sample_message[] = "Hello World!";
+/* sample_message is terminated with a null byte which is not part of
+ * the message itself so we make sure to subtract it in order to get
+ * the message length. */
+const size_t sample_message_length = sizeof(sample_message) - 1;
+
+#define EXPECTED_HASH_VALUE {                                                    \
+        0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81, \
+        0x48, 0xa1, 0xd6, 0x5d, 0xfc, 0x2d, 0x4b, 0x1f, 0xa3, 0xd6, 0x77, 0x28, \
+        0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69 \
+}
+
+const uint8_t expected_hash[] = EXPECTED_HASH_VALUE;
+const size_t expected_hash_len = sizeof(expected_hash);
+
+int main(void)
+{
+    psa_status_t status;
+    uint8_t hash[PSA_HASH_LENGTH(HASH_ALG)];
+    size_t hash_length;
+
+    mbedtls_printf("PSA Crypto API: SHA-256 example\n\n");
+
+    status = psa_crypto_init();
+    if (status != PSA_SUCCESS) {
+        mbedtls_printf("psa_crypto_init failed\n");
+        return EXIT_FAILURE;
+    }
+
+    /* Clear local variables prior to one-shot hash demo */
+    memset(hash, 0, sizeof(hash));
+    hash_length = 0;
+
+    /* Compute hash using one-shot function call */
+    status = psa_hash_compute(HASH_ALG,
+                              sample_message, sample_message_length,
+                              hash, sizeof(hash),
+                              &hash_length);
+    if (status != PSA_SUCCESS) {
+        mbedtls_printf("psa_hash_compute failed\n");
+        goto cleanup;
+    }
+
+    if (hash_length != expected_hash_len ||
+        (memcmp(hash, expected_hash, expected_hash_len) != 0)) {
+        mbedtls_printf("One-shot hash operation gave the wrong result!\n\n");
+        goto cleanup;
+    }
+
+    mbedtls_printf("One-shot hash operation successful!\n\n");
+
+    /* Print out result */
+    mbedtls_printf("The SHA-256( '%s' ) is: ", sample_message);
+
+    for (size_t j = 0; j < expected_hash_len; j++) {
+        mbedtls_printf("%02x", hash[j]);
+    }
+
+    mbedtls_printf("\n");
+
+    mbedtls_psa_crypto_free();
+    return EXIT_SUCCESS;
+
+cleanup:
+    return EXIT_FAILURE;
+}
+#endif /* !MBEDTLS_PSA_CRYPTO_C || !PSA_WANT_ALG_SHA_256 */
diff --git a/tests/psa-client-server/psasim/src/client.c b/tests/psa-client-server/psasim/src/client.c
new file mode 100644
index 0000000..a8c9e08
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/client.c
@@ -0,0 +1,21 @@
+/* psasim test client */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+/* Includes from mbedtls */
+#include "psa/crypto.h"
+
+int main()
+{
+    /* psa_crypto_init() connects to the server */
+    psa_status_t status = psa_crypto_init();
+    if (status != PSA_SUCCESS) {
+        return 1;
+    }
+
+    mbedtls_psa_crypto_free();
+    return 0;
+}
diff --git a/tests/psa-client-server/psasim/src/manifest.json b/tests/psa-client-server/psasim/src/manifest.json
new file mode 100644
index 0000000..e67b636
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/manifest.json
@@ -0,0 +1,29 @@
+{
+   "psa_framework_version":1.0,
+   "name":"TEST_PARTITION",
+   "type":"PSA-ROT",
+   "priority":"LOW",
+   "entry_point":"psa_server_main",
+   "stack_size":"0x400",
+   "heap_size":"0x100",
+   "services":[
+      {
+         "name":"PSA_SID_CRYPTO",
+         "sid":"0x0000F000",
+         "signal":"PSA_CRYPTO",
+         "non_secure_clients": "true",
+         "minor_version":1,
+         "minor_policy":"STRICT"
+      }
+   ],
+   "irqs": [
+        {
+                "source": "SIGINT",
+                "signal": "SIGINT_SIG"
+        },
+        {
+                "source": "SIGTSTP",
+                "signal": "SIGSTP_SIG"
+        }
+   ]
+}
diff --git a/tests/psa-client-server/psasim/src/psa_ff_client.c b/tests/psa-client-server/psasim/src/psa_ff_client.c
new file mode 100644
index 0000000..21a43b3
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/psa_ff_client.c
@@ -0,0 +1,386 @@
+/* PSA firmware framework client API */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+
+#include "client.h"
+#include "common.h"
+#include "error_ext.h"
+#include "util.h"
+
+typedef struct internal_handle {
+    int server_qid;
+    int client_qid;
+    int internal_server_qid;
+    int valid;
+} internal_handle_t;
+
+typedef struct vectors {
+    const psa_invec *in_vec;
+    size_t in_len;
+    psa_outvec *out_vec;
+    size_t out_len;
+} vectors_t;
+
+/* Note that this implementation is functional and not secure */
+int __psa_ff_client_security_state = NON_SECURE;
+
+/* Access to this global is not thread safe */
+#define MAX_HANDLES 32
+static internal_handle_t handles[MAX_HANDLES] = { { 0 } };
+
+static int get_next_free_handle()
+{
+    /* Never return handle 0 as it's a special null handle */
+    for (int i = 1; i < MAX_HANDLES; i++) {
+        if (handles[i].valid == 0) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+static int handle_is_valid(psa_handle_t handle)
+{
+    if (handle > 0 && handle < MAX_HANDLES) {
+        if (handles[handle].valid == 1) {
+            return 1;
+        }
+    }
+    ERROR("ERROR: Invalid handle");
+    return 0;
+}
+
+static int get_queue_info(char *path, int *cqid, int *sqid)
+{
+    key_t server_queue_key;
+    int rx_qid, server_qid;
+
+    INFO("Attempting to contact a RoT service queue");
+
+    if ((rx_qid = msgget(IPC_PRIVATE, 0660)) == -1) {
+        ERROR("msgget: rx_qid");
+        return -1;
+    }
+
+    if ((server_queue_key = ftok(path, PROJECT_ID)) == -1) {
+        ERROR("ftok");
+        return -2;
+    }
+
+    if ((server_qid = msgget(server_queue_key, 0)) == -1) {
+        ERROR("msgget: server_qid");
+        return -3;
+    }
+
+    *cqid = rx_qid;
+    *sqid = server_qid;
+
+    return 0;
+}
+
+static psa_status_t process_response(int rx_qid, vectors_t *vecs, int type,
+                                     int *internal_server_qid)
+{
+    struct message response, request;
+    psa_status_t ret = PSA_ERROR_CONNECTION_REFUSED;
+    size_t invec_seek[4] = { 0 };
+    size_t data_size;
+    psa_status_t invec, outvec; /* TODO: Should these be size_t ? */
+
+    assert(internal_server_qid > 0);
+
+    while (1) {
+        data_size = 0;
+        invec = 0;
+        outvec = 0;
+
+        /* read response from server */
+        if (msgrcv(rx_qid, &response, sizeof(struct message_text), 0, 0) == -1) {
+            ERROR("   msgrcv failed");
+            return ret;
+        }
+
+        /* process return message from server */
+        switch (response.message_type) {
+            case PSA_REPLY:
+                memcpy(&ret, response.message_text.buf, sizeof(psa_status_t));
+                INFO("   Message received from server: %d", ret);
+                if (type == PSA_IPC_CONNECT && ret > 0) {
+                    *internal_server_qid = ret;
+                    INFO("   ASSSIGNED q ID %d", *internal_server_qid);
+                    ret = PSA_SUCCESS;
+                }
+                return ret;
+                break;
+            case READ_REQUEST:
+                /* read data request */
+                request.message_type = READ_RESPONSE;
+
+                assert(vecs != 0);
+
+                memcpy(&invec, response.message_text.buf, sizeof(psa_status_t));
+                memcpy(&data_size, response.message_text.buf+sizeof(size_t), sizeof(size_t));
+                INFO("   Partition asked for %lu bytes from invec %d", data_size, invec);
+
+                /* need to add more checks here */
+                assert(invec >= 0 && invec < PSA_MAX_IOVEC);
+
+                if (data_size > MAX_FRAGMENT_SIZE) {
+                    data_size = MAX_FRAGMENT_SIZE;
+                }
+
+                /* send response */
+                INFO("   invec_seek[invec] is %lu", invec_seek[invec]);
+                INFO("   Reading from offset %p", vecs->in_vec[invec].base + invec_seek[invec]);
+                memcpy(request.message_text.buf,
+                       (vecs->in_vec[invec].base + invec_seek[invec]),
+                       data_size);
+
+                /* update invec base TODO: check me */
+                invec_seek[invec] = invec_seek[invec] + data_size;
+
+                INFO("   Sending message of type %li", request.message_type);
+                INFO("       with content %s", request.message_text.buf);
+
+                if (msgsnd(*internal_server_qid, &request,
+                           sizeof(int) + sizeof(uint32_t) + data_size, 0) == -1) {
+                    ERROR("Internal error: failed to respond to read request");
+                }
+                break;
+            case WRITE_REQUEST:
+                assert(vecs != 0);
+
+                request.message_type = WRITE_RESPONSE;
+
+                memcpy(&outvec, response.message_text.buf, sizeof(psa_status_t));
+                memcpy(&data_size, response.message_text.buf + sizeof(size_t), sizeof(size_t));
+                INFO("   Partition wants to write %lu bytes to outvec %d", data_size, outvec);
+
+                assert(outvec >= 0 && outvec < PSA_MAX_IOVEC);
+
+                /* copy memory into message and send back amount written */
+                size_t sofar = vecs->out_vec[outvec].len;
+                memcpy(vecs->out_vec[outvec].base + sofar,
+                       response.message_text.buf+(sizeof(size_t)*2), data_size);
+                INFO("   Data size is %lu", data_size);
+                vecs->out_vec[outvec].len += data_size;
+
+                INFO("   Sending message of type %li", request.message_type);
+
+                /* send response */
+                if (msgsnd(*internal_server_qid, &request, sizeof(int) + data_size, 0) == -1) {
+                    ERROR("Internal error: failed to respond to write request");
+                }
+                break;
+            case SKIP_REQUEST:
+                memcpy(&invec, response.message_text.buf, sizeof(psa_status_t));
+                memcpy(&data_size, response.message_text.buf+sizeof(size_t), sizeof(size_t));
+                INFO("   Partition asked to skip %lu bytes in invec %d", data_size, invec);
+                assert(invec >= 0 && invec < PSA_MAX_IOVEC);
+                /* update invec base TODO: check me */
+                invec_seek[invec] = invec_seek[invec] + data_size;
+                break;
+
+            default:
+                FATAL("   ERROR: unknown internal message type: %ld",
+                      response.message_type);
+                return ret;
+        }
+    }
+}
+
+static psa_status_t send(int rx_qid, int server_qid, int *internal_server_qid,
+                         int32_t type, uint32_t minor_version, vectors_t *vecs)
+{
+    psa_status_t ret = PSA_ERROR_CONNECTION_REFUSED;
+    size_t request_msg_size = (sizeof(int) + sizeof(long)); /* msg type plus queue id */
+    struct message request;
+    request.message_type = 1; /* TODO: change this */
+    request.message_text.psa_type = type;
+    vector_sizes_t vec_sizes;
+
+    /* If the client is non-secure then set the NS bit */
+    if (__psa_ff_client_security_state != 0) {
+        request.message_type |= NON_SECURE;
+    }
+
+    assert(request.message_type >= 0);
+
+    INFO("SEND: Sending message of type %ld with psa_type %d", request.message_type, type);
+    INFO("     internal_server_qid = %i", *internal_server_qid);
+
+    request.message_text.qid = rx_qid;
+
+    if (type == PSA_IPC_CONNECT) {
+        memcpy(request.message_text.buf, &minor_version, sizeof(minor_version));
+        request_msg_size = request_msg_size + sizeof(minor_version);
+        INFO("   Request msg size is %lu", request_msg_size);
+    } else {
+        assert(internal_server_qid > 0);
+    }
+
+    if (vecs != NULL && type >= PSA_IPC_CALL) {
+
+        memset(&vec_sizes, 0, sizeof(vec_sizes));
+
+        /* Copy invec sizes */
+        for (size_t i = 0; i < (vecs->in_len); i++) {
+            vec_sizes.invec_sizes[i] = vecs->in_vec[i].len;
+            INFO("   Client sending vector %lu: %lu", i, vec_sizes.invec_sizes[i]);
+        }
+
+        /* Copy outvec sizes */
+        for (size_t i = 0; i < (vecs->out_len); i++) {
+            vec_sizes.outvec_sizes[i] = vecs->out_vec[i].len;
+
+            /* Reset to 0 since we need to eventually fill in with bytes written */
+            vecs->out_vec[i].len = 0;
+        }
+
+        memcpy(request.message_text.buf, &vec_sizes, sizeof(vec_sizes));
+        request_msg_size = request_msg_size + sizeof(vec_sizes);
+    }
+
+    INFO("   Sending and then waiting");
+
+    /* send message to server */
+    if (msgsnd(server_qid, &request, request_msg_size, 0) == -1) {
+        ERROR("   msgsnd failed");
+        return ret;
+    }
+
+    return process_response(rx_qid, vecs, type, internal_server_qid);
+}
+
+
+uint32_t psa_framework_version(void)
+{
+    return PSA_FRAMEWORK_VERSION;
+}
+
+psa_handle_t psa_connect(uint32_t sid, uint32_t minor_version)
+{
+    int idx;
+    psa_status_t ret;
+    char pathname[PATHNAMESIZE] = { 0 };
+
+    idx = get_next_free_handle();
+
+    /* if there's a free handle available */
+    if (idx >= 0) {
+        snprintf(pathname, PATHNAMESIZE - 1, TMP_FILE_BASE_PATH "psa_service_%u", sid);
+        INFO("Attempting to contact RoT service at %s", pathname);
+
+        /* if communication is possible */
+        if (get_queue_info(pathname, &handles[idx].client_qid, &handles[idx].server_qid) >= 0) {
+
+            ret = send(handles[idx].client_qid,
+                       handles[idx].server_qid,
+                       &handles[idx].internal_server_qid,
+                       PSA_IPC_CONNECT,
+                       minor_version,
+                       NULL);
+
+            /* if connection accepted by RoT service */
+            if (ret >= 0) {
+                handles[idx].valid = 1;
+                return idx;
+            } else {
+                INFO("Server didn't like you");
+            }
+        } else {
+            INFO("Couldn't contact RoT service. Does it exist?");
+
+            if (__psa_ff_client_security_state == 0) {
+                ERROR("Invalid SID");
+            }
+        }
+    }
+
+    INFO("Couldn't obtain a free handle");
+    return PSA_ERROR_CONNECTION_REFUSED;
+}
+
+uint32_t psa_version(uint32_t sid)
+{
+    int idx;
+    psa_status_t ret;
+    char pathname[PATHNAMESIZE] = { 0 };
+
+    idx = get_next_free_handle();
+
+    if (idx >= 0) {
+        snprintf(pathname, PATHNAMESIZE, TMP_FILE_BASE_PATH "psa_service_%u", sid);
+        if (get_queue_info(pathname, &handles[idx].client_qid, &handles[idx].server_qid) >= 0) {
+            ret = send(handles[idx].client_qid,
+                       handles[idx].server_qid,
+                       &handles[idx].internal_server_qid,
+                       VERSION_REQUEST,
+                       0,
+                       NULL);
+            INFO("psa_version: Recieved from server %d", ret);
+            if (ret > 0) {
+                return ret;
+            }
+        }
+    }
+    INFO("psa_version failed: does the service exist?");
+    return PSA_VERSION_NONE;
+}
+
+psa_status_t psa_call(psa_handle_t handle,
+                      int32_t type,
+                      const psa_invec *in_vec,
+                      size_t in_len,
+                      psa_outvec *out_vec,
+                      size_t out_len)
+{
+    handle_is_valid(handle);
+
+    if ((in_len + out_len) > PSA_MAX_IOVEC) {
+        ERROR("Too many iovecs: %lu + %lu", in_len, out_len);
+    }
+
+    vectors_t vecs = { 0 };
+    vecs.in_vec = in_vec;
+    vecs.in_len = in_len;
+    vecs.out_vec = out_vec;
+    vecs.out_len = out_len;
+
+    return send(handles[handle].client_qid,
+                handles[handle].server_qid,
+                &handles[handle].internal_server_qid,
+                type,
+                0,
+                &vecs);
+}
+
+void psa_close(psa_handle_t handle)
+{
+    handle_is_valid(handle);
+    if (send(handles[handle].client_qid, handles[handle].server_qid,
+             &handles[handle].internal_server_qid, PSA_IPC_DISCONNECT, 0, NULL)) {
+        ERROR("ERROR: Couldn't send disconnect msg");
+    } else {
+        if (msgctl(handles[handle].client_qid, IPC_RMID, NULL) != 0) {
+            ERROR("ERROR: Failed to delete msg queue");
+        }
+    }
+    INFO("Closing handle %u", handle);
+    handles[handle].valid = 0;
+}
diff --git a/tests/psa-client-server/psasim/src/psa_ff_server.c b/tests/psa-client-server/psasim/src/psa_ff_server.c
new file mode 100644
index 0000000..219722a
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/psa_ff_server.c
@@ -0,0 +1,665 @@
+/* PSA Firmware Framework service API */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <time.h>
+#include <assert.h>
+
+#include "service.h"
+#include "init.h"
+#include "error_ext.h"
+#include "common.h"
+#include "util.h"
+
+#define MAX_CLIENTS 128
+#define MAX_MESSAGES 32
+
+#define SLEEP_MS        50
+
+struct connection {
+    uint32_t client;
+    void *rhandle;
+    int client_to_server_q;
+};
+
+/* Note that this implementation is functional and not secure. */
+int __psa_ff_client_security_state = NON_SECURE;
+
+static psa_msg_t messages[MAX_MESSAGES]; /* Message slots */
+static uint8_t pending_message[MAX_MESSAGES] = { 0 }; /* Booleans indicating active message slots */
+static uint32_t message_client[MAX_MESSAGES] = { 0 }; /* Each client's response queue  */
+static int nsacl[32];
+static int strict_policy[32] = { 0 };
+static uint32_t rot_svc_versions[32];
+static int rot_svc_incoming_queue[32] = { -1 };
+static struct connection connections[MAX_CLIENTS] = { { 0 } };
+
+static uint32_t exposed_signals = 0;
+
+void print_vectors(vector_sizes_t *sizes)
+{
+    INFO("Printing iovec sizes");
+    for (int j = 0; j < PSA_MAX_IOVEC; j++) {
+        INFO("Invec  %d: %lu", j, sizes->invec_sizes[j]);
+    }
+
+    for (int j = 0; j < PSA_MAX_IOVEC; j++) {
+        INFO("Outvec %d: %lu", j, sizes->outvec_sizes[j]);
+    }
+}
+
+int find_connection(uint32_t client)
+{
+    for (int i = 1; i < MAX_CLIENTS; i++) {
+        if (client == connections[i].client) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+void destroy_connection(uint32_t client)
+{
+    int idx = find_connection(client);
+    if (idx >= 0) {
+        connections[idx].client = 0;
+        connections[idx].rhandle = 0;
+        INFO("Destroying connection");
+    } else {
+        ERROR("Couldn't destroy connection for %u", client);
+    }
+}
+
+int find_free_connection()
+{
+    INFO("Allocating connection");
+    return find_connection(0);
+}
+
+static void reply(psa_handle_t msg_handle, psa_status_t status)
+{
+    pending_message[msg_handle] = 1;
+    psa_reply(msg_handle, status);
+    pending_message[msg_handle] = 0;
+}
+
+psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout)
+{
+    psa_signal_t mask;
+    struct message msg;
+    vector_sizes_t sizes;
+    struct msqid_ds qinfo;
+    uint32_t requested_version;
+    ssize_t len;
+    int idx;
+#if !defined(PSASIM_USE_USLEEP)
+    const struct timespec ts_delay = { .tv_sec = 0, .tv_nsec = SLEEP_MS * 1000000 };
+#endif
+
+    if (timeout == PSA_POLL) {
+        INFO("psa_wait: Called in polling mode");
+    }
+
+    do {
+        mask = signal_mask;
+
+        /* Check the status of each queue */
+        for (int i = 0; i < 32; i++) {
+            if (mask & 0x1) {
+                if (i < 3) {
+                    // do nothing (reserved)
+                } else if (i == 3) {
+                    // this must be psa doorbell
+                } else {
+                    /* Check if this signal corresponds to a queue */
+                    if (rot_svc_incoming_queue[i] >= 0 && (pending_message[i] == 0)) {
+
+                        /* AFAIK there is no "peek" method in SysV, so try to get a message */
+                        len = msgrcv(rot_svc_incoming_queue[i],
+                                     &msg,
+                                     sizeof(struct message_text),
+                                     0,
+                                     IPC_NOWAIT);
+                        if (len > 0) {
+
+                            INFO("Storing that QID in message_client[%d]", i);
+                            INFO("The message handle will be %d", i);
+
+                            msgctl(rot_svc_incoming_queue[i], IPC_STAT, &qinfo);
+                            messages[i].client_id = qinfo.msg_lspid; /* PID of last msgsnd(2) call */
+                            message_client[i] = msg.message_text.qid;
+                            idx = find_connection(msg.message_text.qid);
+
+                            if (msg.message_type & NON_SECURE) {
+                                /* This is a non-secure message */
+
+                                /* Check if NS client is allowed for this RoT service */
+                                if (nsacl[i] <= 0) {
+#if 0
+                                    INFO(
+                                        "Rejecting non-secure client due to manifest security policy");
+                                    reply(i, PSA_ERROR_CONNECTION_REFUSED);
+                                    continue; /* Skip to next signal */
+#endif
+                                }
+
+                                msg.message_type &= ~(NON_SECURE); /* clear */
+                                messages[i].client_id = messages[i].client_id * -1;
+                            }
+
+                            INFO("Got a message from client ID %d", messages[i].client_id);
+                            INFO("Message type is %lu", msg.message_type);
+                            INFO("PSA message type is %d", msg.message_text.psa_type);
+
+                            messages[i].handle = i;
+
+                            switch (msg.message_text.psa_type) {
+                                case PSA_IPC_CONNECT:
+
+                                    if (len >= 16) {
+                                        memcpy(&requested_version, msg.message_text.buf,
+                                               sizeof(requested_version));
+                                        INFO("Requesting version %u", requested_version);
+                                        INFO("Implemented version %u", rot_svc_versions[i]);
+                                        /* TODO: need to check whether the policy is strict,
+                                         * and if so, then reject the client if the number doesn't match */
+
+                                        if (requested_version > rot_svc_versions[i]) {
+                                            INFO(
+                                                "Rejecting client because requested version that was too high");
+                                            reply(i, PSA_ERROR_CONNECTION_REFUSED);
+                                            continue; /* Skip to next signal */
+                                        }
+
+                                        if (strict_policy[i] == 1 &&
+                                            (requested_version != rot_svc_versions[i])) {
+                                            INFO(
+                                                "Rejecting client because enforcing a STRICT version policy");
+                                            reply(i, PSA_ERROR_CONNECTION_REFUSED);
+                                            continue; /* Skip to next signal */
+                                        } else {
+                                            INFO("Not rejecting client");
+                                        }
+                                    }
+
+                                    messages[i].type = PSA_IPC_CONNECT;
+
+                                    if (idx < 0) {
+                                        idx = find_free_connection();
+                                    }
+
+                                    if (idx >= 0) {
+                                        connections[idx].client = msg.message_text.qid;
+                                    } else {
+                                        /* We've run out of system wide connections */
+                                        reply(i, PSA_ERROR_CONNECTION_BUSY);
+                                        ERROR("Ran out of free connections");
+                                        continue;
+                                    }
+
+                                    break;
+                                case PSA_IPC_DISCONNECT:
+                                    messages[i].type = PSA_IPC_DISCONNECT;
+                                    break;
+                                case VERSION_REQUEST:
+                                    INFO("Got a version request");
+                                    reply(i, rot_svc_versions[i]);
+                                    continue; /* Skip to next signal */
+                                    break;
+
+                                default:
+
+                                    /* PSA CALL */
+                                    if (msg.message_text.psa_type >= 0) {
+                                        messages[i].type = msg.message_text.psa_type;
+                                        memcpy(&sizes, msg.message_text.buf, sizeof(sizes));
+                                        print_vectors(&sizes);
+                                        memcpy(&messages[i].in_size, &sizes.invec_sizes,
+                                               (sizeof(size_t) * PSA_MAX_IOVEC));
+                                        memcpy(&messages[i].out_size, &sizes.outvec_sizes,
+                                               (sizeof(size_t) * PSA_MAX_IOVEC));
+                                    } else {
+                                        FATAL("UNKNOWN MESSAGE TYPE RECEIVED %li",
+                                              msg.message_type);
+                                    }
+                                    break;
+                            }
+                            messages[i].handle = i;
+
+                            /* Check if the client has a connection */
+                            if (idx >= 0) {
+                                messages[i].rhandle = connections[idx].rhandle;
+                            } else {
+                                /* Client is begging for a programmer error */
+                                reply(i, PSA_ERROR_PROGRAMMER_ERROR);
+                                continue;
+                            }
+
+                            /* House keeping */
+                            pending_message[i] = 1; /* set message as pending */
+                            exposed_signals |= (0x1 << i); /* assert the signal */
+                        }
+                    }
+                }
+                mask = mask >> 1;
+            }
+        }
+
+        if ((timeout == PSA_BLOCK) && (exposed_signals > 0)) {
+            break;
+        } else {
+            /* There is no 'select' function in SysV to block on multiple queues, so busy-wait :( */
+#if defined(PSASIM_USE_USLEEP)
+            usleep(SLEEP_MS * 1000);
+#else /* PSASIM_USE_USLEEP */
+            nanosleep(&ts_delay, NULL);
+#endif /* PSASIM_USE_USLEEP */
+        }
+    } while (timeout == PSA_BLOCK);
+
+    /* Assert signals */
+    return signal_mask & exposed_signals;
+}
+
+static int signal_to_index(psa_signal_t signal)
+{
+    int i;
+    int count = 0;
+    int ret = -1;
+
+    for (i = 0; i < 32; i++) {
+        if (signal & 0x1) {
+            ret = i;
+            count++;
+        }
+        signal = signal >> 1;
+    }
+
+    if (count > 1) {
+        ERROR("ERROR: Too many signals");
+        return -1; /* Too many signals */
+    }
+    return ret;
+}
+
+static void clear_signal(psa_signal_t signal)
+{
+    exposed_signals = exposed_signals & ~signal;
+}
+
+void raise_signal(psa_signal_t signal)
+{
+    exposed_signals |= signal;
+}
+
+psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg)
+{
+    int index = signal_to_index(signal);
+    if (index < 0) {
+        ERROR("Bad signal");
+    }
+
+    clear_signal(signal);
+
+    assert(messages[index].handle != 0);
+
+    if (pending_message[index] == 1) {
+        INFO("There is a pending message!");
+        memcpy(msg, &messages[index], sizeof(struct psa_msg_t));
+        assert(msg->handle != 0);
+        return PSA_SUCCESS;
+    } else {
+        INFO("no pending message");
+    }
+
+    return PSA_ERROR_DOES_NOT_EXIST;
+}
+
+static inline int is_valid_msg_handle(psa_handle_t h)
+{
+    if (h > 0 && h < MAX_MESSAGES) {
+        return 1;
+    }
+    ERROR("Not a valid message handle");
+    return 0;
+}
+
+static inline int is_call_msg(psa_handle_t h)
+{
+    assert(messages[h].type >= PSA_IPC_CALL);
+    return 1;
+}
+
+void psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
+{
+    is_valid_msg_handle(msg_handle);
+    int idx = find_connection(message_client[msg_handle]);
+    INFO("Setting rhandle to %p", rhandle);
+    assert(idx >= 0);
+    connections[idx].rhandle = rhandle;
+}
+
+/* Sends a message from the server to the client. Does not wait for a response */
+static void send_msg(psa_handle_t msg_handle,
+                     int ctrl_msg,
+                     psa_status_t status,
+                     size_t amount,
+                     const void *data,
+                     size_t data_amount)
+{
+    struct message response;
+    int flags = 0;
+
+    assert(ctrl_msg > 0); /* According to System V, it must be greater than 0 */
+
+    response.message_type = ctrl_msg;
+    if (ctrl_msg == PSA_REPLY) {
+        memcpy(response.message_text.buf, &status, sizeof(psa_status_t));
+    } else if (ctrl_msg == READ_REQUEST || ctrl_msg == WRITE_REQUEST || ctrl_msg == SKIP_REQUEST) {
+        memcpy(response.message_text.buf, &status, sizeof(psa_status_t));
+        memcpy(response.message_text.buf+sizeof(size_t), &amount, sizeof(size_t));
+        if (ctrl_msg == WRITE_REQUEST) {
+            /* TODO: Check if too big */
+            memcpy(response.message_text.buf + (sizeof(size_t) * 2), data, data_amount);
+        }
+    }
+
+    /* TODO: sizeof doesn't need to be so big here for small responses */
+    if (msgsnd(message_client[msg_handle], &response, sizeof(response.message_text), flags) == -1) {
+        ERROR("Failed to reply");
+    }
+}
+
+static size_t skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes)
+{
+    if (num_bytes < (messages[msg_handle].in_size[invec_idx] - num_bytes)) {
+        messages[msg_handle].in_size[invec_idx] = messages[msg_handle].in_size[invec_idx] -
+                                                  num_bytes;
+        return num_bytes;
+    } else {
+        if (num_bytes >= messages[msg_handle].in_size[invec_idx]) {
+            size_t ret = messages[msg_handle].in_size[invec_idx];
+            messages[msg_handle].in_size[invec_idx] = 0;
+            return ret;
+        } else {
+            return num_bytes;
+        }
+    }
+}
+
+size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
+                void *buffer, size_t num_bytes)
+{
+    size_t sofar = 0;
+    struct message msg = { 0 };
+    int idx;
+    ssize_t len;
+
+    is_valid_msg_handle(msg_handle);
+    is_call_msg(msg_handle);
+
+    if (invec_idx >= PSA_MAX_IOVEC) {
+        ERROR("Invalid iovec number");
+    }
+
+    /* If user wants more data than what's available, truncate their request */
+    if (num_bytes > messages[msg_handle].in_size[invec_idx]) {
+        num_bytes = messages[msg_handle].in_size[invec_idx];
+    }
+
+    while (sofar < num_bytes) {
+        INFO("Server: requesting %lu bytes from client", (num_bytes - sofar));
+        send_msg(msg_handle, READ_REQUEST, invec_idx, (num_bytes - sofar), NULL, 0);
+
+        idx = find_connection(message_client[msg_handle]);
+        assert(idx >= 0);
+
+        len = msgrcv(connections[idx].client_to_server_q, &msg, sizeof(struct message_text), 0, 0);
+        len = (len - offsetof(struct message_text, buf));
+
+        if (len < 0) {
+            FATAL("Internal error: failed to dispatch read request to the client");
+        }
+
+        if (len > (num_bytes - sofar)) {
+            if ((num_bytes - sofar) > 0) {
+                memcpy(buffer+sofar, msg.message_text.buf, (num_bytes - sofar));
+            }
+        } else {
+            memcpy(buffer + sofar, msg.message_text.buf, len);
+        }
+
+        INFO("Printing what i got so far: %s", msg.message_text.buf);
+
+        sofar = sofar + len;
+    }
+
+    /* Update the seek count */
+    skip(msg_handle, invec_idx, num_bytes);
+    INFO("Finished psa_read");
+    return sofar;
+}
+
+void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
+               const void *buffer, size_t num_bytes)
+{
+    size_t sofar = 0;
+    struct message msg = { 0 };
+    int idx;
+    ssize_t len;
+
+    is_valid_msg_handle(msg_handle);
+    is_call_msg(msg_handle);
+
+    if (outvec_idx >= PSA_MAX_IOVEC) {
+        ERROR("Invalid iovec number");
+    }
+
+    if (num_bytes > messages[msg_handle].out_size[outvec_idx]) {
+        ERROR("Program tried to write too much data %lu/%lu", num_bytes,
+              messages[msg_handle].out_size[outvec_idx]);
+    }
+
+    while (sofar < num_bytes) {
+        size_t sending = (num_bytes - sofar);
+        if (sending >= MAX_FRAGMENT_SIZE) {
+            sending = MAX_FRAGMENT_SIZE - (sizeof(size_t) * 2);
+        }
+
+        INFO("Server: sending %lu bytes to client, sofar = %lu", sending, (long) sofar);
+
+        send_msg(msg_handle, WRITE_REQUEST, outvec_idx, sending, buffer + sofar, sending);
+
+        idx = find_connection(message_client[msg_handle]);
+        assert(idx >= 0);
+
+        len = msgrcv(connections[idx].client_to_server_q, &msg, sizeof(struct message_text), 0, 0);
+        if (len < 1) {
+            FATAL("Client didn't give me a full response");
+        }
+        sofar = sofar + sending;
+    }
+
+    /* Update the seek count */
+    messages[msg_handle].out_size[outvec_idx] -= num_bytes;
+}
+
+size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes)
+{
+    is_valid_msg_handle(msg_handle);
+    is_call_msg(msg_handle);
+
+    size_t ret = skip(msg_handle, invec_idx, num_bytes);
+
+    /* notify client to skip */
+    send_msg(msg_handle, SKIP_REQUEST, invec_idx, num_bytes, NULL, 0);
+    return ret;
+}
+
+static void destroy_temporary_queue(int myqid)
+{
+    if (msgctl(myqid, IPC_RMID, NULL) != 0) {
+        INFO("ERROR: Failed to delete msg queue %d", myqid);
+    }
+}
+
+static int make_temporary_queue()
+{
+    int myqid;
+    if ((myqid = msgget(IPC_PRIVATE, 0660)) == -1) {
+        INFO("msgget: myqid");
+        return -1;
+    }
+    return myqid;
+}
+
+/**
+ * Assumes msg_handle is the index into the message array
+ */
+void psa_reply(psa_handle_t msg_handle, psa_status_t status)
+{
+    int idx, q;
+    is_valid_msg_handle(msg_handle);
+
+    if (pending_message[msg_handle] != 1) {
+        ERROR("Not a valid message handle");
+    }
+
+    if (messages[msg_handle].type == PSA_IPC_CONNECT) {
+        switch (status) {
+            case PSA_SUCCESS:
+                idx = find_connection(message_client[msg_handle]);
+                q = make_temporary_queue();
+                if (q > 0 && idx >= 0) {
+                    connections[idx].client_to_server_q = q;
+                    status = q;
+                } else {
+                    FATAL("What happened?");
+                }
+                break;
+            case PSA_ERROR_CONNECTION_REFUSED:
+                destroy_connection(message_client[msg_handle]);
+                break;
+            case PSA_ERROR_CONNECTION_BUSY:
+                destroy_connection(message_client[msg_handle]);
+                break;
+            case PSA_ERROR_PROGRAMMER_ERROR:
+                destroy_connection(message_client[msg_handle]);
+                break;
+            default:
+                ERROR("Not a valid reply %d", status);
+        }
+    } else if (messages[msg_handle].type == PSA_IPC_DISCONNECT) {
+        idx = find_connection(message_client[msg_handle]);
+        if (idx >= 0) {
+            destroy_temporary_queue(connections[idx].client_to_server_q);
+        }
+        destroy_connection(message_client[msg_handle]);
+    }
+
+    send_msg(msg_handle, PSA_REPLY, status, 0, NULL, 0);
+
+    pending_message[msg_handle] = 0;
+    message_client[msg_handle] = 0;
+}
+
+/* TODO: make sure you only clear interrupt signals, and not others */
+void psa_eoi(psa_signal_t signal)
+{
+    int index = signal_to_index(signal);
+    if (index >= 0 && (rot_svc_incoming_queue[index] >= 0)) {
+        clear_signal(signal);
+    } else {
+        ERROR("Tried to EOI a signal that isn't an interrupt");
+    }
+}
+
+void psa_notify(int32_t partition_id)
+{
+    char pathname[PATHNAMESIZE] = { 0 };
+
+    if (partition_id < 0) {
+        ERROR("Not a valid secure partition");
+    }
+
+    snprintf(pathname, PATHNAMESIZE, "/tmp/psa_notify_%u", partition_id);
+    INFO("psa_notify: notifying partition %u using %s",
+         partition_id, pathname);
+    INFO("psa_notify is unimplemented");
+}
+
+void psa_clear(void)
+{
+    clear_signal(PSA_DOORBELL);
+}
+
+void __init_psasim(const char **array,
+                   int size,
+                   const int allow_ns_clients_array[32],
+                   const uint32_t versions[32],
+                   const int strict_policy_array[32])
+{
+    static uint8_t library_initialised = 0;
+    key_t key;
+    int qid;
+    FILE *fp;
+    char doorbell_path[PATHNAMESIZE] = { 0 };
+    char queue_path[PATHNAMESIZE];
+    snprintf(doorbell_path, PATHNAMESIZE, TMP_FILE_BASE_PATH "psa_notify_%u", getpid());
+
+    if (library_initialised > 0) {
+        return;
+    } else {
+        library_initialised = 1;
+    }
+
+    if (size != 32) {
+        FATAL("Unsupported value. Aborting.");
+    }
+
+    array[3] = doorbell_path;
+
+    for (int i = 0; i < 32; i++) {
+        if (strncmp(array[i], "", 1) != 0) {
+            INFO("Setting up %s", array[i]);
+            memset(queue_path, 0, sizeof(queue_path));
+            snprintf(queue_path, sizeof(queue_path), "%s%s", TMP_FILE_BASE_PATH, array[i]);
+
+            /* Create file if doesn't exist */
+            fp = fopen(queue_path, "ab+");
+            if (fp) {
+                fclose(fp);
+            }
+
+            if ((key = ftok(queue_path, PROJECT_ID)) == -1) {
+                FATAL("Error finding message queue during initialisation");
+            }
+
+            /* TODO: Investigate. Permissions are likely to be too relaxed */
+            if ((qid = msgget(key, IPC_CREAT | 0660)) == -1) {
+                FATAL("Error opening message queue during initialisation");
+            } else {
+                rot_svc_incoming_queue[i] = qid;
+            }
+        }
+    }
+
+    memcpy(nsacl, allow_ns_clients_array, sizeof(int) * 32);
+    memcpy(strict_policy, strict_policy_array, sizeof(int) * 32);
+    memcpy(rot_svc_versions, versions, sizeof(uint32_t) * 32);
+    memset(&connections, 0, sizeof(struct connection) * MAX_CLIENTS);
+
+    __psa_ff_client_security_state = 0; /* Set the client status to SECURE */
+}
diff --git a/tests/psa-client-server/psasim/src/psa_functions_codes.h b/tests/psa-client-server/psasim/src/psa_functions_codes.h
new file mode 100644
index 0000000..0093733
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/psa_functions_codes.h
@@ -0,0 +1,25 @@
+/* THIS FILE WAS AUTO-GENERATED BY psa_sim_generate.pl. DO NOT EDIT!! */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef _PSA_FUNCTIONS_CODES_H_
+#define  _PSA_FUNCTIONS_CODES_H_
+
+enum {
+    /* Start here to avoid overlap with PSA_IPC_CONNECT, PSA_IPC_DISCONNECT
+     * and VERSION_REQUEST */
+    PSA_CRYPTO_INIT = 100,
+    PSA_HASH_ABORT,
+    PSA_HASH_CLONE,
+    PSA_HASH_COMPARE,
+    PSA_HASH_COMPUTE,
+    PSA_HASH_FINISH,
+    PSA_HASH_SETUP,
+    PSA_HASH_UPDATE,
+    PSA_HASH_VERIFY,
+};
+
+#endif /*  _PSA_FUNCTIONS_CODES_H_ */
diff --git a/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c b/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c
new file mode 100644
index 0000000..4ac6c4a
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/psa_sim_crypto_client.c
@@ -0,0 +1,701 @@
+/* THIS FILE WAS AUTO-GENERATED BY psa_sim_generate.pl. DO NOT EDIT!! */
+
+/* client calls */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+/* Includes from psasim */
+#include <client.h>
+#include <util.h>
+#include "psa_manifest/sid.h"
+#include "psa_functions_codes.h"
+#include "psa_sim_serialise.h"
+
+/* Includes from mbedtls */
+#include "mbedtls/version.h"
+#include "psa/crypto.h"
+
+#define CLIENT_PRINT(fmt, ...) \
+    PRINT("Client: " fmt, ##__VA_ARGS__)
+
+static psa_handle_t handle = -1;
+
+int psa_crypto_call(int function,
+                    uint8_t *in_params, size_t in_params_len,
+                    uint8_t **out_params, size_t *out_params_len)
+{
+    // psa_outvec outvecs[1];
+    if (handle < 0) {
+        fprintf(stderr, "NOT CONNECTED\n");
+        exit(1);
+    }
+
+    psa_invec invec;
+    invec.base = in_params;
+    invec.len = in_params_len;
+
+    size_t max_receive = 8192;
+    uint8_t *receive = malloc(max_receive);
+    if (receive == NULL) {
+        fprintf(stderr, "FAILED to allocate %u bytes\n", (unsigned) max_receive);
+        exit(1);
+    }
+
+    size_t actual_received = 0;
+
+    psa_outvec outvecs[2];
+    outvecs[0].base = &actual_received;
+    outvecs[0].len = sizeof(actual_received);
+    outvecs[1].base = receive;
+    outvecs[1].len = max_receive;
+
+    psa_status_t status = psa_call(handle, function, &invec, 1, outvecs, 2);
+    if (status != PSA_SUCCESS) {
+        free(receive);
+        return 0;
+    }
+
+    *out_params = receive;
+    *out_params_len = actual_received;
+
+    return 1;   // success
+}
+
+psa_status_t psa_crypto_init(void)
+{
+    char mbedtls_version[18];
+    uint8_t *result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    mbedtls_version_get_string_full(mbedtls_version);
+    CLIENT_PRINT("%s", mbedtls_version);
+
+    CLIENT_PRINT("My PID: %d", getpid());
+
+    CLIENT_PRINT("PSA version: %u", psa_version(PSA_SID_CRYPTO_SID));
+    handle = psa_connect(PSA_SID_CRYPTO_SID, 1);
+
+    if (handle < 0) {
+        CLIENT_PRINT("Couldn't connect %d", handle);
+        return PSA_ERROR_COMMUNICATION_FAILURE;
+    }
+
+    int ok = psa_crypto_call(PSA_CRYPTO_INIT, NULL, 0, &result, &result_length);
+    CLIENT_PRINT("PSA_CRYPTO_INIT returned: %d", ok);
+
+    if (!ok) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(result);
+
+    return status;
+}
+
+void mbedtls_psa_crypto_free(void)
+{
+    CLIENT_PRINT("Closing handle");
+    psa_close(handle);
+    handle = -1;
+}
+
+
+psa_status_t psa_hash_abort(
+    psa_hash_operation_t *operation
+    )
+{
+    uint8_t *params = NULL;
+    uint8_t *result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed = psasim_serialise_begin_needs() +
+                    psasim_serialise_psa_hash_operation_t_needs(*operation);
+
+    params = malloc(needed);
+    if (params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_HASH_ABORT,
+                         params, (size_t) (pos - params), &result, &result_length);
+    if (!ok) {
+        printf("XXX server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(params);
+    free(result);
+
+    return status;
+}
+
+
+psa_status_t psa_hash_clone(
+    const psa_hash_operation_t *source_operation,
+    psa_hash_operation_t *target_operation
+    )
+{
+    uint8_t *params = NULL;
+    uint8_t *result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed = psasim_serialise_begin_needs() +
+                    psasim_serialise_psa_hash_operation_t_needs(*source_operation) +
+                    psasim_serialise_psa_hash_operation_t_needs(*target_operation);
+
+    params = malloc(needed);
+    if (params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *source_operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *target_operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_HASH_CLONE,
+                         params, (size_t) (pos - params), &result, &result_length);
+    if (!ok) {
+        printf("XXX server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, target_operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(params);
+    free(result);
+
+    return status;
+}
+
+
+psa_status_t psa_hash_compare(
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t  input_length,
+    const uint8_t *hash, size_t  hash_length
+    )
+{
+    uint8_t *params = NULL;
+    uint8_t *result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed = psasim_serialise_begin_needs() +
+                    psasim_serialise_psa_algorithm_t_needs(alg) +
+                    psasim_serialise_buffer_needs(input, input_length) +
+                    psasim_serialise_buffer_needs(hash, hash_length);
+
+    params = malloc(needed);
+    if (params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(&pos, &remaining, input, input_length);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_HASH_COMPARE,
+                         params, (size_t) (pos - params), &result, &result_length);
+    if (!ok) {
+        printf("XXX server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(params);
+    free(result);
+
+    return status;
+}
+
+
+psa_status_t psa_hash_compute(
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t  input_length,
+    uint8_t *hash, size_t  hash_size,
+    size_t *hash_length
+    )
+{
+    uint8_t *params = NULL;
+    uint8_t *result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed = psasim_serialise_begin_needs() +
+                    psasim_serialise_psa_algorithm_t_needs(alg) +
+                    psasim_serialise_buffer_needs(input, input_length) +
+                    psasim_serialise_buffer_needs(hash, hash_size) +
+                    psasim_serialise_size_t_needs(*hash_length);
+
+    params = malloc(needed);
+    if (params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(&pos, &remaining, input, input_length);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_size);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_size_t(&pos, &remaining, *hash_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_HASH_COMPUTE,
+                         params, (size_t) (pos - params), &result, &result_length);
+    if (!ok) {
+        printf("XXX server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_return_buffer(&rpos, &rremain, hash, hash_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(&rpos, &rremain, hash_length);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(params);
+    free(result);
+
+    return status;
+}
+
+
+psa_status_t psa_hash_finish(
+    psa_hash_operation_t *operation,
+    uint8_t *hash, size_t  hash_size,
+    size_t *hash_length
+    )
+{
+    uint8_t *params = NULL;
+    uint8_t *result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed = psasim_serialise_begin_needs() +
+                    psasim_serialise_psa_hash_operation_t_needs(*operation) +
+                    psasim_serialise_buffer_needs(hash, hash_size) +
+                    psasim_serialise_size_t_needs(*hash_length);
+
+    params = malloc(needed);
+    if (params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_size);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_size_t(&pos, &remaining, *hash_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_HASH_FINISH,
+                         params, (size_t) (pos - params), &result, &result_length);
+    if (!ok) {
+        printf("XXX server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_return_buffer(&rpos, &rremain, hash, hash_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(&rpos, &rremain, hash_length);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(params);
+    free(result);
+
+    return status;
+}
+
+
+psa_status_t psa_hash_setup(
+    psa_hash_operation_t *operation,
+    psa_algorithm_t alg
+    )
+{
+    uint8_t *params = NULL;
+    uint8_t *result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed = psasim_serialise_begin_needs() +
+                    psasim_serialise_psa_hash_operation_t_needs(*operation) +
+                    psasim_serialise_psa_algorithm_t_needs(alg);
+
+    params = malloc(needed);
+    if (params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_algorithm_t(&pos, &remaining, alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_HASH_SETUP,
+                         params, (size_t) (pos - params), &result, &result_length);
+    if (!ok) {
+        printf("XXX server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(params);
+    free(result);
+
+    return status;
+}
+
+
+psa_status_t psa_hash_update(
+    psa_hash_operation_t *operation,
+    const uint8_t *input, size_t  input_length
+    )
+{
+    uint8_t *params = NULL;
+    uint8_t *result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed = psasim_serialise_begin_needs() +
+                    psasim_serialise_psa_hash_operation_t_needs(*operation) +
+                    psasim_serialise_buffer_needs(input, input_length);
+
+    params = malloc(needed);
+    if (params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(&pos, &remaining, input, input_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_HASH_UPDATE,
+                         params, (size_t) (pos - params), &result, &result_length);
+    if (!ok) {
+        printf("XXX server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(params);
+    free(result);
+
+    return status;
+}
+
+
+psa_status_t psa_hash_verify(
+    psa_hash_operation_t *operation,
+    const uint8_t *hash, size_t  hash_length
+    )
+{
+    uint8_t *params = NULL;
+    uint8_t *result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t needed = psasim_serialise_begin_needs() +
+                    psasim_serialise_psa_hash_operation_t_needs(*operation) +
+                    psasim_serialise_buffer_needs(hash, hash_length);
+
+    params = malloc(needed);
+    if (params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_psa_hash_operation_t(&pos, &remaining, *operation);
+    if (!ok) {
+        goto fail;
+    }
+    ok = psasim_serialise_buffer(&pos, &remaining, hash, hash_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psa_crypto_call(PSA_HASH_VERIFY,
+                         params, (size_t) (pos - params), &result, &result_length);
+    if (!ok) {
+        printf("XXX server call failed\n");
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(params);
+    free(result);
+
+    return status;
+}
diff --git a/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c b/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c
new file mode 100644
index 0000000..919eb84
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/psa_sim_crypto_server.c
@@ -0,0 +1,834 @@
+/* THIS FILE WAS AUTO-GENERATED BY psa_sim_generate.pl. DO NOT EDIT!! */
+
+/* server implementations */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <psa/crypto.h>
+
+#include "psa_functions_codes.h"
+#include "psa_sim_serialise.h"
+
+#include "service.h"
+
+// Returns 1 for success, 0 for failure
+int psa_crypto_init_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    uint8_t *result = NULL;
+    int ok;
+
+    // Now we call the actual target function
+
+    status = psa_crypto_init(
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_hash_abort_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_hash_operation_t operation;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_hash_abort(
+        &operation
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status) +
+        psasim_serialise_psa_hash_operation_t_needs(operation);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_hash_clone_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_hash_operation_t source_operation;
+    psa_hash_operation_t target_operation;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &source_operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &target_operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_hash_clone(
+        &source_operation,
+        &target_operation
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status) +
+        psasim_serialise_psa_hash_operation_t_needs(target_operation);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, target_operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_hash_compare_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_algorithm_t alg;
+    uint8_t *input = NULL;
+    size_t input_length;
+    uint8_t *hash = NULL;
+    size_t hash_length;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(&pos, &remaining, &hash, &hash_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_hash_compare(
+        alg,
+        input, input_length,
+        hash, hash_length
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(input);
+    free(hash);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(input);
+    free(hash);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_hash_compute_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_algorithm_t alg;
+    uint8_t *input = NULL;
+    size_t input_length;
+    uint8_t *hash = NULL;
+    size_t hash_size;
+    size_t hash_length;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(&pos, &remaining, &hash, &hash_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(&pos, &remaining, &hash_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_hash_compute(
+        alg,
+        input, input_length,
+        hash, hash_size,
+        &hash_length
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status) +
+        psasim_serialise_buffer_needs(hash, hash_size) +
+        psasim_serialise_size_t_needs(hash_length);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_buffer(&rpos, &rremain, hash, hash_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_size_t(&rpos, &rremain, hash_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(input);
+    free(hash);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(input);
+    free(hash);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_hash_finish_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_hash_operation_t operation;
+    uint8_t *hash = NULL;
+    size_t hash_size;
+    size_t hash_length;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(&pos, &remaining, &hash, &hash_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_size_t(&pos, &remaining, &hash_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_hash_finish(
+        &operation,
+        hash, hash_size,
+        &hash_length
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status) +
+        psasim_serialise_psa_hash_operation_t_needs(operation) +
+        psasim_serialise_buffer_needs(hash, hash_size) +
+        psasim_serialise_size_t_needs(hash_length);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_buffer(&rpos, &rremain, hash, hash_size);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_size_t(&rpos, &rremain, hash_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(hash);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(hash);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_hash_setup_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_hash_operation_t operation;
+    psa_algorithm_t alg;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_algorithm_t(&pos, &remaining, &alg);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_hash_setup(
+        &operation,
+        alg
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status) +
+        psasim_serialise_psa_hash_operation_t_needs(operation);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_hash_update_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_hash_operation_t operation;
+    uint8_t *input = NULL;
+    size_t input_length;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(&pos, &remaining, &input, &input_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_hash_update(
+        &operation,
+        input, input_length
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status) +
+        psasim_serialise_psa_hash_operation_t_needs(operation);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(input);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(input);
+
+    return 0;       // This shouldn't happen!
+}
+
+// Returns 1 for success, 0 for failure
+int psa_hash_verify_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_hash_operation_t operation;
+    uint8_t *hash = NULL;
+    size_t hash_length;
+
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+    uint8_t *result = NULL;
+    int ok;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_hash_operation_t(&pos, &remaining, &operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_buffer(&pos, &remaining, &hash, &hash_length);
+    if (!ok) {
+        goto fail;
+    }
+
+    // Now we call the actual target function
+
+    status = psa_hash_verify(
+        &operation,
+        hash, hash_length
+        );
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs() +
+        psasim_serialise_psa_status_t_needs(status) +
+        psasim_serialise_psa_hash_operation_t_needs(operation);
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_status_t(&rpos, &rremain, status);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_serialise_psa_hash_operation_t(&rpos, &rremain, operation);
+    if (!ok) {
+        goto fail;
+    }
+
+    *out_params = result;
+    *out_params_len = result_size;
+
+    free(hash);
+
+    return 1;   // success
+
+fail:
+    free(result);
+
+    free(hash);
+
+    return 0;       // This shouldn't happen!
+}
+
+psa_status_t psa_crypto_call(psa_msg_t msg)
+{
+    int ok = 0;
+
+    int func = msg.type;
+
+    /* We only expect a single input buffer, with everything serialised in it */
+    if (msg.in_size[1] != 0 || msg.in_size[2] != 0 || msg.in_size[3] != 0) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* We expect exactly 2 output buffers, one for size, the other for data */
+    if (msg.out_size[0] != sizeof(size_t) || msg.out_size[1] == 0 ||
+        msg.out_size[2] != 0 || msg.out_size[3] != 0) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    uint8_t *in_params = NULL;
+    size_t in_params_len = 0;
+    uint8_t *out_params = NULL;
+    size_t out_params_len = 0;
+
+    in_params_len = msg.in_size[0];
+    in_params = malloc(in_params_len);
+    if (in_params == NULL) {
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+
+    /* Read the bytes from the client */
+    size_t actual = psa_read(msg.handle, 0, in_params, in_params_len);
+    if (actual != in_params_len) {
+        free(in_params);
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
+    switch (func) {
+        case PSA_CRYPTO_INIT:
+            ok = psa_crypto_init_wrapper(in_params, in_params_len,
+                                         &out_params, &out_params_len);
+            break;
+        case PSA_HASH_ABORT:
+            ok = psa_hash_abort_wrapper(in_params, in_params_len,
+                                        &out_params, &out_params_len);
+            break;
+        case PSA_HASH_CLONE:
+            ok = psa_hash_clone_wrapper(in_params, in_params_len,
+                                        &out_params, &out_params_len);
+            break;
+        case PSA_HASH_COMPARE:
+            ok = psa_hash_compare_wrapper(in_params, in_params_len,
+                                          &out_params, &out_params_len);
+            break;
+        case PSA_HASH_COMPUTE:
+            ok = psa_hash_compute_wrapper(in_params, in_params_len,
+                                          &out_params, &out_params_len);
+            break;
+        case PSA_HASH_FINISH:
+            ok = psa_hash_finish_wrapper(in_params, in_params_len,
+                                         &out_params, &out_params_len);
+            break;
+        case PSA_HASH_SETUP:
+            ok = psa_hash_setup_wrapper(in_params, in_params_len,
+                                        &out_params, &out_params_len);
+            break;
+        case PSA_HASH_UPDATE:
+            ok = psa_hash_update_wrapper(in_params, in_params_len,
+                                         &out_params, &out_params_len);
+            break;
+        case PSA_HASH_VERIFY:
+            ok = psa_hash_verify_wrapper(in_params, in_params_len,
+                                         &out_params, &out_params_len);
+            break;
+    }
+
+    free(in_params);
+
+    if (out_params_len > msg.out_size[1]) {
+        fprintf(stderr, "unable to write %zu bytes into buffer of %zu bytes\n",
+                out_params_len, msg.out_size[1]);
+        exit(1);
+    }
+
+    /* Write the exact amount of data we're returning */
+    psa_write(msg.handle, 0, &out_params_len, sizeof(out_params_len));
+
+    /* And write the data itself */
+    if (out_params_len) {
+        psa_write(msg.handle, 1, out_params, out_params_len);
+    }
+
+    free(out_params);
+
+    return ok ? PSA_SUCCESS : PSA_ERROR_GENERIC_ERROR;
+}
diff --git a/tests/psa-client-server/psasim/src/psa_sim_generate.pl b/tests/psa-client-server/psasim/src/psa_sim_generate.pl
new file mode 100755
index 0000000..19c6a0b
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/psa_sim_generate.pl
@@ -0,0 +1,1411 @@
+#!/usr/bin/env perl
+#
+# This is a proof-of-concept script to show that the client and server wrappers
+# can be created by a script. It is not hooked into the build, so is run
+# manually and the output files are what are to be reviewed. In due course
+# this will be replaced by a Python script.
+#
+# Copyright The Mbed TLS Contributors
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+#
+use strict;
+use Data::Dumper;
+use JSON qw(encode_json);
+
+my $debug = 0;
+
+# Globals (sorry!)
+my %functions = get_functions();
+my @functions = sort keys %functions;
+
+# get_functions(), called above, returns a data structure for each function
+# that we need to create client and server stubs for. In this example Perl script,
+# the function declarations we want are in the data section (after __END__ at
+# the bottom of this file), but a production Python version should process
+# psa_crypto.h.
+#
+# In this script, the data for psa_crypto_init() looks like:
+#
+#   "psa_crypto_init": {
+#     "return": {               # Info on return type
+#       "type": "psa_status_t", # Return type
+#       "name": "status",       # Name to be used for this in C code
+#       "default": "PSA_ERROR_CORRUPTION_DETECTED"      # Default value
+#     },
+#     "args": [],               # void function, so args empty
+#   }
+#
+# The data for psa_hash_compute() looks like:
+#
+#  "psa_hash_compute": {
+#    "return": {                # Information on return type
+#      "type": "psa_status_t",
+#      "name": "status",
+#      "default": "PSA_ERROR_CORRUPTION_DETECTED"
+#    },
+#    "args": [{
+#        "type": "psa_algorithm_t",             # Type of first argument
+#        "ctypename": "psa_algorithm_t ",       # C type with trailing spaces
+#                                               # (so that e.g. `char *` looks ok)
+#        "name": "alg",
+#        "is_output": 0
+#      }, {
+#        "type": "const buffer",                # Specially created
+#        "ctypename": "",                       # (so no C type)
+#        "name": "input, input_length",         # A pair of arguments
+#        "is_output": 0                         # const, so not an output argument
+#      }, {
+#        "type": "buffer",                      # Specially created
+#        "ctypename": "",
+#        "name": "hash, hash_size",
+#        "is_output": 1                         # Not const, so output argument
+#      }, {
+#        "type": "size_t",                      # size_t *hash_length
+#        "ctypename": "size_t ",
+#        "name": "*hash_length",                # * comes into the name
+#        "is_output": 1
+#      }
+#    ],
+#  },
+#
+# It's possible that a production version might not need both type and ctypename;
+# that was done for convenience and future-proofing during development.
+
+# We'll do psa_crypto_init() first
+put_crypto_init_first(\@functions);
+
+write_function_codes("psa_functions_codes.h");
+
+write_client_calls("psa_sim_crypto_client.c");
+
+write_server_implementations("psa_sim_crypto_server.c");
+
+sub write_function_codes
+{
+    my ($file) = @_;
+
+    open(my $fh, ">", $file) || die("$0: $file: $!\n");
+
+    # NOTE: psa_crypto_init() is written manually
+
+    print $fh <<EOF;
+/* THIS FILE WAS AUTO-GENERATED BY psa_sim_generate.pl. DO NOT EDIT!! */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef _PSA_FUNCTIONS_CODES_H_
+#define  _PSA_FUNCTIONS_CODES_H_
+
+enum {
+    /* Start here to avoid overlap with PSA_IPC_CONNECT, PSA_IPC_DISCONNECT
+     * and VERSION_REQUEST */
+    PSA_CRYPTO_INIT = 100,
+EOF
+
+    for my $function (@functions) {
+        my $enum = uc($function);
+        if ($enum ne "PSA_CRYPTO_INIT") {
+            print $fh <<EOF;
+    $enum,
+EOF
+        }
+    }
+
+    print $fh <<EOF;
+};
+
+#endif /*  _PSA_FUNCTIONS_CODES_H_ */
+EOF
+
+    close($fh);
+}
+
+sub write_client_calls
+{
+    my ($file) = @_;
+
+    open(my $fh, ">", $file) || die("$0: $file: $!\n");
+
+    print $fh client_calls_header();
+
+    for my $function (@functions) {
+        # psa_crypto_init() is hand written to establish connection to server
+        if ($function ne "psa_crypto_init") {
+            my $f = $functions{$function};
+            output_client($fh, $f, $function);
+        }
+    }
+
+    close($fh);
+}
+
+sub write_server_implementations
+{
+    my ($file) = @_;
+
+    open(my $fh, ">", $file) || die("$0: $file: $!\n");
+
+    print $fh server_implementations_header();
+
+    print $fh debug_functions() if $debug;
+
+    for my $function (@functions) {
+        my $f = $functions{$function};
+        output_server_wrapper($fh, $f, $function);
+    }
+
+    # Now output a switch statement that calls each of the wrappers
+
+    print $fh <<EOF;
+
+psa_status_t psa_crypto_call(psa_msg_t msg)
+{
+    int ok = 0;
+
+    int func = msg.type;
+
+    /* We only expect a single input buffer, with everything serialised in it */
+    if (msg.in_size[1] != 0 || msg.in_size[2] != 0 || msg.in_size[3] != 0) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* We expect exactly 2 output buffers, one for size, the other for data */
+    if (msg.out_size[0] != sizeof(size_t) || msg.out_size[1] == 0 ||
+        msg.out_size[2] != 0 || msg.out_size[3] != 0) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    uint8_t *in_params = NULL;
+    size_t in_params_len = 0;
+    uint8_t *out_params = NULL;
+    size_t out_params_len = 0;
+
+    in_params_len = msg.in_size[0];
+    in_params = malloc(in_params_len);
+    if (in_params == NULL) {
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+
+    /* Read the bytes from the client */
+    size_t actual = psa_read(msg.handle, 0, in_params, in_params_len);
+    if (actual != in_params_len) {
+        free(in_params);
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
+    switch (func) {
+EOF
+
+    for my $function (@functions) {
+        my $f = $functions{$function};
+        my $enum = uc($function);
+
+        # Create this call, in a way acceptable to uncustify:
+        #            ok = ${function}_wrapper(in_params, in_params_len,
+        #                                     &out_params, &out_params_len);
+        my $first_line = "            ok = ${function}_wrapper(in_params, in_params_len,";
+        my $idx = index($first_line, "(");
+        die("can't find (") if $idx < 0;
+        my $indent = " " x ($idx + 1);
+
+        print $fh <<EOF;
+        case $enum:
+$first_line
+$indent&out_params, &out_params_len);
+            break;
+EOF
+    }
+
+    print $fh <<EOF;
+    }
+
+    free(in_params);
+
+    if (out_params_len > msg.out_size[1]) {
+        fprintf(stderr, "unable to write %zu bytes into buffer of %zu bytes\\n",
+                out_params_len, msg.out_size[1]);
+        exit(1);
+    }
+
+    /* Write the exact amount of data we're returning */
+    psa_write(msg.handle, 0, &out_params_len, sizeof(out_params_len));
+
+    /* And write the data itself */
+    if (out_params_len) {
+        psa_write(msg.handle, 1, out_params, out_params_len);
+    }
+
+    free(out_params);
+
+    return ok ? PSA_SUCCESS : PSA_ERROR_GENERIC_ERROR;
+}
+EOF
+
+    close($fh);
+}
+
+sub server_implementations_header
+{
+    return <<'EOF';
+/* THIS FILE WAS AUTO-GENERATED BY psa_sim_generate.pl. DO NOT EDIT!! */
+
+/* server implementations */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <psa/crypto.h>
+
+#include "psa_functions_codes.h"
+#include "psa_sim_serialise.h"
+
+#include "service.h"
+EOF
+}
+
+sub client_calls_header
+{
+    my $code = <<'EOF';
+/* THIS FILE WAS AUTO-GENERATED BY psa_sim_generate.pl. DO NOT EDIT!! */
+
+/* client calls */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+/* Includes from psasim */
+#include <client.h>
+#include <util.h>
+#include "psa_manifest/sid.h"
+#include "psa_functions_codes.h"
+#include "psa_sim_serialise.h"
+
+/* Includes from mbedtls */
+#include "mbedtls/version.h"
+#include "psa/crypto.h"
+
+#define CLIENT_PRINT(fmt, ...) \
+    PRINT("Client: " fmt, ##__VA_ARGS__)
+
+static psa_handle_t handle = -1;
+EOF
+
+    $code .= debug_functions() if $debug;
+
+    $code .= <<'EOF';
+
+int psa_crypto_call(int function,
+                    uint8_t *in_params, size_t in_params_len,
+                    uint8_t **out_params, size_t *out_params_len)
+{
+    // psa_outvec outvecs[1];
+    if (handle < 0) {
+        fprintf(stderr, "NOT CONNECTED\n");
+        exit(1);
+    }
+
+    psa_invec invec;
+    invec.base = in_params;
+    invec.len = in_params_len;
+
+    size_t max_receive = 8192;
+    uint8_t *receive = malloc(max_receive);
+    if (receive == NULL) {
+        fprintf(stderr, "FAILED to allocate %u bytes\n", (unsigned) max_receive);
+        exit(1);
+    }
+
+    size_t actual_received = 0;
+
+    psa_outvec outvecs[2];
+    outvecs[0].base = &actual_received;
+    outvecs[0].len = sizeof(actual_received);
+    outvecs[1].base = receive;
+    outvecs[1].len = max_receive;
+
+    psa_status_t status = psa_call(handle, function, &invec, 1, outvecs, 2);
+    if (status != PSA_SUCCESS) {
+        free(receive);
+        return 0;
+    }
+
+    *out_params = receive;
+    *out_params_len = actual_received;
+
+    return 1;   // success
+}
+
+psa_status_t psa_crypto_init(void)
+{
+    char mbedtls_version[18];
+    uint8_t *result = NULL;
+    size_t result_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    mbedtls_version_get_string_full(mbedtls_version);
+    CLIENT_PRINT("%s", mbedtls_version);
+
+    CLIENT_PRINT("My PID: %d", getpid());
+
+    CLIENT_PRINT("PSA version: %u", psa_version(PSA_SID_CRYPTO_SID));
+    handle = psa_connect(PSA_SID_CRYPTO_SID, 1);
+
+    if (handle < 0) {
+        CLIENT_PRINT("Couldn't connect %d", handle);
+        return PSA_ERROR_COMMUNICATION_FAILURE;
+    }
+
+    int ok = psa_crypto_call(PSA_CRYPTO_INIT, NULL, 0, &result, &result_length);
+    CLIENT_PRINT("PSA_CRYPTO_INIT returned: %d", ok);
+
+    if (!ok) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+
+    ok = psasim_deserialise_psa_status_t(&rpos, &rremain, &status);
+    if (!ok) {
+        goto fail;
+    }
+
+fail:
+    free(result);
+
+    return status;
+}
+
+void mbedtls_psa_crypto_free(void)
+{
+    CLIENT_PRINT("Closing handle");
+    psa_close(handle);
+    handle = -1;
+}
+EOF
+}
+
+sub debug_functions
+{
+    return <<EOF;
+
+static inline char hex_digit(char nibble) {
+    return (nibble < 10) ? (nibble + '0') : (nibble + 'a' - 10);
+}
+
+int hex_byte(char *p, uint8_t b)
+{
+    p[0] = hex_digit(b >> 4);
+    p[1] = hex_digit(b & 0x0F);
+
+    return 2;
+}
+
+int hex_uint16(char *p, uint16_t b)
+{
+    hex_byte(p, b >> 8);
+    hex_byte(p + 2, b & 0xFF);
+
+    return 4;
+}
+
+char human_char(uint8_t c)
+{
+    return (c >= ' ' && c <= '~') ? (char)c : '.';
+}
+
+void dump_buffer(const uint8_t *buffer, size_t len)
+{
+    char line[80];
+
+    const uint8_t *p = buffer;
+
+    size_t max = (len > 0xFFFF) ? 0xFFFF : len;
+
+    for (size_t i = 0; i < max; i += 16) {
+
+        char *q = line;
+
+        q += hex_uint16(q, (uint16_t)i);
+        *q++ = ' ';
+        *q++ = ' ';
+
+        size_t ll = (i + 16 > max) ? (max % 16) : 16;
+
+        size_t j;
+        for (j = 0; j < ll; j++) {
+            q += hex_byte(q, p[i + j]);
+            *q++ = ' ';
+        }
+
+        while (j++ < 16) {
+            *q++ = ' ';
+            *q++ = ' ';
+            *q++ = ' ';
+        }
+
+        *q++ = ' ';
+
+        for (j = 0; j < ll; j++) {
+            *q++ = human_char(p[i + j]);
+        }
+
+        *q = '\\0';
+
+        printf("%s\\n", line);
+    }
+}
+
+void hex_dump(uint8_t *p, size_t n)
+{
+    for (size_t i = 0; i < n; i++) {
+        printf("0x%02X ", p[i]);
+    }
+    printf("\\n");
+}
+EOF
+}
+
+sub output_server_wrapper
+{
+    my ($fh, $f, $name) = @_;
+
+    my $ret_type = $f->{return}->{type};
+    my $ret_name = $f->{return}->{name};
+    my $ret_default = $f->{return}->{default};
+
+    my @buffers = ();           # We need to free() these on exit
+
+    print $fh <<EOF;
+
+// Returns 1 for success, 0 for failure
+int ${name}_wrapper(
+    uint8_t *in_params, size_t in_params_len,
+    uint8_t **out_params, size_t *out_params_len)
+{
+    $ret_type $ret_name = $ret_default;
+EOF
+    # Output the variables we will need when we call the target function
+
+    my $args = $f->{args};
+
+    for my $i (0 .. $#$args) {
+        my $arg = $args->[$i];
+        my $argtype = $arg->{type};     # e.g. int, psa_algorithm_t, or "buffer"
+        my $argname = $arg->{name};
+        $argtype =~ s/^const //;
+
+        if ($argtype =~ /^(const )?buffer$/) {
+            my ($n1, $n2) = split(/,\s*/, $argname);
+            print $fh <<EOF;
+    uint8_t *$n1 = NULL;
+    size_t $n2;
+EOF
+            push(@buffers, $n1);        # Add to the list to be free()d at end
+        } else {
+            $argname =~ s/^\*//;        # Remove any leading *
+            print $fh <<EOF;
+    $argtype $argname;
+EOF
+        }
+    }
+
+    print $fh "\n";
+
+    if ($#$args >= 0) {          # If we have any args (>= 0)
+        print $fh <<EOF;
+    uint8_t *pos = in_params;
+    size_t remaining = in_params_len;
+EOF
+    }
+
+    print $fh <<EOF;
+    uint8_t *result = NULL;
+    int ok;
+EOF
+
+    print $fh <<EOF if $debug;
+
+    printf("$name: server\\n");
+EOF
+    if ($#$args >= 0) {          # If we have any args (>= 0)
+        print $fh <<EOF;
+
+    ok = psasim_deserialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+EOF
+    }
+
+    for my $i (0 .. $#$args) {
+        my $arg = $args->[$i];
+        my $argtype = $arg->{type};     # e.g. int, psa_algorithm_t, or "buffer"
+        my $argname = $arg->{name};
+        my $sep = ($i == $#$args) ? ";" : " +";
+        $argtype =~ s/^const //;
+
+        if ($argtype =~ /^(const )?buffer$/) {
+            my ($n1, $n2) = split(/,\s*/, $argname);
+            print $fh <<EOF;
+
+    ok = psasim_deserialise_${argtype}(&pos, &remaining, &$n1, &$n2);
+    if (!ok) {
+        goto fail;
+    }
+EOF
+        } else {
+            $argname =~ s/^\*//;        # Remove any leading *
+            print $fh <<EOF;
+
+    ok = psasim_deserialise_${argtype}(&pos, &remaining, &$argname);
+    if (!ok) {
+        goto fail;
+    }
+EOF
+        }
+    }
+
+    print $fh <<EOF;
+
+    // Now we call the actual target function
+EOF
+    output_call($fh, $f, $name);
+
+    my @outputs = grep($_->{is_output}, @$args);
+
+    my $sep1 = ($ret_type eq "void") ? ";" : " +";
+
+    print $fh <<EOF;
+
+    // NOTE: Should really check there is no overflow as we go along.
+    size_t result_size =
+        psasim_serialise_begin_needs()$sep1
+EOF
+
+    if ($ret_type ne "void") {
+        my $sep = ($#outputs < 0) ? ";" : " +";
+        print $fh <<EOF;
+        psasim_serialise_${ret_type}_needs($ret_name)$sep
+EOF
+    }
+
+    for my $i (0 .. $#outputs) {
+        my $arg = $outputs[$i];
+        die("$i: this should have been filtered out by grep") unless $arg->{is_output};
+        my $argtype = $arg->{type};     # e.g. int, psa_algorithm_t, or "buffer"
+        my $argname = $arg->{name};
+        my $sep = ($i == $#outputs) ? ";" : " +";
+        $argtype =~ s/^const //;
+        $argname =~ s/^\*//;        # Remove any leading *
+
+        print $fh <<EOF;
+        psasim_serialise_${argtype}_needs($argname)$sep
+EOF
+    }
+
+    print $fh <<EOF;
+
+    result = malloc(result_size);
+    if (result == NULL) {
+        goto fail;
+    }
+
+    uint8_t *rpos = result;
+    size_t rremain = result_size;
+
+    ok = psasim_serialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+EOF
+
+    if ($ret_type ne "void") {
+        print $fh <<EOF;
+
+    ok = psasim_serialise_${ret_type}(&rpos, &rremain, $ret_name);
+    if (!ok) {
+        goto fail;
+    }
+EOF
+    }
+
+    my @outputs = grep($_->{is_output}, @$args);
+
+    for my $i (0 .. $#outputs) {
+        my $arg = $outputs[$i];
+        die("$i: this should have been filtered out by grep") unless $arg->{is_output};
+        my $argtype = $arg->{type};     # e.g. int, psa_algorithm_t, or "buffer"
+        my $argname = $arg->{name};
+        my $sep = ($i == $#outputs) ? ";" : " +";
+        $argtype =~ s/^const //;
+
+        if ($argtype eq "buffer") {
+            print $fh <<EOF;
+
+    ok = psasim_serialise_buffer(&rpos, &rremain, $argname);
+    if (!ok) {
+        goto fail;
+    }
+EOF
+        } else {
+            if ($argname =~ /^\*/) {
+                $argname =~ s/^\*//;    # since it's already a pointer
+            } else {
+                die("$0: $argname: HOW TO OUTPUT?\n");
+            }
+
+            print $fh <<EOF;
+
+    ok = psasim_serialise_${argtype}(&rpos, &rremain, $argname);
+    if (!ok) {
+        goto fail;
+    }
+EOF
+        }
+    }
+
+    my $free_buffers = join("", map { "    free($_);\n" } @buffers);
+    $free_buffers = "\n" . $free_buffers if length($free_buffers);
+
+    print $fh <<EOF;
+
+    *out_params = result;
+    *out_params_len = result_size;
+$free_buffers
+    return 1;   // success
+
+fail:
+    free(result);
+$free_buffers
+    return 0;       // This shouldn't happen!
+}
+EOF
+}
+
+sub output_client
+{
+    my ($fh, $f, $name) = @_;
+
+    print $fh "\n";
+
+    output_definition_begin($fh, $f, $name);
+
+    my $ret_type = $f->{return}->{type};
+    my $ret_name = $f->{return}->{name};
+    my $ret_default = $f->{return}->{default};
+
+    print $fh <<EOF;
+{
+    uint8_t *params = NULL;
+    uint8_t *result = NULL;
+    size_t result_length;
+    $ret_type $ret_name = $ret_default;
+EOF
+
+    print $fh <<EOF if $debug;
+
+    printf("$name: client\\n");
+EOF
+
+    print $fh <<EOF;
+
+    size_t needed = psasim_serialise_begin_needs() +
+EOF
+
+    my $args = $f->{args};
+
+    for my $i (0 .. $#$args) {
+        my $arg = $args->[$i];
+        my $argtype = $arg->{type};     # e.g. int, psa_algorithm_t, or "buffer"
+        my $argname = $arg->{name};
+        my $sep = ($i == $#$args) ? ";" : " +";
+        $argtype =~ s/^const //;
+
+        print $fh <<EOF;
+                    psasim_serialise_${argtype}_needs($argname)$sep
+EOF
+    }
+
+    print $fh <<EOF;
+
+    params = malloc(needed);
+    if (params == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto fail;
+    }
+
+    uint8_t *pos = params;
+    size_t remaining = needed;
+    int ok;
+    ok = psasim_serialise_begin(&pos, &remaining);
+    if (!ok) {
+        goto fail;
+    }
+EOF
+
+    for my $i (0 .. $#$args) {
+        my $arg = $args->[$i];
+        my $argtype = $arg->{type};     # e.g. int, psa_algorithm_t, or "buffer"
+        my $argname = $arg->{name};
+        my $sep = ($i == $#$args) ? ";" : " +";
+        $argtype =~ s/^const //;
+
+        print $fh <<EOF;
+    ok = psasim_serialise_${argtype}(&pos, &remaining, $argname);
+    if (!ok) {
+        goto fail;
+    }
+EOF
+    }
+
+    print $fh <<EOF if $debug;
+
+    printf("client sending %d:\\n", (int)(pos - params));
+    dump_buffer(params, (size_t)(pos - params));
+EOF
+
+    my $enum = uc($name);
+
+    print $fh <<EOF;
+
+    ok = psa_crypto_call($enum,
+                         params, (size_t) (pos - params), &result, &result_length);
+    if (!ok) {
+        printf("XXX server call failed\\n");
+        goto fail;
+    }
+EOF
+
+    print $fh <<EOF if $debug;
+
+    printf("client receiving %d:\\n", (int)result_length);
+    dump_buffer(result, result_length);
+EOF
+
+    print $fh <<EOF;
+
+    uint8_t *rpos = result;
+    size_t rremain = result_length;
+
+    ok = psasim_deserialise_begin(&rpos, &rremain);
+    if (!ok) {
+        goto fail;
+    }
+EOF
+
+    print $fh <<EOF;
+
+    ok = psasim_deserialise_$ret_type(&rpos, &rremain, &$ret_name);
+    if (!ok) {
+        goto fail;
+    }
+EOF
+
+    my @outputs = grep($_->{is_output}, @$args);
+
+    for my $i (0 .. $#outputs) {
+        my $arg = $outputs[$i];
+        die("$i: this should have been filtered out by grep") unless $arg->{is_output};
+        my $argtype = $arg->{type};     # e.g. int, psa_algorithm_t, or "buffer"
+        my $argname = $arg->{name};
+        my $sep = ($i == $#outputs) ? ";" : " +";
+        $argtype =~ s/^const //;
+
+        if ($argtype eq "buffer") {
+            print $fh <<EOF;
+
+    ok = psasim_deserialise_return_buffer(&rpos, &rremain, $argname);
+    if (!ok) {
+        goto fail;
+    }
+EOF
+        } else {
+            if ($argname =~ /^\*/) {
+                $argname =~ s/^\*//;    # since it's already a pointer
+            } else {
+                die("$0: $argname: HOW TO OUTPUT?\n");
+            }
+
+            print $fh <<EOF;
+
+    ok = psasim_deserialise_${argtype}(&rpos, &rremain, $argname);
+    if (!ok) {
+        goto fail;
+    }
+EOF
+        }
+    }
+    print $fh <<EOF;
+
+fail:
+    free(params);
+    free(result);
+
+    return $ret_name;
+}
+EOF
+}
+
+sub output_declaration
+{
+    my ($f, $name) = @_;
+
+    output_signature($f, $name, "declaration");
+}
+
+sub output_definition_begin
+{
+    my ($fh, $f, $name) = @_;
+
+    output_signature($fh, $f, $name, "definition");
+}
+
+sub output_call
+{
+    my ($fh, $f, $name) = @_;
+
+    my $ret_name = $f->{return}->{name};
+    my $args = $f->{args};
+
+    print $fh "\n    $ret_name = $name(\n";
+
+    print $fh "        );\n" if $#$args < 0; # If no arguments, empty arg list
+
+    for my $i (0 .. $#$args) {
+        my $arg = $args->[$i];
+        my $argtype = $arg->{type};     # e.g. int, psa_algorithm_t, or "buffer"
+        my $argname = $arg->{name};
+
+        if ($argtype =~ /^(const )?buffer$/) {
+            my ($n1, $n2) = split(/,\s*/, $argname);
+            print $fh "        $n1, $n2";
+        } else {
+            $argname =~ s/^\*/\&/;      # Replace leading * with &
+            print $fh "        $argname";
+        }
+        my $sep = ($i == $#$args) ? "\n        );" : ",";
+        print $fh "$sep\n";
+    }
+}
+
+sub output_signature
+{
+    my ($fh, $f, $name, $what) = @_;
+
+    my $ret_type = $f->{return}->{type};
+    my $args = $f->{args};
+
+    my $final_sep = ($what eq "declaration") ? "\n);" : "\n    )";
+
+    print $fh "\n$ret_type $name(\n";
+
+    print $fh "    void\n)\n" if $#$args < 0;   # No arguments
+
+    for my $i (0 .. $#$args) {
+        my $arg = $args->[$i];
+        my $argtype = $arg->{type};             # e.g. int, psa_algorithm_t, or "buffer"
+        my $ctypename = $arg->{ctypename};      # e.g. "int ", "char *"; empty for buffer
+        my $argname = $arg->{name};
+
+        if ($argtype =~ /^(const )?buffer$/) {
+            my $const = length($1) ? "const " : "";
+            my ($n1, $n2) = split(/,/, $argname);
+            print $fh "    ${const}uint8_t *$n1, size_t $n2";
+        } else {
+            print $fh "    $ctypename$argname";
+        }
+        my $sep = ($i == $#$args) ? $final_sep : ",";
+        print $fh "$sep\n";
+    }
+}
+
+sub get_functions
+{
+    my $src = "";
+    while (<DATA>) {
+        chomp;
+        s/\/\/.*//;
+        s/\s+^//;
+        s/\s+/ /g;
+        $_ .= "\n";
+        $src .= $_;
+    }
+
+    $src =~ s/\/\*.*?\*\///gs;
+
+    my @src = split(/\n+/, $src);
+
+    my @rebuild = ();
+    my %funcs = ();
+    for (my $i = 0; $i <= $#src; $i++) {
+        my $line = $src[$i];
+        if ($line =~ /^psa_status_t (psa_\w*)\(/) { # begin function definition
+            #print "have one $line\n";
+            while ($line !~ /;/) {
+                $line .= $src[$i + 1];
+                $i++;
+            }
+            $line =~ s/\s+/ /g;
+            if ($line =~ /(\w+)\s+\b(\w+)\s*\(\s*(.*\S)\s*\)\s*[;{]/s) {
+                my ($ret_type, $func, $args) = ($1, $2, $3);
+                my $copy = $line;
+                $copy =~ s/{$//;
+                my $f = {
+                    "orig" => $copy,
+                };
+
+                my @args = split(/\s*,\s*/, $args);
+
+                my $ret_name = "";
+                $ret_name = "status" if $ret_type eq "psa_status_t";
+                die("ret_name for $ret_type?") unless length($ret_name);
+                my $ret_default = "";
+                $ret_default = "PSA_ERROR_CORRUPTION_DETECTED" if $ret_type eq "psa_status_t";
+                die("ret_default for $ret_type?") unless length($ret_default);
+
+                #print "FUNC $func RET_NAME $ret_name RET_TYPE $ret_type ARGS (", join("; ", @args), ")\n";
+
+                $f->{return} = {
+                    "type" => $ret_type,
+                    "default" => $ret_default,
+                    "name" => $ret_name,
+                };
+                $f->{args} = [];
+                # psa_algorithm_t alg; const uint8_t *input; size_t input_length; uint8_t *hash; size_t hash_size; size_t *hash_length
+                for (my $i = 0; $i <= $#args; $i++) {
+                    my $arg = $args[$i];
+                    # "type" => "psa_algorithm_t",
+                    # "ctypename" => "psa_algorithm_t ",
+                    # "name" => "alg",
+                    # "is_output" => 0,
+                    my ($type, $ctype, $name, $is_output);
+                    if ($arg =~ /^(\w+)\s+(\w+)$/) {    # e.g. psa_algorithm_t alg
+                        ($type, $name) = ($1, $2);
+                        $ctype = $type . " ";
+                        $is_output = 0;
+                    } elsif ($arg =~ /^((const)\s+)?uint8_t\s*\*\s*(\w+)$/) {
+                        $type = "buffer";
+                        $is_output = (length($1) == 0) ? 1 : 0;
+                        $type = "const buffer" if !$is_output;
+                        $ctype = "";
+                        $name = $3;
+                        #print("$arg: $name: might be a buffer?\n");
+                        die("$arg: not a buffer 1!\n") if $i == $#args;
+                        my $next = $args[$i + 1];
+                        die("$arg: not a buffer 2!\n") if $next !~ /^size_t\s+(${name}_\w+)$/;
+                        $i++;                   # We're using the next param here
+                        my $nname = $1;
+                        $name .= ", " . $nname;
+                    } elsif ($arg =~ /^((const)\s+)?(\w+)\s*\*(\w+)$/) {
+                        ($type, $name) = ($3, "*" . $4);
+                        $ctype = $1 . $type . " ";
+                        $is_output = (length($1) == 0) ? 1 : 0;
+                    } elsif ($arg eq "void") {
+                         # we'll just ignore this one
+                    } else {
+                        die("ARG HELP $arg\n");
+                    }
+                    #print "$arg => <$type><$ctype><$name><$is_output>\n";
+                    if ($arg ne "void") {
+                        push(@{$f->{args}}, {
+                            "type" => $type,
+                            "ctypename" => $ctype,
+                            "name" => $name,
+                            "is_output" => $is_output,
+                        });
+                    }
+                }
+                $funcs{$func} = $f;
+            } else {
+                die("FAILED");
+            }
+            push(@rebuild, $line);
+        } elsif ($line =~ /^static psa_\w+_t (psa_\w*)\(/) { # begin function definition
+             # IGNORE static functions
+        } else {
+            if ($line =~ /psa_/) {
+                print "NOT PARSED: $line\n";
+            }
+            push(@rebuild, $line);
+        }
+    }
+
+    #print ::Dumper(\%funcs);
+    #exit;
+
+    return %funcs;
+}
+
+sub put_crypto_init_first
+{
+    my ($functions) = @_;
+
+    my $want_first = "psa_crypto_init";
+
+    my $idx = undef;
+    for my $i (0 .. $#$functions) {
+        if ($functions->[$i] eq $want_first) {
+            $idx = $i;
+            last;
+        }
+    }
+
+    if (defined($idx) && $idx != 0) {   # Do nothing if already first
+        splice(@$functions, $idx, 1);
+        unshift(@$functions, $want_first);
+    }
+}
+
+__END__
+/**
+ * \brief Library initialization.
+ *
+ * Applications must call this function before calling any other
+ * function in this module.
+ *
+ * Applications may call this function more than once. Once a call
+ * succeeds, subsequent calls are guaranteed to succeed.
+ *
+ * If the application calls other functions before calling psa_crypto_init(),
+ * the behavior is undefined. Implementations are encouraged to either perform
+ * the operation as if the library had been initialized or to return
+ * #PSA_ERROR_BAD_STATE or some other applicable error. In particular,
+ * implementations should not return a success status if the lack of
+ * initialization may have security implications, for example due to improper
+ * seeding of the random number generator.
+ *
+ * \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);
+
+/** Calculate the hash (digest) of a message.
+ *
+ * \note To verify the hash of a message against an
+ *       expected value, use psa_hash_compare() instead.
+ *
+ * \param alg               The hash algorithm to compute (\c PSA_ALG_XXX value
+ *                          such that #PSA_ALG_IS_HASH(\p alg) is true).
+ * \param[in] input         Buffer containing the message to hash.
+ * \param input_length      Size of the \p input buffer in bytes.
+ * \param[out] hash         Buffer where the hash is to be written.
+ * \param hash_size         Size of the \p hash buffer in bytes.
+ * \param[out] hash_length  On success, the number of bytes
+ *                          that make up the hash value. This is always
+ *                          #PSA_HASH_LENGTH(\p alg).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported or is not a hash algorithm.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         \p hash_size is too small
+ * \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
+ *         results in this error code.
+ */
+psa_status_t psa_hash_compute(psa_algorithm_t alg,
+                              const uint8_t *input,
+                              size_t input_length,
+                              uint8_t *hash,
+                              size_t hash_size,
+                              size_t *hash_length);
+
+/* XXX We put this next one in place to check we ignore static functions
+ *     when we eventually read all this from a real header file
+ */
+
+/** Return an initial value for a hash operation object.
+ */
+static psa_hash_operation_t psa_hash_operation_init(void);
+
+/* XXX Back to normal function declarations */
+
+/** Set up a multipart hash operation.
+ *
+ * The sequence of operations to calculate a hash (message digest)
+ * is as follows:
+ * -# Allocate an operation object which will be passed to all the functions
+ *    listed here.
+ * -# Initialize the operation object with one of the methods described in the
+ *    documentation for #psa_hash_operation_t, e.g. #PSA_HASH_OPERATION_INIT.
+ * -# Call psa_hash_setup() to specify the algorithm.
+ * -# Call psa_hash_update() zero, one or more times, passing a fragment
+ *    of the message each time. The hash that is calculated is the hash
+ *    of the concatenation of these messages in order.
+ * -# To calculate the hash, call psa_hash_finish().
+ *    To compare the hash with an expected value, call psa_hash_verify().
+ *
+ * If an error occurs at any step after a call to psa_hash_setup(), the
+ * operation will need to be reset by a call to psa_hash_abort(). The
+ * application may call psa_hash_abort() at any time after the operation
+ * has been initialized.
+ *
+ * After a successful call to psa_hash_setup(), the application must
+ * eventually terminate the operation. The following events terminate an
+ * operation:
+ * - A successful call to psa_hash_finish() or psa_hash_verify().
+ * - A call to psa_hash_abort().
+ *
+ * \param[in,out] operation The operation object to set up. It must have
+ *                          been initialized as per the documentation for
+ *                          #psa_hash_operation_t and not yet in use.
+ * \param alg               The hash algorithm to compute (\c PSA_ALG_XXX value
+ *                          such that #PSA_ALG_IS_HASH(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \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 \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().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_hash_setup(psa_hash_operation_t *operation,
+                            psa_algorithm_t alg);
+
+/** Add a message fragment to a multipart hash operation.
+ *
+ * The application must call psa_hash_setup() before calling this function.
+ *
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling psa_hash_abort().
+ *
+ * \param[in,out] operation Active hash operation.
+ * \param[in] input         Buffer containing the message fragment to hash.
+ * \param input_length      Size of the \p input buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \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().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_hash_update(psa_hash_operation_t *operation,
+                             const uint8_t *input,
+                             size_t input_length);
+
+/** Finish the calculation of the hash of a message.
+ *
+ * The application must call psa_hash_setup() before calling this function.
+ * This function calculates the hash of the message formed by concatenating
+ * the inputs passed to preceding calls to psa_hash_update().
+ *
+ * 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 psa_hash_abort().
+ *
+ * \warning Applications should not call this function if they expect
+ *          a specific value for the hash. Call psa_hash_verify() instead.
+ *          Beware that comparing integrity or authenticity data such as
+ *          hash values with a function such as \c memcmp is risky
+ *          because the time taken by the comparison may leak information
+ *          about the hashed data which could allow an attacker to guess
+ *          a valid hash and thereby bypass security controls.
+ *
+ * \param[in,out] operation     Active hash operation.
+ * \param[out] hash             Buffer where the hash is to be written.
+ * \param hash_size             Size of the \p hash buffer in bytes.
+ * \param[out] hash_length      On success, the number of bytes
+ *                              that make up the hash value. This is always
+ *                              #PSA_HASH_LENGTH(\c alg) where \c alg is the
+ *                              hash algorithm that is calculated.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         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 \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().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_hash_finish(psa_hash_operation_t *operation,
+                             uint8_t *hash,
+                             size_t hash_size,
+                             size_t *hash_length);
+
+/** Finish the calculation of the hash of a message and compare it with
+ * an expected value.
+ *
+ * The application must call psa_hash_setup() before calling this function.
+ * This function calculates the hash of the message formed by concatenating
+ * the inputs passed to preceding calls to psa_hash_update(). It then
+ * compares the calculated hash with the expected hash passed as a
+ * parameter to this function.
+ *
+ * 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 psa_hash_abort().
+ *
+ * \note Implementations shall make the best effort to ensure that the
+ * comparison between the actual hash and the expected hash is performed
+ * in constant time.
+ *
+ * \param[in,out] operation     Active hash operation.
+ * \param[in] hash              Buffer containing the expected hash value.
+ * \param hash_length           Size of the \p hash buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The expected hash is identical to the actual hash of the message.
+ * \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 \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().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_hash_verify(psa_hash_operation_t *operation,
+                             const uint8_t *hash,
+                             size_t hash_length);
+
+/** Abort a hash operation.
+ *
+ * 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
+ * psa_hash_setup() again.
+ *
+ * You may call this function any time after the operation object has
+ * been initialized by one of the methods described in #psa_hash_operation_t.
+ *
+ * In particular, calling psa_hash_abort() after the operation has been
+ * terminated by a call to psa_hash_abort(), psa_hash_finish() or
+ * psa_hash_verify() is safe and has no effect.
+ *
+ * \param[in,out] operation     Initialized hash operation.
+ *
+ * \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
+ *         results in this error code.
+ */
+psa_status_t psa_hash_abort(psa_hash_operation_t *operation);
+
+/** Clone a hash operation.
+ *
+ * This function copies the state of an ongoing hash operation to
+ * a new operation object. In other words, this function is equivalent
+ * to calling psa_hash_setup() on \p target_operation with the same
+ * algorithm that \p source_operation was set up for, then
+ * psa_hash_update() on \p target_operation with the same input that
+ * that was passed to \p source_operation. After this function returns, the
+ * two objects are independent, i.e. subsequent calls involving one of
+ * the objects do not affect the other object.
+ *
+ * \param[in] source_operation      The active hash operation to clone.
+ * \param[in,out] target_operation  The operation object to set up.
+ *                                  It must be initialized but not active.
+ *
+ * \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
+ *         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_hash_clone(const psa_hash_operation_t *source_operation,
+                            psa_hash_operation_t *target_operation);
+
+/** Calculate the hash (digest) of a message and compare it with a
+ * reference value.
+ *
+ * \param alg               The hash algorithm to compute (\c PSA_ALG_XXX value
+ *                          such that #PSA_ALG_IS_HASH(\p alg) is true).
+ * \param[in] input         Buffer containing the message to hash.
+ * \param input_length      Size of the \p input buffer in bytes.
+ * \param[out] hash         Buffer containing the expected hash value.
+ * \param hash_length       Size of the \p hash buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The expected hash is identical to the actual hash of the input.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The hash of the message was calculated successfully, but it
+ *         differs from the expected hash.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \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 \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
+ *         results in this error code.
+ */
+psa_status_t psa_hash_compare(psa_algorithm_t alg,
+                              const uint8_t *input,
+                              size_t input_length,
+                              const uint8_t *hash,
+                              size_t hash_length);
diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.c b/tests/psa-client-server/psasim/src/psa_sim_serialise.c
new file mode 100644
index 0000000..78ae9d6
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.c
@@ -0,0 +1,406 @@
+/**
+ * \file psa_sim_serialise.c
+ *
+ * \brief Rough-and-ready serialisation and deserialisation for the PSA Crypto simulator
+ */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "psa_sim_serialise.h"
+#include <stdlib.h>
+#include <string.h>
+
+/* Basic idea:
+ *
+ * All arguments to a function will be serialised into a single buffer to
+ * be sent to the server with the PSA crypto function to be called.
+ *
+ * All returned data (the function's return value and any values returned
+ * via `out` parameters) will similarly be serialised into a buffer to be
+ * sent back to the client from the server.
+ *
+ * For each data type foo (e.g. int, size_t, psa_algorithm_t, but also "buffer"
+ * where "buffer" is a (uint8_t *, size_t) pair, we have a pair of functions,
+ * psasim_serialise_foo() and psasim_deserialise_foo().
+ *
+ * We also have psasim_serialise_foo_needs() functions, which return a
+ * size_t giving the number of bytes that serialising that instance of that
+ * type will need. This allows callers to size buffers for serialisation.
+ *
+ * Each serialised buffer starts with a version byte, bytes that indicate
+ * the size of basic C types, and four bytes that indicate the endianness
+ * (to avoid incompatibilities if we ever run this over a network - we are
+ * not aiming for universality, just for correctness and simplicity).
+ *
+ * Most types are serialised as a fixed-size (per type) octet string, with
+ * no type indication. This is acceptable as (a) this is for the test PSA crypto
+ * simulator only, not production, and (b) these functions are called by
+ * code that itself is written by script.
+ *
+ * We also want to keep serialised data reasonably compact as communication
+ * between client and server goes in messages of less than 200 bytes each.
+ *
+ * Many serialisation functions can be created by a script; an exemplar Perl
+ * script is included. It is not hooked into the build and so must be run
+ * manually, but is expected to be replaced by a Python script in due course.
+ * Types that can have their functions created by script include plain old C
+ * data types (e.g. int), types typedef'd to those, and even structures that
+ * don't contain pointers.
+ */
+
+size_t psasim_serialise_begin_needs(void)
+{
+    /* The serialisation buffer will
+     * start with a byte of 0 to indicate version 0,
+     * then have 1 byte each for length of int, long, void *,
+     * then have 4 bytes to indicate endianness. */
+    return 4 + sizeof(uint32_t);
+}
+
+int psasim_serialise_begin(uint8_t **pos, size_t *remaining)
+{
+    uint32_t endian = 0x1234;
+
+    if (*remaining < 4 + sizeof(endian)) {
+        return 0;
+    }
+
+    *(*pos)++ = 0;      /* version */
+    *(*pos)++ = (uint8_t) sizeof(int);
+    *(*pos)++ = (uint8_t) sizeof(long);
+    *(*pos)++ = (uint8_t) sizeof(void *);
+
+    memcpy(*pos, &endian, sizeof(endian));
+
+    *pos += sizeof(endian);
+
+    return 1;
+}
+
+int psasim_deserialise_begin(uint8_t **pos, size_t *remaining)
+{
+    uint8_t version = 255;
+    uint8_t int_size = 0;
+    uint8_t long_size = 0;
+    uint8_t ptr_size = 0;
+    uint32_t endian;
+
+    if (*remaining < 4 + sizeof(endian)) {
+        return 0;
+    }
+
+    memcpy(&version, (*pos)++, sizeof(version));
+    if (version != 0) {
+        return 0;
+    }
+
+    memcpy(&int_size, (*pos)++, sizeof(int_size));
+    if (int_size != sizeof(int)) {
+        return 0;
+    }
+
+    memcpy(&long_size, (*pos)++, sizeof(long_size));
+    if (long_size != sizeof(long)) {
+        return 0;
+    }
+
+    memcpy(&ptr_size, (*pos)++, sizeof(ptr_size));
+    if (ptr_size != sizeof(void *)) {
+        return 0;
+    }
+
+    *remaining -= 4;
+
+    memcpy(&endian, *pos, sizeof(endian));
+    if (endian != 0x1234) {
+        return 0;
+    }
+
+    *pos += sizeof(endian);
+    *remaining -= sizeof(endian);
+
+    return 1;
+}
+
+size_t psasim_serialise_unsigned_int_needs(unsigned int value)
+{
+    return sizeof(value);
+}
+
+int psasim_serialise_unsigned_int(uint8_t **pos,
+                                  size_t *remaining,
+                                  unsigned int value)
+{
+    if (*remaining < sizeof(value)) {
+        return 0;
+    }
+
+    memcpy(*pos, &value, sizeof(value));
+    *pos += sizeof(value);
+
+    return 1;
+}
+
+int psasim_deserialise_unsigned_int(uint8_t **pos,
+                                    size_t *remaining,
+                                    unsigned int *value)
+{
+    if (*remaining < sizeof(*value)) {
+        return 0;
+    }
+
+    memcpy(value, *pos, sizeof(*value));
+
+    *pos += sizeof(*value);
+    *remaining -= sizeof(*value);
+
+    return 1;
+}
+
+size_t psasim_serialise_int_needs(int value)
+{
+    return sizeof(value);
+}
+
+int psasim_serialise_int(uint8_t **pos,
+                         size_t *remaining,
+                         int value)
+{
+    if (*remaining < sizeof(value)) {
+        return 0;
+    }
+
+    memcpy(*pos, &value, sizeof(value));
+    *pos += sizeof(value);
+
+    return 1;
+}
+
+int psasim_deserialise_int(uint8_t **pos,
+                           size_t *remaining,
+                           int *value)
+{
+    if (*remaining < sizeof(*value)) {
+        return 0;
+    }
+
+    memcpy(value, *pos, sizeof(*value));
+
+    *pos += sizeof(*value);
+    *remaining -= sizeof(*value);
+
+    return 1;
+}
+
+size_t psasim_serialise_size_t_needs(size_t value)
+{
+    return sizeof(value);
+}
+
+int psasim_serialise_size_t(uint8_t **pos,
+                            size_t *remaining,
+                            size_t value)
+{
+    if (*remaining < sizeof(value)) {
+        return 0;
+    }
+
+    memcpy(*pos, &value, sizeof(value));
+    *pos += sizeof(value);
+
+    return 1;
+}
+
+int psasim_deserialise_size_t(uint8_t **pos,
+                              size_t *remaining,
+                              size_t *value)
+{
+    if (*remaining < sizeof(*value)) {
+        return 0;
+    }
+
+    memcpy(value, *pos, sizeof(*value));
+
+    *pos += sizeof(*value);
+    *remaining -= sizeof(*value);
+
+    return 1;
+}
+
+size_t psasim_serialise_buffer_needs(const uint8_t *buffer, size_t buffer_size)
+{
+    (void) buffer;
+    return sizeof(buffer_size) + buffer_size;
+}
+
+int psasim_serialise_buffer(uint8_t **pos,
+                            size_t *remaining,
+                            const uint8_t *buffer,
+                            size_t buffer_length)
+{
+    if (*remaining < sizeof(buffer_length) + buffer_length) {
+        return 0;
+    }
+
+    memcpy(*pos, &buffer_length, sizeof(buffer_length));
+    *pos += sizeof(buffer_length);
+
+    if (buffer_length > 0) {    // To be able to serialise (NULL, 0)
+        memcpy(*pos, buffer, buffer_length);
+        *pos += buffer_length;
+    }
+
+    return 1;
+}
+
+int psasim_deserialise_buffer(uint8_t **pos,
+                              size_t *remaining,
+                              uint8_t **buffer,
+                              size_t *buffer_length)
+{
+    if (*remaining < sizeof(*buffer_length)) {
+        return 0;
+    }
+
+    memcpy(buffer_length, *pos, sizeof(*buffer_length));
+
+    *pos += sizeof(buffer_length);
+    *remaining -= sizeof(buffer_length);
+
+    if (*buffer_length == 0) {          // Deserialise (NULL, 0)
+        *buffer = NULL;
+        return 1;
+    }
+
+    if (*remaining < *buffer_length) {
+        return 0;
+    }
+
+    uint8_t *data = malloc(*buffer_length);
+    if (data == NULL) {
+        return 0;
+    }
+
+    memcpy(data, *pos, *buffer_length);
+    *pos += *buffer_length;
+    *remaining -= *buffer_length;
+
+    *buffer = data;
+
+    return 1;
+}
+
+/* When the client is deserialising a buffer returned from the server, it needs
+ * to use this function to deserialised the  returned buffer. It should use the
+ * usual \c psasim_serialise_buffer() function to serialise the outbound
+ * buffer. */
+int psasim_deserialise_return_buffer(uint8_t **pos,
+                                     size_t *remaining,
+                                     uint8_t *buffer,
+                                     size_t buffer_length)
+{
+    if (*remaining < sizeof(buffer_length)) {
+        return 0;
+    }
+
+    size_t length_check;
+
+    memcpy(&length_check, *pos, sizeof(buffer_length));
+
+    *pos += sizeof(buffer_length);
+    *remaining -= sizeof(buffer_length);
+
+    if (buffer_length != length_check) {        // Make sure we're sent back the same we sent to the server
+        return 0;
+    }
+
+    if (length_check == 0) {          // Deserialise (NULL, 0)
+        return 1;
+    }
+
+    if (*remaining < buffer_length) {
+        return 0;
+    }
+
+    memcpy(buffer, *pos, buffer_length);
+    *pos += buffer_length;
+    *remaining -= buffer_length;
+
+    return 1;
+}
+
+size_t psasim_serialise_psa_status_t_needs(psa_status_t value)
+{
+    return psasim_serialise_int_needs(value);
+}
+
+int psasim_serialise_psa_status_t(uint8_t **pos,
+                                  size_t *remaining,
+                                  psa_status_t value)
+{
+    return psasim_serialise_int(pos, remaining, value);
+}
+
+int psasim_deserialise_psa_status_t(uint8_t **pos,
+                                    size_t *remaining,
+                                    psa_status_t *value)
+{
+    return psasim_deserialise_int(pos, remaining, value);
+}
+
+size_t psasim_serialise_psa_algorithm_t_needs(psa_algorithm_t value)
+{
+    return psasim_serialise_unsigned_int_needs(value);
+}
+
+int psasim_serialise_psa_algorithm_t(uint8_t **pos,
+                                     size_t *remaining,
+                                     psa_algorithm_t value)
+{
+    return psasim_serialise_unsigned_int(pos, remaining, value);
+}
+
+int psasim_deserialise_psa_algorithm_t(uint8_t **pos,
+                                       size_t *remaining,
+                                       psa_algorithm_t *value)
+{
+    return psasim_deserialise_unsigned_int(pos, remaining, value);
+}
+
+size_t psasim_serialise_psa_hash_operation_t_needs(psa_hash_operation_t value)
+{
+    return sizeof(value);
+}
+
+int psasim_serialise_psa_hash_operation_t(uint8_t **pos,
+                                          size_t *remaining,
+                                          psa_hash_operation_t value)
+{
+    if (*remaining < sizeof(value)) {
+        return 0;
+    }
+
+    memcpy(*pos, &value, sizeof(value));
+    *pos += sizeof(value);
+
+    return 1;
+}
+
+int psasim_deserialise_psa_hash_operation_t(uint8_t **pos,
+                                            size_t *remaining,
+                                            psa_hash_operation_t *value)
+{
+    if (*remaining < sizeof(*value)) {
+        return 0;
+    }
+
+    memcpy(value, *pos, sizeof(*value));
+
+    *pos += sizeof(*value);
+    *remaining -= sizeof(*value);
+
+    return 1;
+}
diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.h b/tests/psa-client-server/psasim/src/psa_sim_serialise.h
new file mode 100644
index 0000000..d5eaccf
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.h
@@ -0,0 +1,410 @@
+/**
+ * \file psa_sim_serialise.h
+ *
+ * \brief Rough-and-ready serialisation and deserialisation for the PSA Crypto simulator
+ */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "psa/crypto.h"
+#include "psa/crypto_types.h"
+#include "psa/crypto_values.h"
+
+/* Basic idea:
+ *
+ * All arguments to a function will be serialised into a single buffer to
+ * be sent to the server with the PSA crypto function to be called.
+ *
+ * All returned data (the function's return value and any values returned
+ * via `out` parameters) will similarly be serialised into a buffer to be
+ * sent back to the client from the server.
+ *
+ * For each data type foo (e.g. int, size_t, psa_algorithm_t, but also "buffer"
+ * where "buffer" is a (uint8_t *, size_t) pair, we have a pair of functions,
+ * psasim_serialise_foo() and psasim_deserialise_foo().
+ *
+ * We also have psasim_serialise_foo_needs() functions, which return a
+ * size_t giving the number of bytes that serialising that instance of that
+ * type will need. This allows callers to size buffers for serialisation.
+ *
+ * Each serialised buffer starts with a version byte, bytes that indicate
+ * the size of basic C types, and four bytes that indicate the endianness
+ * (to avoid incompatibilities if we ever run this over a network - we are
+ * not aiming for universality, just for correctness and simplicity).
+ *
+ * Most types are serialised as a fixed-size (per type) octet string, with
+ * no type indication. This is acceptable as (a) this is for the test PSA crypto
+ * simulator only, not production, and (b) these functions are called by
+ * code that itself is written by script.
+ *
+ * We also want to keep serialised data reasonably compact as communication
+ * between client and server goes in messages of less than 200 bytes each.
+ *
+ * Many serialisation functions can be created by a script; an exemplar Perl
+ * script is included. It is not hooked into the build and so must be run
+ * manually, but is expected to be replaced by a Python script in due course.
+ * Types that can have their functions created by script include plain old C
+ * data types (e.g. int), types typedef'd to those, and even structures that
+ * don't contain pointers.
+ */
+
+/** Return how much buffer space is needed by \c psasim_serialise_begin().
+ *
+ * \return                   The number of bytes needed in the buffer for
+ *                           \c psasim_serialise_begin()'s output.
+ */
+size_t psasim_serialise_begin_needs(void);
+
+/** Begin serialisation into a buffer.
+ *
+ *                           This must be the first serialisation API called
+ *                           on a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error (likely
+ *                           no space).
+ */
+int psasim_serialise_begin(uint8_t **pos, size_t *remaining);
+
+/** Begin deserialisation of a buffer.
+ *
+ *                           This must be the first deserialisation API called
+ *                           on a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_begin(uint8_t **pos, size_t *remaining);
+
+/** Return how much buffer space is needed by \c psasim_serialise_unsigned_int()
+ *  to serialise an `unsigned int`.
+ *
+ * \param value              The value that will be serialised into the buffer
+ *                           (needed in case some serialisations are value-
+ *                           dependent).
+ *
+ * \return                   The number of bytes needed in the buffer by
+ *                           \c psasim_serialise_unsigned_int() to serialise
+ *                           the given value.
+ */
+size_t psasim_serialise_unsigned_int_needs(unsigned int value);
+
+/** Serialise an `unsigned int` into a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              The value to serialise into the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_serialise_unsigned_int(uint8_t **pos,
+                                  size_t *remaining,
+                                  unsigned int value);
+
+/** Deserialise an `unsigned int` from a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              Pointer to an `unsigned int` to receive the value
+ *                           deserialised from the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_unsigned_int(uint8_t **pos,
+                                    size_t *remaining,
+                                    unsigned int *value);
+
+/** Return how much buffer space is needed by \c psasim_serialise_int()
+ *  to serialise an `int`.
+ *
+ * \param value              The value that will be serialised into the buffer
+ *                           (needed in case some serialisations are value-
+ *                           dependent).
+ *
+ * \return                   The number of bytes needed in the buffer by
+ *                           \c psasim_serialise_int() to serialise
+ *                           the given value.
+ */
+size_t psasim_serialise_int_needs(int value);
+
+/** Serialise an `int` into a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              The value to serialise into the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_serialise_int(uint8_t **pos,
+                         size_t *remaining,
+                         int value);
+
+/** Deserialise an `int` from a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              Pointer to an `int` to receive the value
+ *                           deserialised from the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_int(uint8_t **pos,
+                           size_t *remaining,
+                           int *value);
+
+/** Return how much buffer space is needed by \c psasim_serialise_size_t()
+ *  to serialise a `size_t`.
+ *
+ * \param value              The value that will be serialised into the buffer
+ *                           (needed in case some serialisations are value-
+ *                           dependent).
+ *
+ * \return                   The number of bytes needed in the buffer by
+ *                           \c psasim_serialise_size_t() to serialise
+ *                           the given value.
+ */
+size_t psasim_serialise_size_t_needs(size_t value);
+
+/** Serialise a `size_t` into a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              The value to serialise into the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_serialise_size_t(uint8_t **pos,
+                            size_t *remaining,
+                            size_t value);
+
+/** Deserialise a `size_t` from a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              Pointer to a `size_t` to receive the value
+ *                           deserialised from the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_size_t(uint8_t **pos,
+                              size_t *remaining,
+                              size_t *value);
+
+/** Return how much space is needed by \c psasim_serialise_buffer()
+ *  to serialise a buffer: a (`uint8_t *`, `size_t`) pair.
+ *
+ * \param buffer             Pointer to the buffer to be serialised
+ *                           (needed in case some serialisations are value-
+ *                           dependent).
+ * \param buffer_size        Number of bytes in the buffer to be serialised.
+ *
+ * \return                   The number of bytes needed in the buffer by
+ *                           \c psasim_serialise_buffer() to serialise
+ *                           the specified buffer.
+ */
+size_t psasim_serialise_buffer_needs(const uint8_t *buffer, size_t buffer_size);
+
+/** Serialise a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param buffer             Pointer to the buffer to be serialised.
+ * \param buffer_length      Number of bytes in the buffer to be serialised.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_serialise_buffer(uint8_t **pos, size_t *remaining,
+                            const uint8_t *buffer, size_t buffer_length);
+
+/** Deserialise a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the serialisation buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the serialisation buffer.
+ * \param buffer             Pointer to a `uint8_t *` to receive the address
+ *                           of a newly-allocated buffer, which the caller
+ *                           must `free()`.
+ * \param buffer_length      Pointer to a `size_t` to receive the number of
+ *                           bytes in the deserialised buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_buffer(uint8_t **pos, size_t *remaining,
+                              uint8_t **buffer, size_t *buffer_length);
+
+/** Deserialise a buffer returned from the server.
+ *
+ * When the client is deserialising a buffer returned from the server, it needs
+ * to use this function to deserialised the  returned buffer. It should use the
+ * usual \c psasim_serialise_buffer() function to serialise the outbound
+ * buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the serialisation buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the serialisation buffer.
+ * \param buffer             Pointer to a `uint8_t *` to receive the address
+ *                           of a newly-allocated buffer, which the caller
+ *                           must `free()`.
+ * \param buffer_length      Pointer to a `size_t` to receive the number of
+ *                           bytes in the deserialised buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_return_buffer(uint8_t **pos, size_t *remaining,
+                                     uint8_t *buffer, size_t buffer_length);
+
+/** Return how much buffer space is needed by \c psasim_serialise_psa_status_t()
+ *  to serialise a `psa_status_t`.
+ *
+ * \param value              The value that will be serialised into the buffer
+ *                           (needed in case some serialisations are value-
+ *                           dependent).
+ *
+ * \return                   The number of bytes needed in the buffer by
+ *                           \c psasim_serialise_psa_status_t() to serialise
+ *                           the given value.
+ */
+size_t psasim_serialise_psa_status_t_needs(psa_status_t value);
+
+/** Serialise a `psa_status_t` into a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              The value to serialise into the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_serialise_psa_status_t(uint8_t **pos,
+                                  size_t *remaining,
+                                  psa_status_t value);
+
+/** Deserialise a `psa_status_t` from a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              Pointer to a `psa_status_t` to receive the value
+ *                           deserialised from the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_psa_status_t(uint8_t **pos,
+                                    size_t *remaining,
+                                    psa_status_t *value);
+
+/** Return how much buffer space is needed by \c psasim_serialise_psa_algorithm_t()
+ *  to serialise a `psa_algorithm_t`.
+ *
+ * \param value              The value that will be serialised into the buffer
+ *                           (needed in case some serialisations are value-
+ *                           dependent).
+ *
+ * \return                   The number of bytes needed in the buffer by
+ *                           \c psasim_serialise_psa_algorithm_t() to serialise
+ *                           the given value.
+ */
+size_t psasim_serialise_psa_algorithm_t_needs(psa_algorithm_t value);
+
+/** Serialise a `psa_algorithm_t` into a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              The value to serialise into the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_serialise_psa_algorithm_t(uint8_t **pos,
+                                     size_t *remaining,
+                                     psa_algorithm_t value);
+
+/** Deserialise a `psa_algorithm_t` from a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              Pointer to a `psa_algorithm_t` to receive the value
+ *                           deserialised from the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_psa_algorithm_t(uint8_t **pos,
+                                       size_t *remaining,
+                                       psa_algorithm_t *value);
+
+/** Return how much buffer space is needed by \c psasim_serialise_psa_hash_operation_t()
+ *  to serialise a `psa_hash_operation_t`.
+ *
+ * \param value              The value that will be serialised into the buffer
+ *                           (needed in case some serialisations are value-
+ *                           dependent).
+ *
+ * \return                   The number of bytes needed in the buffer by
+ *                           \c psasim_serialise_psa_hash_operation_t() to serialise
+ *                           the given value.
+ */
+size_t psasim_serialise_psa_hash_operation_t_needs(psa_hash_operation_t value);
+
+/** Serialise a `psa_hash_operation_t` into a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              The value to serialise into the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_serialise_psa_hash_operation_t(uint8_t **pos,
+                                          size_t *remaining,
+                                          psa_hash_operation_t value);
+
+/** Deserialise a `psa_hash_operation_t` from a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param value              Pointer to a `psa_hash_operation_t` to receive the value
+ *                           deserialised from the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_psa_hash_operation_t(uint8_t **pos,
+                                            size_t *remaining,
+                                            psa_hash_operation_t *value);
diff --git a/tests/psa-client-server/psasim/src/psa_sim_serialise.pl b/tests/psa-client-server/psasim/src/psa_sim_serialise.pl
new file mode 100755
index 0000000..5161db1
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/psa_sim_serialise.pl
@@ -0,0 +1,747 @@
+#!/usr/bin/env perl
+#
+# psa_sim_serialise.pl - Sample Perl script to show how many serialisation
+#                        functions can be created by templated scripting.
+#
+# This is an example only, and is expected to be replaced by a Python script
+# for production use. It is not hooked into the build: it needs to be run
+# manually:
+#
+# perl psa_sim_serialise.pl h > psa_sim_serialise.h
+# perl psa_sim_serialise.pl c > psa_sim_serialise.c
+#
+# Copyright The Mbed TLS Contributors
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+#
+use strict;
+
+my $usage = "$0: usage: $0 c|h\n";
+my $which = lc(shift) || die($usage);
+die($usage) unless $which eq "c" || $which eq "h";
+
+# Most types are serialised as a fixed-size (per type) octet string, with
+# no type indication. This is acceptable as (a) this is for the test PSA crypto
+# simulator only, not production, and (b) these functions are called by
+# code that itself is written by script.
+#
+# We also want to keep serialised data reasonably compact as communication
+# between client and server goes in messages of less than 200 bytes each.
+#
+# This script is able to create serialisation functions for plain old C data
+# types (e.g. unsigned int), types typedef'd to those, and even structures
+# that don't contain pointers.
+#
+# Structures that contain pointers will need to have their serialisation and
+# deserialisation functions written manually (like those for the "buffer" type
+# are).
+#
+my @types = qw(unsigned-int int size_t
+               buffer
+               psa_status_t psa_algorithm_t
+               psa_hash_operation_t);
+grep(s/-/ /g, @types);
+
+# IS-A: Some data types are typedef'd; we serialise them as the other type
+my %isa = (
+    "psa_status_t" => "int",
+    "psa_algorithm_t" => "unsigned int",
+);
+
+if ($which eq "h") {
+
+    print h_header();
+
+    for my $type (@types) {
+        if ($type eq "buffer") {
+            print declare_buffer_functions();
+        } else {
+            print declare_needs($type);
+            print declare_serialise($type);
+            print declare_deserialise($type);
+        }
+    }
+
+} elsif ($which eq "c") {
+
+    print c_header();
+
+    for my $type (@types) {
+        if ($type eq "buffer") {
+            print define_buffer_functions();
+        } elsif (exists($isa{$type})) {
+            print define_needs_isa($type, $isa{$type});
+            print define_serialise_isa($type, $isa{$type});
+            print define_deserialise_isa($type, $isa{$type});
+        } else {
+            print define_needs($type);
+            print define_serialise($type);
+            print define_deserialise($type);
+        }
+    }
+
+} else {
+    die("internal error - shouldn't happen");
+}
+
+sub declare_needs
+{
+    my ($type) = @_;
+
+    my $an = ($type =~ /^[ui]/) ? "an" : "a";
+    my $type_d = $type;
+    $type_d =~ s/ /_/g;
+
+    return <<EOF;
+
+/** Return how much buffer space is needed by \\c psasim_serialise_$type_d()
+ *  to serialise $an `$type`.
+ *
+ * \\param value              The value that will be serialised into the buffer
+ *                           (needed in case some serialisations are value-
+ *                           dependent).
+ *
+ * \\return                   The number of bytes needed in the buffer by
+ *                           \\c psasim_serialise_$type_d() to serialise
+ *                           the given value.
+ */
+size_t psasim_serialise_${type_d}_needs($type value);
+EOF
+}
+
+sub declare_serialise
+{
+    my ($type) = @_;
+
+    my $an = ($type =~ /^[ui]/) ? "an" : "a";
+    my $type_d = $type;
+    $type_d =~ s/ /_/g;
+
+    return align_declaration(<<EOF);
+
+/** Serialise $an `$type` into a buffer.
+ *
+ * \\param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \\param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \\param value              The value to serialise into the buffer.
+ *
+ * \\return                   \\c 1 on success ("okay"), \\c 0 on error.
+ */
+int psasim_serialise_$type_d(uint8_t **pos,
+                             size_t *remaining,
+                             $type value);
+EOF
+}
+
+sub declare_deserialise
+{
+    my ($type) = @_;
+
+    my $an = ($type =~ /^[ui]/) ? "an" : "a";
+    my $type_d = $type;
+    $type_d =~ s/ /_/g;
+
+    return align_declaration(<<EOF);
+
+/** Deserialise $an `$type` from a buffer.
+ *
+ * \\param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \\param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \\param value              Pointer to $an `$type` to receive the value
+ *                           deserialised from the buffer.
+ *
+ * \\return                   \\c 1 on success ("okay"), \\c 0 on error.
+ */
+int psasim_deserialise_$type_d(uint8_t **pos,
+                               size_t *remaining,
+                               $type *value);
+EOF
+}
+
+sub declare_buffer_functions
+{
+    return <<'EOF';
+
+/** Return how much space is needed by \c psasim_serialise_buffer()
+ *  to serialise a buffer: a (`uint8_t *`, `size_t`) pair.
+ *
+ * \param buffer             Pointer to the buffer to be serialised
+ *                           (needed in case some serialisations are value-
+ *                           dependent).
+ * \param buffer_size        Number of bytes in the buffer to be serialised.
+ *
+ * \return                   The number of bytes needed in the buffer by
+ *                           \c psasim_serialise_buffer() to serialise
+ *                           the specified buffer.
+ */
+size_t psasim_serialise_buffer_needs(const uint8_t *buffer, size_t buffer_size);
+
+/** Serialise a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ * \param buffer             Pointer to the buffer to be serialised.
+ * \param buffer_length      Number of bytes in the buffer to be serialised.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_serialise_buffer(uint8_t **pos, size_t *remaining,
+                            const uint8_t *buffer, size_t buffer_length);
+
+/** Deserialise a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the serialisation buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the serialisation buffer.
+ * \param buffer             Pointer to a `uint8_t *` to receive the address
+ *                           of a newly-allocated buffer, which the caller
+ *                           must `free()`.
+ * \param buffer_length      Pointer to a `size_t` to receive the number of
+ *                           bytes in the deserialised buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_buffer(uint8_t **pos, size_t *remaining,
+                              uint8_t **buffer, size_t *buffer_length);
+
+/** Deserialise a buffer returned from the server.
+ *
+ * When the client is deserialising a buffer returned from the server, it needs
+ * to use this function to deserialised the  returned buffer. It should use the
+ * usual \c psasim_serialise_buffer() function to serialise the outbound
+ * buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the serialisation buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the serialisation buffer.
+ * \param buffer             Pointer to a `uint8_t *` to receive the address
+ *                           of a newly-allocated buffer, which the caller
+ *                           must `free()`.
+ * \param buffer_length      Pointer to a `size_t` to receive the number of
+ *                           bytes in the deserialised buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_return_buffer(uint8_t **pos, size_t *remaining,
+                                     uint8_t *buffer, size_t buffer_length);
+EOF
+}
+
+sub h_header
+{
+    return <<'EOF';
+/**
+ * \file psa_sim_serialise.h
+ *
+ * \brief Rough-and-ready serialisation and deserialisation for the PSA Crypto simulator
+ */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "psa/crypto.h"
+#include "psa/crypto_types.h"
+#include "psa/crypto_values.h"
+
+/* Basic idea:
+ *
+ * All arguments to a function will be serialised into a single buffer to
+ * be sent to the server with the PSA crypto function to be called.
+ *
+ * All returned data (the function's return value and any values returned
+ * via `out` parameters) will similarly be serialised into a buffer to be
+ * sent back to the client from the server.
+ *
+ * For each data type foo (e.g. int, size_t, psa_algorithm_t, but also "buffer"
+ * where "buffer" is a (uint8_t *, size_t) pair, we have a pair of functions,
+ * psasim_serialise_foo() and psasim_deserialise_foo().
+ *
+ * We also have psasim_serialise_foo_needs() functions, which return a
+ * size_t giving the number of bytes that serialising that instance of that
+ * type will need. This allows callers to size buffers for serialisation.
+ *
+ * Each serialised buffer starts with a version byte, bytes that indicate
+ * the size of basic C types, and four bytes that indicate the endianness
+ * (to avoid incompatibilities if we ever run this over a network - we are
+ * not aiming for universality, just for correctness and simplicity).
+ *
+ * Most types are serialised as a fixed-size (per type) octet string, with
+ * no type indication. This is acceptable as (a) this is for the test PSA crypto
+ * simulator only, not production, and (b) these functions are called by
+ * code that itself is written by script.
+ *
+ * We also want to keep serialised data reasonably compact as communication
+ * between client and server goes in messages of less than 200 bytes each.
+ *
+ * Many serialisation functions can be created by a script; an exemplar Perl
+ * script is included. It is not hooked into the build and so must be run
+ * manually, but is expected to be replaced by a Python script in due course.
+ * Types that can have their functions created by script include plain old C
+ * data types (e.g. int), types typedef'd to those, and even structures that
+ * don't contain pointers.
+ */
+
+/** Return how much buffer space is needed by \c psasim_serialise_begin().
+ *
+ * \return                   The number of bytes needed in the buffer for
+ *                           \c psasim_serialise_begin()'s output.
+ */
+size_t psasim_serialise_begin_needs(void);
+
+/** Begin serialisation into a buffer.
+ *
+ *                           This must be the first serialisation API called
+ *                           on a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error (likely
+ *                           no space).
+ */
+int psasim_serialise_begin(uint8_t **pos, size_t *remaining);
+
+/** Begin deserialisation of a buffer.
+ *
+ *                           This must be the first deserialisation API called
+ *                           on a buffer.
+ *
+ * \param pos[in,out]        Pointer to a `uint8_t *` holding current position
+ *                           in the buffer.
+ * \param remaining[in,out]  Pointer to a `size_t` holding number of bytes
+ *                           remaining in the buffer.
+ *
+ * \return                   \c 1 on success ("okay"), \c 0 on error.
+ */
+int psasim_deserialise_begin(uint8_t **pos, size_t *remaining);
+EOF
+}
+
+sub define_needs
+{
+    my ($type) = @_;
+
+    my $type_d = $type;
+    $type_d =~ s/ /_/g;
+
+    return <<EOF;
+
+size_t psasim_serialise_${type_d}_needs($type value)
+{
+    return sizeof(value);
+}
+EOF
+}
+
+sub define_needs_isa
+{
+    my ($type, $isa) = @_;
+
+    my $type_d = $type;
+    $type_d =~ s/ /_/g;
+
+    my $isa_d = $isa;
+    $isa_d =~ s/ /_/g;
+
+    return <<EOF;
+
+size_t psasim_serialise_${type_d}_needs($type value)
+{
+    return psasim_serialise_${isa_d}_needs(value);
+}
+EOF
+}
+
+sub define_serialise
+{
+    my ($type) = @_;
+
+    my $type_d = $type;
+    $type_d =~ s/ /_/g;
+
+    return align_signature(<<EOF);
+
+int psasim_serialise_$type_d(uint8_t **pos,
+                             size_t *remaining,
+                             $type value)
+{
+    if (*remaining < sizeof(value)) {
+        return 0;
+    }
+
+    memcpy(*pos, &value, sizeof(value));
+    *pos += sizeof(value);
+
+    return 1;
+}
+EOF
+}
+
+sub define_serialise_isa
+{
+    my ($type, $isa) = @_;
+
+    my $type_d = $type;
+    $type_d =~ s/ /_/g;
+
+    my $isa_d = $isa;
+    $isa_d =~ s/ /_/g;
+
+    return align_signature(<<EOF);
+
+int psasim_serialise_$type_d(uint8_t **pos,
+                             size_t *remaining,
+                             $type value)
+{
+    return psasim_serialise_$isa_d(pos, remaining, value);
+}
+EOF
+}
+
+sub define_deserialise
+{
+    my ($type) = @_;
+
+    my $type_d = $type;
+    $type_d =~ s/ /_/g;
+
+    return align_signature(<<EOF);
+
+int psasim_deserialise_$type_d(uint8_t **pos,
+                               size_t *remaining,
+                               $type *value)
+{
+    if (*remaining < sizeof(*value)) {
+        return 0;
+    }
+
+    memcpy(value, *pos, sizeof(*value));
+
+    *pos += sizeof(*value);
+    *remaining -= sizeof(*value);
+
+    return 1;
+}
+EOF
+}
+
+sub define_deserialise_isa
+{
+    my ($type, $isa) = @_;
+
+    my $type_d = $type;
+    $type_d =~ s/ /_/g;
+
+    my $isa_d = $isa;
+    $isa_d =~ s/ /_/g;
+
+    return align_signature(<<EOF);
+
+int psasim_deserialise_$type_d(uint8_t **pos,
+                              size_t *remaining,
+                              $type *value)
+{
+    return psasim_deserialise_$isa_d(pos, remaining, value);
+}
+EOF
+}
+
+sub define_buffer_functions
+{
+    return <<'EOF';
+
+size_t psasim_serialise_buffer_needs(const uint8_t *buffer, size_t buffer_size)
+{
+    (void) buffer;
+    return sizeof(buffer_size) + buffer_size;
+}
+
+int psasim_serialise_buffer(uint8_t **pos,
+                            size_t *remaining,
+                            const uint8_t *buffer,
+                            size_t buffer_length)
+{
+    if (*remaining < sizeof(buffer_length) + buffer_length) {
+        return 0;
+    }
+
+    memcpy(*pos, &buffer_length, sizeof(buffer_length));
+    *pos += sizeof(buffer_length);
+
+    if (buffer_length > 0) {    // To be able to serialise (NULL, 0)
+        memcpy(*pos, buffer, buffer_length);
+        *pos += buffer_length;
+    }
+
+    return 1;
+}
+
+int psasim_deserialise_buffer(uint8_t **pos,
+                              size_t *remaining,
+                              uint8_t **buffer,
+                              size_t *buffer_length)
+{
+    if (*remaining < sizeof(*buffer_length)) {
+        return 0;
+    }
+
+    memcpy(buffer_length, *pos, sizeof(*buffer_length));
+
+    *pos += sizeof(buffer_length);
+    *remaining -= sizeof(buffer_length);
+
+    if (*buffer_length == 0) {          // Deserialise (NULL, 0)
+        *buffer = NULL;
+        return 1;
+    }
+
+    if (*remaining < *buffer_length) {
+        return 0;
+    }
+
+    uint8_t *data = malloc(*buffer_length);
+    if (data == NULL) {
+        return 0;
+    }
+
+    memcpy(data, *pos, *buffer_length);
+    *pos += *buffer_length;
+    *remaining -= *buffer_length;
+
+    *buffer = data;
+
+    return 1;
+}
+
+/* When the client is deserialising a buffer returned from the server, it needs
+ * to use this function to deserialised the  returned buffer. It should use the
+ * usual \c psasim_serialise_buffer() function to serialise the outbound
+ * buffer. */
+int psasim_deserialise_return_buffer(uint8_t **pos,
+                                     size_t *remaining,
+                                     uint8_t *buffer,
+                                     size_t buffer_length)
+{
+    if (*remaining < sizeof(buffer_length)) {
+        return 0;
+    }
+
+    size_t length_check;
+
+    memcpy(&length_check, *pos, sizeof(buffer_length));
+
+    *pos += sizeof(buffer_length);
+    *remaining -= sizeof(buffer_length);
+
+    if (buffer_length != length_check) {        // Make sure we're sent back the same we sent to the server
+        return 0;
+    }
+
+    if (length_check == 0) {          // Deserialise (NULL, 0)
+        return 1;
+    }
+
+    if (*remaining < buffer_length) {
+        return 0;
+    }
+
+    memcpy(buffer, *pos, buffer_length);
+    *pos += buffer_length;
+    *remaining -= buffer_length;
+
+    return 1;
+}
+EOF
+}
+
+sub c_header
+{
+    return <<'EOF';
+/**
+ * \file psa_sim_serialise.c
+ *
+ * \brief Rough-and-ready serialisation and deserialisation for the PSA Crypto simulator
+ */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "psa_sim_serialise.h"
+#include <stdlib.h>
+#include <string.h>
+
+/* Basic idea:
+ *
+ * All arguments to a function will be serialised into a single buffer to
+ * be sent to the server with the PSA crypto function to be called.
+ *
+ * All returned data (the function's return value and any values returned
+ * via `out` parameters) will similarly be serialised into a buffer to be
+ * sent back to the client from the server.
+ *
+ * For each data type foo (e.g. int, size_t, psa_algorithm_t, but also "buffer"
+ * where "buffer" is a (uint8_t *, size_t) pair, we have a pair of functions,
+ * psasim_serialise_foo() and psasim_deserialise_foo().
+ *
+ * We also have psasim_serialise_foo_needs() functions, which return a
+ * size_t giving the number of bytes that serialising that instance of that
+ * type will need. This allows callers to size buffers for serialisation.
+ *
+ * Each serialised buffer starts with a version byte, bytes that indicate
+ * the size of basic C types, and four bytes that indicate the endianness
+ * (to avoid incompatibilities if we ever run this over a network - we are
+ * not aiming for universality, just for correctness and simplicity).
+ *
+ * Most types are serialised as a fixed-size (per type) octet string, with
+ * no type indication. This is acceptable as (a) this is for the test PSA crypto
+ * simulator only, not production, and (b) these functions are called by
+ * code that itself is written by script.
+ *
+ * We also want to keep serialised data reasonably compact as communication
+ * between client and server goes in messages of less than 200 bytes each.
+ *
+ * Many serialisation functions can be created by a script; an exemplar Perl
+ * script is included. It is not hooked into the build and so must be run
+ * manually, but is expected to be replaced by a Python script in due course.
+ * Types that can have their functions created by script include plain old C
+ * data types (e.g. int), types typedef'd to those, and even structures that
+ * don't contain pointers.
+ */
+
+size_t psasim_serialise_begin_needs(void)
+{
+    /* The serialisation buffer will
+     * start with a byte of 0 to indicate version 0,
+     * then have 1 byte each for length of int, long, void *,
+     * then have 4 bytes to indicate endianness. */
+    return 4 + sizeof(uint32_t);
+}
+
+int psasim_serialise_begin(uint8_t **pos, size_t *remaining)
+{
+    uint32_t endian = 0x1234;
+
+    if (*remaining < 4 + sizeof(endian)) {
+        return 0;
+    }
+
+    *(*pos)++ = 0;      /* version */
+    *(*pos)++ = (uint8_t) sizeof(int);
+    *(*pos)++ = (uint8_t) sizeof(long);
+    *(*pos)++ = (uint8_t) sizeof(void *);
+
+    memcpy(*pos, &endian, sizeof(endian));
+
+    *pos += sizeof(endian);
+
+    return 1;
+}
+
+int psasim_deserialise_begin(uint8_t **pos, size_t *remaining)
+{
+    uint8_t version = 255;
+    uint8_t int_size = 0;
+    uint8_t long_size = 0;
+    uint8_t ptr_size = 0;
+    uint32_t endian;
+
+    if (*remaining < 4 + sizeof(endian)) {
+        return 0;
+    }
+
+    memcpy(&version, (*pos)++, sizeof(version));
+    if (version != 0) {
+        return 0;
+    }
+
+    memcpy(&int_size, (*pos)++, sizeof(int_size));
+    if (int_size != sizeof(int)) {
+        return 0;
+    }
+
+    memcpy(&long_size, (*pos)++, sizeof(long_size));
+    if (long_size != sizeof(long)) {
+        return 0;
+    }
+
+    memcpy(&ptr_size, (*pos)++, sizeof(ptr_size));
+    if (ptr_size != sizeof(void *)) {
+        return 0;
+    }
+
+    *remaining -= 4;
+
+    memcpy(&endian, *pos, sizeof(endian));
+    if (endian != 0x1234) {
+        return 0;
+    }
+
+    *pos += sizeof(endian);
+    *remaining -= sizeof(endian);
+
+    return 1;
+}
+EOF
+}
+
+# Horrible way to align first, second and third lines of function signature to
+# appease uncrustify (these are the 2nd-4th lines of code, indices 1, 2 and 3)
+#
+sub align_signature
+{
+    my ($code) = @_;
+
+    my @code = split(/\n/, $code);
+
+    # Find where the ( is
+    my $idx = index($code[1], "(");
+    die("can't find (") if $idx < 0;
+
+    my $indent = " " x ($idx + 1);
+    $code[2] =~ s/^\s+/$indent/;
+    $code[3] =~ s/^\s+/$indent/;
+
+    return join("\n", @code) . "\n";
+}
+
+# Horrible way to align the function declaration to appease uncrustify
+#
+sub align_declaration
+{
+    my ($code) = @_;
+
+    my @code = split(/\n/, $code);
+
+    # Find out which lines we need to massage
+    my $i;
+    for ($i = 0; $i <= $#code; $i++) {
+        last if $code[$i] =~ /^int psasim_/;
+    }
+    die("can't find int psasim_") if $i > $#code;
+
+    # Find where the ( is
+    my $idx = index($code[$i], "(");
+    die("can't find (") if $idx < 0;
+
+    my $indent = " " x ($idx + 1);
+    $code[$i + 1] =~ s/^\s+/$indent/;
+    $code[$i + 2] =~ s/^\s+/$indent/;
+
+    return join("\n", @code) . "\n";
+}
diff --git a/tests/psa-client-server/psasim/src/server.c b/tests/psa-client-server/psasim/src/server.c
new file mode 100644
index 0000000..77ce269
--- /dev/null
+++ b/tests/psa-client-server/psasim/src/server.c
@@ -0,0 +1,114 @@
+/* psasim test server */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+
+/* Includes from psasim */
+#include "service.h"
+#include "error_ext.h"
+#include "util.h"
+#include "psa_manifest/manifest.h"
+#include "psa_functions_codes.h"
+
+/* Includes from mbedtls */
+#include "mbedtls/version.h"
+#include "psa/crypto.h"
+
+#ifdef DEBUG
+#define SERVER_PRINT(fmt, ...) \
+    PRINT("Server: " fmt, ##__VA_ARGS__)
+#else
+#define SERVER_PRINT(...)
+#endif
+
+#define BUF_SIZE 25
+
+static int kill_on_disconnect = 0; /* Kill the server on client disconnection. */
+
+void parse_input_args(int argc, char *argv[])
+{
+    int opt;
+
+    while ((opt = getopt(argc, argv, "k")) != -1) {
+        switch (opt) {
+            case 'k':
+                kill_on_disconnect = 1;
+                break;
+            default:
+                fprintf(stderr, "Usage: %s [-k]\n", argv[0]);
+                exit(EXIT_FAILURE);
+        }
+    }
+}
+
+int psa_server_main(int argc, char *argv[])
+{
+    psa_status_t ret = PSA_ERROR_PROGRAMMER_ERROR;
+    psa_msg_t msg = { -1 };
+    const int magic_num = 66;
+    int client_disconnected = 0;
+    char mbedtls_version[18];
+    extern psa_status_t psa_crypto_call(psa_msg_t msg);
+
+    mbedtls_version_get_string_full(mbedtls_version);
+    SERVER_PRINT("%s", mbedtls_version);
+
+    parse_input_args(argc, argv);
+    SERVER_PRINT("Starting");
+
+    while (!(kill_on_disconnect && client_disconnected)) {
+        psa_signal_t signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
+
+        if (signals > 0) {
+            SERVER_PRINT("Signals: 0x%08x", signals);
+        }
+
+        if (signals & PSA_CRYPTO_SIGNAL) {
+            if (PSA_SUCCESS == psa_get(PSA_CRYPTO_SIGNAL, &msg)) {
+                SERVER_PRINT("handle: %d - rhandle: %p", msg.handle, (int *) msg.rhandle);
+                switch (msg.type) {
+                    case PSA_IPC_CONNECT:
+                        SERVER_PRINT("Got a connection message");
+                        psa_set_rhandle(msg.handle, (void *) &magic_num);
+                        ret = PSA_SUCCESS;
+                        break;
+                    case PSA_IPC_DISCONNECT:
+                        SERVER_PRINT("Got a disconnection message");
+                        ret = PSA_SUCCESS;
+                        client_disconnected = 1;
+                        break;
+                    default:
+                        SERVER_PRINT("Got an IPC call of type %d", msg.type);
+                        ret = psa_crypto_call(msg);
+                        SERVER_PRINT("Internal function call returned %d", ret);
+
+                        if (msg.client_id > 0) {
+                            psa_notify(msg.client_id);
+                        } else {
+                            SERVER_PRINT("Client is non-secure, so won't notify");
+                        }
+                }
+
+                psa_reply(msg.handle, ret);
+            } else {
+                SERVER_PRINT("Failed to retrieve message");
+            }
+        } else if (SIGSTP_SIG & signals) {
+            SERVER_PRINT("Recieved SIGSTP signal. Gonna EOI it.");
+            psa_eoi(SIGSTP_SIG);
+        } else if (SIGINT_SIG & signals) {
+            SERVER_PRINT("Handling interrupt!");
+            SERVER_PRINT("Gracefully quitting");
+            psa_panic();
+        } else {
+            SERVER_PRINT("No signal asserted");
+        }
+    }
+
+    return 0;
+}
diff --git a/tests/psa-client-server/psasim/test/run_test.sh b/tests/psa-client-server/psasim/test/run_test.sh
new file mode 100755
index 0000000..31429c8
--- /dev/null
+++ b/tests/psa-client-server/psasim/test/run_test.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+# This is a simple bash script that tests psa_client/psa_server interaction.
+# This script is automatically executed when "make run" is launched by the
+# "psasim" root folder. The script can also be launched manually once
+# binary files are built (i.e. after "make test" is executed from the "psasim"
+# root folder).
+#
+# Copyright The Mbed TLS Contributors
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+set -e
+
+cd "$(dirname "$0")"
+
+function clean_run() {
+    rm -f psa_notify_*
+    pkill psa_partition || true
+    pkill psa_client || true
+    ipcs | grep q | awk '{ printf " -q " $2 }' | xargs ipcrm > /dev/null 2>&1 || true
+}
+
+# The server creates some local files when it starts up so we can wait for this
+# event as signal that the server is ready so that we can start client(s).
+function wait_for_server_startup() {
+    while [ ! -f ./psa_notify_* ]; do
+        sleep 0.1
+    done
+}
+
+clean_run
+
+./psa_partition -k &
+SERV_PID=$!
+wait_for_server_startup
+./psa_client
+wait $SERV_PID
diff --git a/tests/psa-client-server/psasim/tools/psa_autogen.py b/tests/psa-client-server/psasim/tools/psa_autogen.py
new file mode 100755
index 0000000..fbc9806
--- /dev/null
+++ b/tests/psa-client-server/psasim/tools/psa_autogen.py
@@ -0,0 +1,174 @@
+#!/usr/bin/env python3
+"""This hacky script generates a partition from a manifest file"""
+
+# Copyright The Mbed TLS Contributors
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+import json
+import os
+import sys
+from os import listdir
+
+if len(sys.argv) != 2:
+    print("Usage: psa_autogen <manifest_file>")
+    sys.exit(1)
+
+FILENAME = str(sys.argv[1])
+
+SCRIPT_PATH = os.path.dirname(__file__)
+GENERATED_H_PATH = os.path.join(SCRIPT_PATH, "..", "include", "psa_manifest")
+GENERATED_C_PATH = os.path.join(SCRIPT_PATH, "..", "src")
+
+MANIFEST_FILE = os.path.join(GENERATED_H_PATH, "manifest.h")
+PID_FILE = os.path.join(GENERATED_H_PATH, "pid.h")
+SID_FILE = os.path.join(GENERATED_H_PATH, "sid.h")
+
+with open(str(FILENAME), "r") as read_file:
+    data = json.load(read_file)
+    FILENAME = os.path.basename(FILENAME)
+    FILENAME = FILENAME.split('.')[0]
+    print("Base filename is " + str(FILENAME))
+
+    if str(data['psa_framework_version'] == "1.0"):
+        entry_point = str(data['entry_point'])
+        partition_name = str(data['name'])
+        services = data['services']
+        try:
+            irqs = data['irqs']
+        except KeyError:
+            irqs = []
+
+        try:
+            os.mkdir(GENERATED_H_PATH)
+            print("Generating psa_manifest directory")
+        except OSError:
+            print("PSA manifest directory already exists")
+
+        manifest_content = []
+        pids_content = []
+        sids_content = []
+
+        if len(services) > 28:
+           print ("Unsupported number of services")
+
+        count = 4 # For creating SID array
+        nsacl = "const int ns_allowed[32] = { "
+        policy = "const int strict_policy[32] = { "
+        qcode = "const char *psa_queues[] = { "
+        versions = "const uint32_t versions[32] = { "
+        queue_path = "psa_service_"
+        start = False
+
+        for x in range(0, count):
+            qcode = qcode + "\"\", "
+            nsacl = nsacl + "0, "
+            policy = policy + "0, "
+            versions = versions + "0, "
+
+        # Go through all the services to make sid.h and pid.h
+        for svc in services:
+            manifest_content.append("#define {}_SIGNAL    0x{:08x}".format(svc['signal'], 2**count))
+            sids_content.append("#define {}_SID    {}".format(svc['name'], svc['sid']))
+            qcode = qcode + "\"" + queue_path + str(int(svc['sid'], 16)) + "\","
+            ns_clients = svc['non_secure_clients']
+            print(str(svc))
+            if ns_clients == "true":
+                nsacl = nsacl + "1, "
+            else:
+                nsacl = nsacl + "0, "
+            try:
+                versions = versions + str(svc['minor_version']) + ", "
+            except KeyError:
+                versions = versions + "1, "
+
+            strict = 0
+            try:
+                if str(svc['minor_policy']).lower() == "strict":
+                    strict = 1
+                    policy = policy + "1, "
+                else:
+                    policy = policy + "0, "
+            except KeyError:
+                strict = 0
+                policy = policy + "0, "
+
+            count = count+1
+
+        sigcode = ""
+        handlercode = "void __sig_handler(int signo) {\n"
+        irqcount = count
+        for irq in irqs:
+            manifest_content.append("#define {}    0x{:08x}".format(irq['signal'], 2**irqcount))
+            sigcode = sigcode + "    signal({}, __sig_handler);\n".format(irq['source'])
+            handlercode = handlercode + \
+                          "    if (signo == {}) {{ raise_signal(0x{:08x}); }};\n".format(irq['source'], 2**irqcount)
+            irqcount = irqcount+1
+
+        handlercode = handlercode + "}\n"
+
+        while (count < 32):
+            qcode = qcode + "\"\", "
+            nsacl = nsacl + "0, "
+            versions = versions + "0, "
+            policy = policy + "0, "
+            count = count + 1
+
+        qcode = qcode + "};\n"
+        nsacl = nsacl + "};\n"
+        versions = versions + "};\n"
+        policy = policy + "};\n"
+
+        with open(MANIFEST_FILE, "wt") as output:
+            output.write("\n".join(manifest_content))
+        with open(SID_FILE, "wt") as output:
+            output.write("\n".join(sids_content))
+        with open(PID_FILE, "wt") as output:
+            output.write("\n".join(pids_content))
+
+        symbols = []
+
+        # Go through source files and look for the entrypoint
+        for root, directories, filenames in os.walk(GENERATED_C_PATH):
+            for filename in filenames:
+                if "psa_ff_bootstrap" in filename or filename == "psa_manifest":
+                    continue
+                try:
+                    fullpath = os.path.join(root,filename)
+                    with open(fullpath, encoding='utf-8') as currentFile:
+                        text = currentFile.read()
+                        if str(entry_point + "(") in text:
+                            symbols.append(filename)
+                except IOError:
+                    print("Couldn't open " + filename)
+                except UnicodeDecodeError:
+                    pass
+
+        print(str("Number of entrypoints detected: " + str(len(symbols))))
+        if len(symbols) < 1:
+            print("Couldn't find function " + entry_point)
+            sys.exit(1)
+        elif len(symbols) > 1:
+            print("Duplicate entrypoint symbol detected: " + str(symbols))
+            sys.exit(2)
+        else:
+            C_FILENAME = os.path.join(GENERATED_C_PATH, "psa_ff_bootstrap_" + partition_name + ".c")
+            c_content = []
+            c_content.append("#include <init.h>")
+            c_content.append("#include \"" + symbols[0] + "\"")
+            c_content.append("#include <signal.h>")
+            c_content.append(qcode)
+            c_content.append(nsacl)
+            c_content.append(policy)
+            c_content.append(versions)
+            c_content.append(handlercode)
+            c_content.append("int main(int argc, char *argv[]) {")
+            c_content.append("    (void) argc;")
+            c_content.append(sigcode)
+            c_content.append("    __init_psasim(psa_queues, 32, ns_allowed, versions,"
+                             "strict_policy);")
+            c_content.append("    " + entry_point + "(argc, argv);")
+            c_content.append("}")
+            with open(C_FILENAME, "wt") as output:
+                output.write("\n".join(c_content))
+
+            print("Success")
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 03303e0..0bd6d18 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -945,6 +945,39 @@
     make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -I../tests/include -I../tests -I../../tests -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_TEST_LIBTESTDRIVER1 $loc_accel_flags" LDFLAGS="-ltestdriver1 $ASAN_CFLAGS" "$@"
 }
 
+# $1: target which can be "client" or "server"
+helper_crypto_client_build() {
+    TARGET=$1
+    shift
+    TARGET_LIB=libpsa$TARGET
+
+    if [ "$TARGET" == "client" ]; then
+        scripts/config.py full
+        scripts/config.py unset MBEDTLS_PSA_CRYPTO_C
+        scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C
+        # Dynamic secure element support is a deprecated feature and it is not
+        # available when CRYPTO_C and PSA_CRYPTO_STORAGE_C are disabled.
+        scripts/config.py unset MBEDTLS_PSA_CRYPTO_SE_C
+        # Disable potentially problematic features
+        scripts/config.py unset MBEDTLS_X509_RSASSA_PSS_SUPPORT
+        scripts/config.py unset MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
+        scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+        scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+        scripts/config.py unset MBEDTLS_ECP_RESTARTABLE
+    else
+        scripts/config.py crypto_full
+        scripts/config.py unset MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS
+        scripts/config.py set MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
+    fi
+
+    make -C tests/psa-client-server/psasim/ CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" $TARGET_LIB "$@"
+
+    # cleanup() will restore some backed-up files which include $CONFIG_H and
+    # $CRYPTO_CONFIG_H. Built libraries were already copied to psasim at this
+    # point.
+    cleanup
+}
+
 ################################################################
 #### Configuration helpers
 ################################################################
@@ -1731,6 +1764,7 @@
         scripts/config.py -f $CRYPTO_CONFIG_H unset PSA_WANT_ALG_CTR
         scripts/config.py -f $CRYPTO_CONFIG_H unset PSA_WANT_ALG_ECB_NO_PADDING
         scripts/config.py -f $CRYPTO_CONFIG_H unset PSA_WANT_ALG_OFB
+        scripts/config.py -f $CRYPTO_CONFIG_H unset PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128
         scripts/config.py -f $CRYPTO_CONFIG_H unset PSA_WANT_ALG_STREAM_CIPHER
         scripts/config.py -f $CRYPTO_CONFIG_H unset PSA_WANT_KEY_TYPE_DES
     else
@@ -4015,6 +4049,7 @@
     scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_CBC_PKCS7
     scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_CMAC
     scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_CCM_STAR_NO_TAG
+    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128
 
     # Disable direct dependency on AES_C
     scripts/config.py unset MBEDTLS_NIST_KW_C
@@ -5215,9 +5250,11 @@
     make clean
 
     msg "build: make with MBEDTLS_PSA_CRYPTO_CONFIG_FILE + MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE" # ~40s
-    # In the user config, disable one feature, which will reflect on the
-    # mbedtls configuration so we can query it with query_compile_time_config.
+    # In the user config, disable one feature and its dependencies, which will
+    # reflect on the mbedtls configuration so we can query it with
+    # query_compile_time_config.
     echo '#undef PSA_WANT_ALG_CMAC' >psa_user_config.h
+    echo '#undef PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128' >> psa_user_config.h
     scripts/config.py unset MBEDTLS_CMAC_C
     make CFLAGS="-I '$PWD' -DMBEDTLS_PSA_CRYPTO_CONFIG_FILE='\"psa_test_config.h\"' -DMBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE='\"psa_user_config.h\"'"
     not programs/test/query_compile_time_config MBEDTLS_CMAC_C
@@ -6016,6 +6053,15 @@
     support_test_cmake_out_of_source
 }
 
+component_build_cmake_programs_no_testing () {
+    # Verify that the type of builds performed by oss-fuzz don't get accidentally broken
+    msg "build: cmake with -DENABLE_PROGRAMS=ON and -DENABLE_TESTING=OFF"
+    cmake -DENABLE_PROGRAMS=ON -DENABLE_TESTING=OFF .
+    make
+}
+support_build_cmake_programs_no_testing () {
+    support_test_cmake_out_of_source
+}
 
 component_build_zeroize_checks () {
     msg "build: check for obviously wrong calls to mbedtls_platform_zeroize()"
@@ -6098,12 +6144,56 @@
     # unittest writes out mundane stuff like number or tests run on stderr.
     # Our convention is to reserve stderr for actual errors, and write
     # harmless info on stdout so it can be suppress with --quiet.
-    ./tests/scripts/test_generate_test_code.py 2>&1
+    ./framework/scripts/test_generate_test_code.py 2>&1
 
     msg "unit test: translate_ciphers.py"
     python3 -m unittest tests/scripts/translate_ciphers.py 2>&1
 }
 
+component_test_psasim() {
+    msg "build library for client"
+
+    helper_crypto_client_build client
+
+    msg "build library for server"
+
+    scripts/config.py crypto
+
+    helper_crypto_client_build server
+
+    msg "build psasim"
+    make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS"
+
+    msg "test psasim"
+    tests/psa-client-server/psasim/test/run_test.sh
+
+    msg "build psasim to test psa_hash_compute"
+    # Delete the executable to ensure we build using the right MAIN
+    rm tests/psa-client-server/psasim/test/psa_client
+    # API under test: psa_hash_compute()
+    make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" MAIN="src/aut_psa_hash_compute.c"
+
+    msg "test psasim running psa_hash_compute"
+    tests/psa-client-server/psasim/test/run_test.sh
+
+    # Next APIs under test: psa_hash_*(). Just use the PSA hash example.
+    aut_psa_hash="../../../programs/psa/psa_hash.c"
+    if [ -f "tests/psa-client-server/psasim/$aut_psa_hash" ]; then
+
+        msg "build psasim to test all psa_hash_* APIs"
+        # Delete the executable to ensure we build using the right MAIN
+        rm tests/psa-client-server/psasim/test/psa_client
+        make -C tests/psa-client-server/psasim CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS" MAIN="$aut_psa_hash"
+
+        msg "test psasim running psa_hash sample"
+        tests/psa-client-server/psasim/test/run_test.sh
+    else
+        echo $aut_psa_hash NOT FOUND, so not running that test
+    fi
+
+    msg "clean psasim"
+    make -C tests/psa-client-server/psasim clean
+}
 
 ################################################################
 #### Termination
diff --git a/tests/scripts/analyze_outcomes.py b/tests/scripts/analyze_outcomes.py
index 5b4deb6..eb24694 100755
--- a/tests/scripts/analyze_outcomes.py
+++ b/tests/scripts/analyze_outcomes.py
@@ -85,6 +85,17 @@
 def analyze_coverage(results: Results, outcomes: Outcomes,
                      allow_list: typing.List[str], full_coverage: bool) -> None:
     """Check that all available test cases are executed at least once."""
+    # Make sure that the generated data files are present (and up-to-date).
+    # This allows analyze_outcomes.py to run correctly on a fresh Git
+    # checkout.
+    cp = subprocess.run(['make', 'generated_files'],
+                        cwd='tests',
+                        stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+                        check=False)
+    if cp.returncode != 0:
+        sys.stderr.write(cp.stdout.decode('utf-8'))
+        results.error("Failed \"make generated_files\" in tests. "
+                      "Coverage analysis may be incorrect.")
     available = check_test_cases.collect_available_test_cases()
     for suite_case in available:
         hit = any(suite_case in comp_outcomes.successes or
@@ -468,6 +479,12 @@
                 'bignum.generated', 'bignum.misc',
             ],
             'ignored_tests': {
+                'ssl-opt': [
+                    # DHE support in TLS 1.2 requires built-in MBEDTLS_DHM_C
+                    # (because it needs custom groups, which PSA does not
+                    # provide), even with MBEDTLS_USE_PSA_CRYPTO.
+                    re.compile(r'PSK callback:.*\bdhe-psk\b.*'),
+                ],
                 'test_suite_platform': [
                     # Incompatible with sanitizers (e.g. ASan). If the driver
                     # component uses a sanitizer but the reference component
diff --git a/tests/scripts/audit-validity-dates.py b/tests/scripts/audit-validity-dates.py
index 96b705a..44b083d 100755
--- a/tests/scripts/audit-validity-dates.py
+++ b/tests/scripts/audit-validity-dates.py
@@ -29,8 +29,8 @@
 from generate_test_code import FileWrapper
 
 import scripts_path # pylint: disable=unused-import
-from mbedtls_dev import build_tree
-from mbedtls_dev import logging_util
+from mbedtls_framework import build_tree
+from mbedtls_framework import logging_util
 
 def check_cryptography_version():
     match = re.match(r'^[0-9]+', cryptography.__version__)
diff --git a/tests/scripts/check-generated-files.sh b/tests/scripts/check-generated-files.sh
index 2f20026..e740f33 100755
--- a/tests/scripts/check-generated-files.sh
+++ b/tests/scripts/check-generated-files.sh
@@ -128,9 +128,10 @@
 
 # These checks are common to Mbed TLS and TF-PSA-Crypto
 check scripts/generate_psa_constants.py programs/psa/psa_constant_names_generated.c
-check tests/scripts/generate_bignum_tests.py $(tests/scripts/generate_bignum_tests.py --list)
-check tests/scripts/generate_ecp_tests.py $(tests/scripts/generate_ecp_tests.py --list)
-check tests/scripts/generate_psa_tests.py $(tests/scripts/generate_psa_tests.py --list)
+check framework/scripts/generate_bignum_tests.py $(framework/scripts/generate_bignum_tests.py --list)
+check framework/scripts/generate_ecp_tests.py $(framework/scripts/generate_ecp_tests.py --list)
+check framework/scripts/generate_psa_tests.py $(framework/scripts/generate_psa_tests.py --list)
+check framework/scripts/generate_test_keys.py tests/src/test_keys.h
 check scripts/generate_driver_wrappers.py $library_dir/psa_crypto_driver_wrappers.h $library_dir/psa_crypto_driver_wrappers_no_static.c
 
 # Additional checks for Mbed TLS only
@@ -139,6 +140,7 @@
     check scripts/generate_query_config.pl programs/test/query_config.c
     check scripts/generate_features.pl library/version_features.c
     check scripts/generate_ssl_debug_helpers.py library/ssl_debug_helpers_generated.c
+    check framework/scripts/generate_test_cert_macros.py tests/src/test_certs.h
     # generate_visualc_files enumerates source files (library/*.c). It doesn't
     # care about their content, but the files must exist. So it must run after
     # the step that creates or updates these files.
@@ -148,4 +150,4 @@
 # Generated files that are present in the repository even in the development
 # branch. (This is intended to be temporary, until the generator scripts are
 # fully reviewed and the build scripts support a generated header file.)
-check tests/scripts/generate_psa_wrappers.py tests/include/test/psa_test_wrappers.h tests/src/psa_test_wrappers.c
+check framework/scripts/generate_psa_wrappers.py tests/include/test/psa_test_wrappers.h tests/src/psa_test_wrappers.c
diff --git a/tests/scripts/check-python-files.sh b/tests/scripts/check-python-files.sh
index 51e8079..77102ba 100755
--- a/tests/scripts/check-python-files.sh
+++ b/tests/scripts/check-python-files.sh
@@ -31,14 +31,14 @@
 
 can_pylint () {
     # Pylint 1.5.2 from Ubuntu 16.04 is too old:
-    #     E: 34, 0: Unable to import 'mbedtls_dev' (import-error)
+    #     E: 34, 0: Unable to import 'mbedtls_framework' (import-error)
     # Pylint 1.8.3 from Ubuntu 18.04 passed on the first commit containing this line.
     check_version pylint 1.8.3
 }
 
 can_mypy () {
     # mypy 0.770 is too old:
-    #     tests/scripts/test_psa_constant_names.py:34: error: Cannot find implementation or library stub for module named 'mbedtls_dev'
+    #     tests/scripts/test_psa_constant_names.py:34: error: Cannot find implementation or library stub for module named 'mbedtls_framework'
     # mypy 0.780 from pip passed on the first commit containing this line.
     check_version mypy.version 0.780
 }
@@ -55,14 +55,14 @@
 fi
 
 echo 'Running pylint ...'
-$PYTHON -m pylint scripts/mbedtls_dev/*.py scripts/*.py tests/scripts/*.py || {
+$PYTHON -m pylint framework/scripts/*.py framework/scripts/mbedtls_framework/*.py scripts/*.py tests/scripts/*.py || {
     echo >&2 "pylint reported errors"
     ret=1
 }
 
 echo
 echo 'Running mypy ...'
-$PYTHON -m mypy scripts/*.py tests/scripts/*.py ||
+$PYTHON -m mypy framework/scripts/*.py framework/scripts/mbedtls_framework/*.py scripts/*.py tests/scripts/*.py ||
   ret=1
 
 exit $ret
diff --git a/tests/scripts/check_files.py b/tests/scripts/check_files.py
index d5a4b92..5e9ea7d 100755
--- a/tests/scripts/check_files.py
+++ b/tests/scripts/check_files.py
@@ -24,7 +24,7 @@
     pass
 
 import scripts_path # pylint: disable=unused-import
-from mbedtls_dev import build_tree
+from mbedtls_framework import build_tree
 
 
 class FileIssueTracker:
@@ -373,7 +373,7 @@
         r'3rdparty/(?!(p256-m)/.*)',
         # Documentation explaining the license may have accidental
         # false positives.
-        r'(ChangeLog|LICENSE|[-0-9A-Z_a-z]+\.md)\Z',
+        r'(ChangeLog|LICENSE|framework\/LICENSE|[-0-9A-Z_a-z]+\.md)\Z',
         # Files imported from TF-M, and not used except in test builds,
         # may be under a different license.
         r'configs/ext/crypto_config_profile_medium\.h\Z',
@@ -381,6 +381,7 @@
         r'configs/ext/README\.md\Z',
         # Third-party file.
         r'dco\.txt\Z',
+        r'framework\/dco\.txt\Z',
     ]
     path_exemptions = re.compile('|'.join(BINARY_FILE_PATH_RE_LIST +
                                           LICENSE_EXEMPTION_RE_LIST))
@@ -486,9 +487,17 @@
 
         These are the regular files commited into Git.
         """
+        bytes_output = subprocess.check_output(['git', '-C', 'framework',
+                                                'ls-files', '-z'])
+        bytes_framework_filepaths = bytes_output.split(b'\0')[:-1]
+        bytes_framework_filepaths = ["framework/".encode() + filepath
+                                     for filepath in bytes_framework_filepaths]
+
         bytes_output = subprocess.check_output(['git', 'ls-files', '-z'])
-        bytes_filepaths = bytes_output.split(b'\0')[:-1]
+        bytes_filepaths = bytes_output.split(b'\0')[:-1] + \
+                          bytes_framework_filepaths
         ascii_filepaths = map(lambda fp: fp.decode('ascii'), bytes_filepaths)
+
         # Filter out directories. Normally Git doesn't list directories
         # (it only knows about the files inside them), but there is
         # at least one case where 'git ls-files' includes a directory:
diff --git a/tests/scripts/check_names.py b/tests/scripts/check_names.py
index 9e8ed21..5128dc8 100755
--- a/tests/scripts/check_names.py
+++ b/tests/scripts/check_names.py
@@ -45,7 +45,7 @@
 import logging
 
 import scripts_path # pylint: disable=unused-import
-from mbedtls_dev import build_tree
+from mbedtls_framework import build_tree
 
 
 # Naming patterns to check against. These are defined outside the NameCheck
diff --git a/tests/scripts/generate_bignum_tests.py b/tests/scripts/generate_bignum_tests.py
deleted file mode 100755
index 8dbb6ed..0000000
--- a/tests/scripts/generate_bignum_tests.py
+++ /dev/null
@@ -1,187 +0,0 @@
-#!/usr/bin/env python3
-"""Generate test data for bignum functions.
-
-With no arguments, generate all test data. With non-option arguments,
-generate only the specified files.
-
-Class structure:
-
-Child classes of test_data_generation.BaseTarget (file targets) represent an output
-file. These indicate where test cases will be written to, for all subclasses of
-this target. Multiple file targets should not reuse a `target_basename`.
-
-Each subclass derived from a file target can either be:
-  - A concrete class, representing a test function, which generates test cases.
-  - An abstract class containing shared methods and attributes, not associated
-        with a test function. An example is BignumOperation, which provides
-        common features used for bignum binary operations.
-
-Both concrete and abstract subclasses can be derived from, to implement
-additional test cases (see BignumCmp and BignumCmpAbs for examples of deriving
-from abstract and concrete classes).
-
-
-Adding test case generation for a function:
-
-A subclass representing the test function should be added, deriving from a
-file target such as BignumTarget. This test class must set/implement the
-following:
-  - test_function: the function name from the associated .function file.
-  - test_name: a descriptive name or brief summary to refer to the test
-        function.
-  - arguments(): a method to generate the list of arguments required for the
-        test_function.
-  - generate_function_tests(): a method to generate TestCases for the function.
-        This should create instances of the class with required input data, and
-        call `.create_test_case()` to yield the TestCase.
-
-Additional details and other attributes/methods are given in the documentation
-of BaseTarget in test_data_generation.py.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-
-import sys
-
-from abc import ABCMeta
-from typing import List
-
-import scripts_path # pylint: disable=unused-import
-from mbedtls_dev import test_data_generation
-from mbedtls_dev import bignum_common
-# Import modules containing additional test classes
-# Test function classes in these modules will be registered by
-# the framework
-from mbedtls_dev import bignum_core, bignum_mod_raw, bignum_mod # pylint: disable=unused-import
-
-class BignumTarget(test_data_generation.BaseTarget):
-    #pylint: disable=too-few-public-methods
-    """Target for bignum (legacy) test case generation."""
-    target_basename = 'test_suite_bignum.generated'
-
-
-class BignumOperation(bignum_common.OperationCommon, BignumTarget,
-                      metaclass=ABCMeta):
-    #pylint: disable=abstract-method
-    """Common features for bignum operations in legacy tests."""
-    unique_combinations_only = True
-    input_values = [
-        "", "0", "-", "-0",
-        "7b", "-7b",
-        "0000000000000000123", "-0000000000000000123",
-        "1230000000000000000", "-1230000000000000000"
-    ]
-
-    def description_suffix(self) -> str:
-        #pylint: disable=no-self-use # derived classes need self
-        """Text to add at the end of the test case description."""
-        return ""
-
-    def description(self) -> str:
-        """Generate a description for the test case.
-
-        If not set, case_description uses the form A `symbol` B, where symbol
-        is used to represent the operation. Descriptions of each value are
-        generated to provide some context to the test case.
-        """
-        if not self.case_description:
-            self.case_description = "{} {} {}".format(
-                self.value_description(self.arg_a),
-                self.symbol,
-                self.value_description(self.arg_b)
-            )
-            description_suffix = self.description_suffix()
-            if description_suffix:
-                self.case_description += " " + description_suffix
-        return super().description()
-
-    @staticmethod
-    def value_description(val) -> str:
-        """Generate a description of the argument val.
-
-        This produces a simple description of the value, which is used in test
-        case naming to add context.
-        """
-        if val == "":
-            return "0 (null)"
-        if val == "-":
-            return "negative 0 (null)"
-        if val == "0":
-            return "0 (1 limb)"
-
-        if val[0] == "-":
-            tmp = "negative"
-            val = val[1:]
-        else:
-            tmp = "positive"
-        if val[0] == "0":
-            tmp += " with leading zero limb"
-        elif len(val) > 10:
-            tmp = "large " + tmp
-        return tmp
-
-
-class BignumCmp(BignumOperation):
-    """Test cases for bignum value comparison."""
-    count = 0
-    test_function = "mpi_cmp_mpi"
-    test_name = "MPI compare"
-    input_cases = [
-        ("-2", "-3"),
-        ("-2", "-2"),
-        ("2b4", "2b5"),
-        ("2b5", "2b6")
-        ]
-
-    def __init__(self, val_a, val_b) -> None:
-        super().__init__(val_a, val_b)
-        self._result = int(self.int_a > self.int_b) - int(self.int_a < self.int_b)
-        self.symbol = ["<", "==", ">"][self._result + 1]
-
-    def result(self) -> List[str]:
-        return [str(self._result)]
-
-
-class BignumCmpAbs(BignumCmp):
-    """Test cases for absolute bignum value comparison."""
-    count = 0
-    test_function = "mpi_cmp_abs"
-    test_name = "MPI compare (abs)"
-
-    def __init__(self, val_a, val_b) -> None:
-        super().__init__(val_a.strip("-"), val_b.strip("-"))
-
-
-class BignumAdd(BignumOperation):
-    """Test cases for bignum value addition."""
-    count = 0
-    symbol = "+"
-    test_function = "mpi_add_mpi"
-    test_name = "MPI add"
-    input_cases = bignum_common.combination_pairs(
-        [
-            "1c67967269c6", "9cde3",
-            "-1c67967269c6", "-9cde3",
-        ]
-    )
-
-    def __init__(self, val_a: str, val_b: str) -> None:
-        super().__init__(val_a, val_b)
-        self._result = self.int_a + self.int_b
-
-    def description_suffix(self) -> str:
-        if (self.int_a >= 0 and self.int_b >= 0):
-            return "" # obviously positive result or 0
-        if (self.int_a <= 0 and self.int_b <= 0):
-            return "" # obviously negative result or 0
-        # The sign of the result is not obvious, so indicate it
-        return ", result{}0".format('>' if self._result > 0 else
-                                    '<' if self._result < 0 else '=')
-
-    def result(self) -> List[str]:
-        return [bignum_common.quote_str("{:x}".format(self._result))]
-
-if __name__ == '__main__':
-    # Use the section of the docstring relevant to the CLI as description
-    test_data_generation.main(sys.argv[1:], "\n".join(__doc__.splitlines()[:4]))
diff --git a/tests/scripts/generate_ecp_tests.py b/tests/scripts/generate_ecp_tests.py
deleted file mode 100755
index df1e469..0000000
--- a/tests/scripts/generate_ecp_tests.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env python3
-"""Generate test data for ecp functions.
-
-The command line usage, class structure and available methods are the same
-as in generate_bignum_tests.py.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-
-import sys
-
-import scripts_path # pylint: disable=unused-import
-from mbedtls_dev import test_data_generation
-# Import modules containing additional test classes
-# Test function classes in these modules will be registered by
-# the framework
-from mbedtls_dev import ecp # pylint: disable=unused-import
-
-if __name__ == '__main__':
-    # Use the section of the docstring relevant to the CLI as description
-    test_data_generation.main(sys.argv[1:], "\n".join(__doc__.splitlines()[:4]))
diff --git a/tests/scripts/generate_pkcs7_tests.py b/tests/scripts/generate_pkcs7_tests.py
deleted file mode 100755
index 0e484b0..0000000
--- a/tests/scripts/generate_pkcs7_tests.py
+++ /dev/null
@@ -1,183 +0,0 @@
-#!/usr/bin/env python3
-#
-#  Copyright The Mbed TLS Contributors
-#  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-#
-
-"""
-Make fuzz like testing for pkcs7 tests
-Given a valid DER pkcs7 file add tests to the test_suite_pkcs7.data file
- - It is expected that the pkcs7_asn1_fail( data_t *pkcs7_buf )
-    function is defined in test_suite_pkcs7.function
- - This is not meant to be portable code, if anything it is meant to serve as
-   documentation for showing how those ugly tests in test_suite_pkcs7.data were created
-"""
-
-
-import sys
-from os.path import exists
-
-PKCS7_TEST_FILE = "../suites/test_suite_pkcs7.data"
-
-class Test: # pylint: disable=too-few-public-methods
-    """
-    A instance of a test in test_suite_pkcs7.data
-    """
-    def __init__(self, name, depends, func_call):
-        self.name = name
-        self.depends = depends
-        self.func_call = func_call
-
-    # pylint: disable=no-self-use
-    def to_string(self):
-        return "\n" + self.name + "\n" + self.depends + "\n" + self.func_call + "\n"
-
-class TestData:
-    """
-    Take in test_suite_pkcs7.data file.
-    Allow for new tests to be added.
-    """
-    mandatory_dep = "MBEDTLS_MD_CAN_SHA256"
-    test_name = "PKCS7 Parse Failure Invalid ASN1"
-    test_function = "pkcs7_asn1_fail:"
-    def __init__(self, file_name):
-        self.file_name = file_name
-        self.last_test_num, self.old_tests = self.read_test_file(file_name)
-        self.new_tests = []
-
-    # pylint: disable=no-self-use
-    def read_test_file(self, file):
-        """
-        Parse the test_suite_pkcs7.data file.
-        """
-        tests = []
-        if not exists(file):
-            print(file + " Does not exist")
-            sys.exit()
-        with open(file, "r", encoding='UTF-8') as fp:
-            data = fp.read()
-        lines = [line.strip() for line in data.split('\n') if len(line.strip()) > 1]
-        i = 0
-        while i < len(lines):
-            if "depends" in lines[i+1]:
-                tests.append(Test(lines[i], lines[i+1], lines[i+2]))
-                i += 3
-            else:
-                tests.append(Test(lines[i], None, lines[i+1]))
-                i += 2
-        latest_test_num = float(tests[-1].name.split('#')[1])
-        return latest_test_num, tests
-
-    def add(self, name, func_call):
-        self.last_test_num += 1
-        self.new_tests.append(Test(self.test_name + ": " + name +  " #" + \
-                str(self.last_test_num), "depends_on:" + self.mandatory_dep, \
-                self.test_function + '"' + func_call + '"'))
-
-    def write_changes(self):
-        with open(self.file_name, 'a', encoding='UTF-8') as fw:
-            fw.write("\n")
-            for t in self.new_tests:
-                fw.write(t.to_string())
-
-
-def asn1_mutate(data):
-    """
-    We have been given an asn1 structure representing a pkcs7.
-    We want to return an array of slightly modified versions of this data
-    they should be modified in a way which makes the structure invalid
-
-    We know that asn1 structures are:
-    |---1 byte showing data type---|----byte(s) for length of data---|---data content--|
-    We know that some data types can contain other data types.
-    Return a dictionary of reasons and mutated data types.
-    """
-
-    # off the bat just add bytes to start and end of the buffer
-    mutations = []
-    reasons = []
-    mutations.append(["00"] + data)
-    reasons.append("Add null byte to start")
-    mutations.append(data + ["00"])
-    reasons.append("Add null byte to end")
-    # for every asn1 entry we should attempt to:
-    #    - change the data type tag
-    #    - make the length longer than actual
-    #    - make the length shorter than actual
-    i = 0
-    while i < len(data):
-        tag_i = i
-        leng_i = tag_i + 1
-        data_i = leng_i + 1 + (int(data[leng_i][1], 16) if data[leng_i][0] == '8' else 0)
-        if data[leng_i][0] == '8':
-            length = int(''.join(data[leng_i + 1: data_i]), 16)
-        else:
-            length = int(data[leng_i], 16)
-
-        tag = data[tag_i]
-        print("Looking at ans1: offset " + str(i) + " tag = " + tag + \
-                ", length = " + str(length)+ ":")
-        print(''.join(data[data_i:data_i+length]))
-        # change tag to something else
-        if tag == "02":
-            # turn integers into octet strings
-            new_tag = "04"
-        else:
-            # turn everything else into an integer
-            new_tag = "02"
-        mutations.append(data[:tag_i] + [new_tag] + data[leng_i:])
-        reasons.append("Change tag " + tag + " to " + new_tag)
-
-        # change lengths to too big
-        # skip any edge cases which would cause carry over
-        if int(data[data_i - 1], 16) < 255:
-            new_length = str(hex(int(data[data_i - 1], 16) + 1))[2:]
-            if len(new_length) == 1:
-                new_length = "0"+new_length
-            mutations.append(data[:data_i -1] + [new_length] + data[data_i:])
-            reasons.append("Change length from " + str(length) + " to " \
-                    + str(length + 1))
-            # we can add another test here for tags that contain other tags \
-            # where they have more data than there containing tags account for
-            if tag in ["30", "a0", "31"]:
-                mutations.append(data[:data_i -1] + [new_length] + \
-                        data[data_i:data_i + length] + ["00"] + \
-                        data[data_i + length:])
-                reasons.append("Change contents of tag " + tag + " to contain \
-                        one unaccounted extra byte")
-        # change lengths to too small
-        if int(data[data_i - 1], 16) > 0:
-            new_length = str(hex(int(data[data_i - 1], 16) - 1))[2:]
-            if len(new_length) == 1:
-                new_length = "0"+new_length
-            mutations.append(data[:data_i -1] + [new_length] + data[data_i:])
-            reasons.append("Change length from " + str(length) + " to " + str(length - 1))
-
-        # some tag types contain other tag types so we should iterate into the data
-        if tag in ["30", "a0", "31"]:
-            i = data_i
-        else:
-            i = data_i + length
-
-    return list(zip(reasons, mutations))
-
-if __name__ == "__main__":
-    if len(sys.argv) < 2:
-        print("USAGE: " + sys.argv[0] + " <pkcs7_der_file>")
-        sys.exit()
-
-    DATA_FILE = sys.argv[1]
-    TEST_DATA = TestData(PKCS7_TEST_FILE)
-    with open(DATA_FILE, 'rb') as f:
-        DATA_STR = f.read().hex()
-    # make data an array of byte strings eg ['de','ad','be','ef']
-    HEX_DATA = list(map(''.join, [[DATA_STR[i], DATA_STR[i+1]] for i in range(0, len(DATA_STR), \
-            2)]))
-    # returns tuples of test_names and modified data buffers
-    MUT_ARR = asn1_mutate(HEX_DATA)
-
-    print("made " + str(len(MUT_ARR)) + " new tests")
-    for new_test in MUT_ARR:
-        TEST_DATA.add(new_test[0], ''.join(new_test[1]))
-
-    TEST_DATA.write_changes()
diff --git a/tests/scripts/generate_psa_tests.py b/tests/scripts/generate_psa_tests.py
deleted file mode 100755
index fd278f8..0000000
--- a/tests/scripts/generate_psa_tests.py
+++ /dev/null
@@ -1,850 +0,0 @@
-#!/usr/bin/env python3
-"""Generate test data for PSA cryptographic mechanisms.
-
-With no arguments, generate all test data. With non-option arguments,
-generate only the specified files.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-
-import enum
-import re
-import sys
-from typing import Callable, Dict, FrozenSet, Iterable, Iterator, List, Optional
-
-import scripts_path # pylint: disable=unused-import
-from mbedtls_dev import crypto_data_tests
-from mbedtls_dev import crypto_knowledge
-from mbedtls_dev import macro_collector #pylint: disable=unused-import
-from mbedtls_dev import psa_information
-from mbedtls_dev import psa_storage
-from mbedtls_dev import test_case
-from mbedtls_dev import test_data_generation
-
-
-
-def test_case_for_key_type_not_supported(
-        verb: str, key_type: str, bits: int,
-        dependencies: List[str],
-        *args: str,
-        param_descr: str = ''
-) -> test_case.TestCase:
-    """Return one test case exercising a key creation method
-    for an unsupported key type or size.
-    """
-    psa_information.hack_dependencies_not_implemented(dependencies)
-    tc = test_case.TestCase()
-    short_key_type = crypto_knowledge.short_expression(key_type)
-    adverb = 'not' if dependencies else 'never'
-    if param_descr:
-        adverb = param_descr + ' ' + adverb
-    tc.set_description('PSA {} {} {}-bit {} supported'
-                       .format(verb, short_key_type, bits, adverb))
-    tc.set_dependencies(dependencies)
-    tc.set_function(verb + '_not_supported')
-    tc.set_arguments([key_type] + list(args))
-    return tc
-
-class KeyTypeNotSupported:
-    """Generate test cases for when a key type is not supported."""
-
-    def __init__(self, info: psa_information.Information) -> None:
-        self.constructors = info.constructors
-
-    ALWAYS_SUPPORTED = frozenset([
-        'PSA_KEY_TYPE_DERIVE',
-        'PSA_KEY_TYPE_PASSWORD',
-        'PSA_KEY_TYPE_PASSWORD_HASH',
-        'PSA_KEY_TYPE_RAW_DATA',
-        'PSA_KEY_TYPE_HMAC'
-    ])
-    def test_cases_for_key_type_not_supported(
-            self,
-            kt: crypto_knowledge.KeyType,
-            param: Optional[int] = None,
-            param_descr: str = '',
-    ) -> Iterator[test_case.TestCase]:
-        """Return test cases exercising key creation when the given type is unsupported.
-
-        If param is present and not None, emit test cases conditioned on this
-        parameter not being supported. If it is absent or None, emit test cases
-        conditioned on the base type not being supported.
-        """
-        if kt.name in self.ALWAYS_SUPPORTED:
-            # Don't generate test cases for key types that are always supported.
-            # They would be skipped in all configurations, which is noise.
-            return
-        import_dependencies = [('!' if param is None else '') +
-                               psa_information.psa_want_symbol(kt.name)]
-        if kt.params is not None:
-            import_dependencies += [('!' if param == i else '') +
-                                    psa_information.psa_want_symbol(sym)
-                                    for i, sym in enumerate(kt.params)]
-        if kt.name.endswith('_PUBLIC_KEY'):
-            generate_dependencies = []
-        else:
-            generate_dependencies = \
-                psa_information.fix_key_pair_dependencies(import_dependencies, 'GENERATE')
-            import_dependencies = \
-                psa_information.fix_key_pair_dependencies(import_dependencies, 'BASIC')
-        for bits in kt.sizes_to_test():
-            yield test_case_for_key_type_not_supported(
-                'import', kt.expression, bits,
-                psa_information.finish_family_dependencies(import_dependencies, bits),
-                test_case.hex_string(kt.key_material(bits)),
-                param_descr=param_descr,
-            )
-            if not generate_dependencies and param is not None:
-                # If generation is impossible for this key type, rather than
-                # supported or not depending on implementation capabilities,
-                # only generate the test case once.
-                continue
-                # For public key we expect that key generation fails with
-                # INVALID_ARGUMENT. It is handled by KeyGenerate class.
-            if not kt.is_public():
-                yield test_case_for_key_type_not_supported(
-                    'generate', kt.expression, bits,
-                    psa_information.finish_family_dependencies(generate_dependencies, bits),
-                    str(bits),
-                    param_descr=param_descr,
-                )
-            # To be added: derive
-
-    ECC_KEY_TYPES = ('PSA_KEY_TYPE_ECC_KEY_PAIR',
-                     'PSA_KEY_TYPE_ECC_PUBLIC_KEY')
-    DH_KEY_TYPES = ('PSA_KEY_TYPE_DH_KEY_PAIR',
-                    'PSA_KEY_TYPE_DH_PUBLIC_KEY')
-
-    def test_cases_for_not_supported(self) -> Iterator[test_case.TestCase]:
-        """Generate test cases that exercise the creation of keys of unsupported types."""
-        for key_type in sorted(self.constructors.key_types):
-            if key_type in self.ECC_KEY_TYPES:
-                continue
-            if key_type in self.DH_KEY_TYPES:
-                continue
-            kt = crypto_knowledge.KeyType(key_type)
-            yield from self.test_cases_for_key_type_not_supported(kt)
-        for curve_family in sorted(self.constructors.ecc_curves):
-            for constr in self.ECC_KEY_TYPES:
-                kt = crypto_knowledge.KeyType(constr, [curve_family])
-                yield from self.test_cases_for_key_type_not_supported(
-                    kt, param_descr='type')
-                yield from self.test_cases_for_key_type_not_supported(
-                    kt, 0, param_descr='curve')
-        for dh_family in sorted(self.constructors.dh_groups):
-            for constr in self.DH_KEY_TYPES:
-                kt = crypto_knowledge.KeyType(constr, [dh_family])
-                yield from self.test_cases_for_key_type_not_supported(
-                    kt, param_descr='type')
-                yield from self.test_cases_for_key_type_not_supported(
-                    kt, 0, param_descr='group')
-
-def test_case_for_key_generation(
-        key_type: str, bits: int,
-        dependencies: List[str],
-        *args: str,
-        result: str = ''
-) -> test_case.TestCase:
-    """Return one test case exercising a key generation.
-    """
-    psa_information.hack_dependencies_not_implemented(dependencies)
-    tc = test_case.TestCase()
-    short_key_type = crypto_knowledge.short_expression(key_type)
-    tc.set_description('PSA {} {}-bit'
-                       .format(short_key_type, bits))
-    tc.set_dependencies(dependencies)
-    tc.set_function('generate_key')
-    tc.set_arguments([key_type] + list(args) + [result])
-
-    return tc
-
-class KeyGenerate:
-    """Generate positive and negative (invalid argument) test cases for key generation."""
-
-    def __init__(self, info: psa_information.Information) -> None:
-        self.constructors = info.constructors
-
-    ECC_KEY_TYPES = ('PSA_KEY_TYPE_ECC_KEY_PAIR',
-                     'PSA_KEY_TYPE_ECC_PUBLIC_KEY')
-    DH_KEY_TYPES = ('PSA_KEY_TYPE_DH_KEY_PAIR',
-                    'PSA_KEY_TYPE_DH_PUBLIC_KEY')
-
-    @staticmethod
-    def test_cases_for_key_type_key_generation(
-            kt: crypto_knowledge.KeyType
-    ) -> Iterator[test_case.TestCase]:
-        """Return test cases exercising key generation.
-
-        All key types can be generated except for public keys. For public key
-        PSA_ERROR_INVALID_ARGUMENT status is expected.
-        """
-        result = 'PSA_SUCCESS'
-
-        import_dependencies = [psa_information.psa_want_symbol(kt.name)]
-        if kt.params is not None:
-            import_dependencies += [psa_information.psa_want_symbol(sym)
-                                    for i, sym in enumerate(kt.params)]
-        if kt.name.endswith('_PUBLIC_KEY'):
-            # The library checks whether the key type is a public key generically,
-            # before it reaches a point where it needs support for the specific key
-            # type, so it returns INVALID_ARGUMENT for unsupported public key types.
-            generate_dependencies = []
-            result = 'PSA_ERROR_INVALID_ARGUMENT'
-        else:
-            generate_dependencies = \
-                psa_information.fix_key_pair_dependencies(import_dependencies, 'GENERATE')
-        for bits in kt.sizes_to_test():
-            if kt.name == 'PSA_KEY_TYPE_RSA_KEY_PAIR':
-                size_dependency = "PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS <= " +  str(bits)
-                test_dependencies = generate_dependencies + [size_dependency]
-            else:
-                test_dependencies = generate_dependencies
-            yield test_case_for_key_generation(
-                kt.expression, bits,
-                psa_information.finish_family_dependencies(test_dependencies, bits),
-                str(bits),
-                result
-            )
-
-    def test_cases_for_key_generation(self) -> Iterator[test_case.TestCase]:
-        """Generate test cases that exercise the generation of keys."""
-        for key_type in sorted(self.constructors.key_types):
-            if key_type in self.ECC_KEY_TYPES:
-                continue
-            if key_type in self.DH_KEY_TYPES:
-                continue
-            kt = crypto_knowledge.KeyType(key_type)
-            yield from self.test_cases_for_key_type_key_generation(kt)
-        for curve_family in sorted(self.constructors.ecc_curves):
-            for constr in self.ECC_KEY_TYPES:
-                kt = crypto_knowledge.KeyType(constr, [curve_family])
-                yield from self.test_cases_for_key_type_key_generation(kt)
-        for dh_family in sorted(self.constructors.dh_groups):
-            for constr in self.DH_KEY_TYPES:
-                kt = crypto_knowledge.KeyType(constr, [dh_family])
-                yield from self.test_cases_for_key_type_key_generation(kt)
-
-class OpFail:
-    """Generate test cases for operations that must fail."""
-    #pylint: disable=too-few-public-methods
-
-    class Reason(enum.Enum):
-        NOT_SUPPORTED = 0
-        INVALID = 1
-        INCOMPATIBLE = 2
-        PUBLIC = 3
-
-    def __init__(self, info: psa_information.Information) -> None:
-        self.constructors = info.constructors
-        key_type_expressions = self.constructors.generate_expressions(
-            sorted(self.constructors.key_types)
-        )
-        self.key_types = [crypto_knowledge.KeyType(kt_expr)
-                          for kt_expr in key_type_expressions]
-
-    def make_test_case(
-            self,
-            alg: crypto_knowledge.Algorithm,
-            category: crypto_knowledge.AlgorithmCategory,
-            reason: 'Reason',
-            kt: Optional[crypto_knowledge.KeyType] = None,
-            not_deps: FrozenSet[str] = frozenset(),
-    ) -> test_case.TestCase:
-        """Construct a failure test case for a one-key or keyless operation."""
-        #pylint: disable=too-many-arguments,too-many-locals
-        tc = test_case.TestCase()
-        pretty_alg = alg.short_expression()
-        if reason == self.Reason.NOT_SUPPORTED:
-            short_deps = [re.sub(r'PSA_WANT_ALG_', r'', dep)
-                          for dep in not_deps]
-            pretty_reason = '!' + '&'.join(sorted(short_deps))
-        else:
-            pretty_reason = reason.name.lower()
-        if kt:
-            key_type = kt.expression
-            pretty_type = kt.short_expression()
-        else:
-            key_type = ''
-            pretty_type = ''
-        tc.set_description('PSA {} {}: {}{}'
-                           .format(category.name.lower(),
-                                   pretty_alg,
-                                   pretty_reason,
-                                   ' with ' + pretty_type if pretty_type else ''))
-        dependencies = psa_information.automatic_dependencies(alg.base_expression, key_type)
-        dependencies = psa_information.fix_key_pair_dependencies(dependencies, 'BASIC')
-        for i, dep in enumerate(dependencies):
-            if dep in not_deps:
-                dependencies[i] = '!' + dep
-        tc.set_dependencies(dependencies)
-        tc.set_function(category.name.lower() + '_fail')
-        arguments = [] # type: List[str]
-        if kt:
-            key_material = kt.key_material(kt.sizes_to_test()[0])
-            arguments += [key_type, test_case.hex_string(key_material)]
-        arguments.append(alg.expression)
-        if category.is_asymmetric():
-            arguments.append('1' if reason == self.Reason.PUBLIC else '0')
-        error = ('NOT_SUPPORTED' if reason == self.Reason.NOT_SUPPORTED else
-                 'INVALID_ARGUMENT')
-        arguments.append('PSA_ERROR_' + error)
-        tc.set_arguments(arguments)
-        return tc
-
-    def no_key_test_cases(
-            self,
-            alg: crypto_knowledge.Algorithm,
-            category: crypto_knowledge.AlgorithmCategory,
-    ) -> Iterator[test_case.TestCase]:
-        """Generate failure test cases for keyless operations with the specified algorithm."""
-        if alg.can_do(category):
-            # Compatible operation, unsupported algorithm
-            for dep in psa_information.automatic_dependencies(alg.base_expression):
-                yield self.make_test_case(alg, category,
-                                          self.Reason.NOT_SUPPORTED,
-                                          not_deps=frozenset([dep]))
-        else:
-            # Incompatible operation, supported algorithm
-            yield self.make_test_case(alg, category, self.Reason.INVALID)
-
-    def one_key_test_cases(
-            self,
-            alg: crypto_knowledge.Algorithm,
-            category: crypto_knowledge.AlgorithmCategory,
-    ) -> Iterator[test_case.TestCase]:
-        """Generate failure test cases for one-key operations with the specified algorithm."""
-        for kt in self.key_types:
-            key_is_compatible = kt.can_do(alg)
-            if key_is_compatible and alg.can_do(category):
-                # Compatible key and operation, unsupported algorithm
-                for dep in psa_information.automatic_dependencies(alg.base_expression):
-                    yield self.make_test_case(alg, category,
-                                              self.Reason.NOT_SUPPORTED,
-                                              kt=kt, not_deps=frozenset([dep]))
-                # Public key for a private-key operation
-                if category.is_asymmetric() and kt.is_public():
-                    yield self.make_test_case(alg, category,
-                                              self.Reason.PUBLIC,
-                                              kt=kt)
-            elif key_is_compatible:
-                # Compatible key, incompatible operation, supported algorithm
-                yield self.make_test_case(alg, category,
-                                          self.Reason.INVALID,
-                                          kt=kt)
-            elif alg.can_do(category):
-                # Incompatible key, compatible operation, supported algorithm
-                yield self.make_test_case(alg, category,
-                                          self.Reason.INCOMPATIBLE,
-                                          kt=kt)
-            else:
-                # Incompatible key and operation. Don't test cases where
-                # multiple things are wrong, to keep the number of test
-                # cases reasonable.
-                pass
-
-    def test_cases_for_algorithm(
-            self,
-            alg: crypto_knowledge.Algorithm,
-    ) -> Iterator[test_case.TestCase]:
-        """Generate operation failure test cases for the specified algorithm."""
-        for category in crypto_knowledge.AlgorithmCategory:
-            if category == crypto_knowledge.AlgorithmCategory.PAKE:
-                # PAKE operations are not implemented yet
-                pass
-            elif category.requires_key():
-                yield from self.one_key_test_cases(alg, category)
-            else:
-                yield from self.no_key_test_cases(alg, category)
-
-    def all_test_cases(self) -> Iterator[test_case.TestCase]:
-        """Generate all test cases for operations that must fail."""
-        algorithms = sorted(self.constructors.algorithms)
-        for expr in self.constructors.generate_expressions(algorithms):
-            alg = crypto_knowledge.Algorithm(expr)
-            yield from self.test_cases_for_algorithm(alg)
-
-
-class StorageKey(psa_storage.Key):
-    """Representation of a key for storage format testing."""
-
-    IMPLICIT_USAGE_FLAGS = {
-        'PSA_KEY_USAGE_SIGN_HASH': 'PSA_KEY_USAGE_SIGN_MESSAGE',
-        'PSA_KEY_USAGE_VERIFY_HASH': 'PSA_KEY_USAGE_VERIFY_MESSAGE'
-    } #type: Dict[str, str]
-    """Mapping of usage flags to the flags that they imply."""
-
-    def __init__(
-            self,
-            usage: Iterable[str],
-            without_implicit_usage: Optional[bool] = False,
-            **kwargs
-    ) -> None:
-        """Prepare to generate a key.
-
-        * `usage`                 : The usage flags used for the key.
-        * `without_implicit_usage`: Flag to define to apply the usage extension
-        """
-        usage_flags = set(usage)
-        if not without_implicit_usage:
-            for flag in sorted(usage_flags):
-                if flag in self.IMPLICIT_USAGE_FLAGS:
-                    usage_flags.add(self.IMPLICIT_USAGE_FLAGS[flag])
-        if usage_flags:
-            usage_expression = ' | '.join(sorted(usage_flags))
-        else:
-            usage_expression = '0'
-        super().__init__(usage=usage_expression, **kwargs)
-
-class StorageTestData(StorageKey):
-    """Representation of test case data for storage format testing."""
-
-    def __init__(
-            self,
-            description: str,
-            expected_usage: Optional[List[str]] = None,
-            **kwargs
-    ) -> None:
-        """Prepare to generate test data
-
-        * `description`   : used for the test case names
-        * `expected_usage`: the usage flags generated as the expected usage flags
-                            in the test cases. CAn differ from the usage flags
-                            stored in the keys because of the usage flags extension.
-        """
-        super().__init__(**kwargs)
-        self.description = description #type: str
-        if expected_usage is None:
-            self.expected_usage = self.usage #type: psa_storage.Expr
-        elif expected_usage:
-            self.expected_usage = psa_storage.Expr(' | '.join(expected_usage))
-        else:
-            self.expected_usage = psa_storage.Expr(0)
-
-class StorageFormat:
-    """Storage format stability test cases."""
-
-    def __init__(self, info: psa_information.Information, version: int, forward: bool) -> None:
-        """Prepare to generate test cases for storage format stability.
-
-        * `info`: information about the API. See the `Information` class.
-        * `version`: the storage format version to generate test cases for.
-        * `forward`: if true, generate forward compatibility test cases which
-          save a key and check that its representation is as intended. Otherwise
-          generate backward compatibility test cases which inject a key
-          representation and check that it can be read and used.
-        """
-        self.constructors = info.constructors #type: macro_collector.PSAMacroEnumerator
-        self.version = version #type: int
-        self.forward = forward #type: bool
-
-    RSA_OAEP_RE = re.compile(r'PSA_ALG_RSA_OAEP\((.*)\)\Z')
-    BRAINPOOL_RE = re.compile(r'PSA_KEY_TYPE_\w+\(PSA_ECC_FAMILY_BRAINPOOL_\w+\)\Z')
-    @classmethod
-    def exercise_key_with_algorithm(
-            cls,
-            key_type: psa_storage.Expr, bits: int,
-            alg: psa_storage.Expr
-    ) -> bool:
-        """Whether to exercise the given key with the given algorithm.
-
-        Normally only the type and algorithm matter for compatibility, and
-        this is handled in crypto_knowledge.KeyType.can_do(). This function
-        exists to detect exceptional cases. Exceptional cases detected here
-        are not tested in OpFail and should therefore have manually written
-        test cases.
-        """
-        # Some test keys have the RAW_DATA type and attributes that don't
-        # necessarily make sense. We do this to validate numerical
-        # encodings of the attributes.
-        # Raw data keys have no useful exercise anyway so there is no
-        # loss of test coverage.
-        if key_type.string == 'PSA_KEY_TYPE_RAW_DATA':
-            return False
-        # OAEP requires room for two hashes plus wrapping
-        m = cls.RSA_OAEP_RE.match(alg.string)
-        if m:
-            hash_alg = m.group(1)
-            hash_length = crypto_knowledge.Algorithm.hash_length(hash_alg)
-            key_length = (bits + 7) // 8
-            # Leave enough room for at least one byte of plaintext
-            return key_length > 2 * hash_length + 2
-        # There's nothing wrong with ECC keys on Brainpool curves,
-        # but operations with them are very slow. So we only exercise them
-        # with a single algorithm, not with all possible hashes. We do
-        # exercise other curves with all algorithms so test coverage is
-        # perfectly adequate like this.
-        m = cls.BRAINPOOL_RE.match(key_type.string)
-        if m and alg.string != 'PSA_ALG_ECDSA_ANY':
-            return False
-        return True
-
-    def make_test_case(self, key: StorageTestData) -> test_case.TestCase:
-        """Construct a storage format test case for the given key.
-
-        If ``forward`` is true, generate a forward compatibility test case:
-        create a key and validate that it has the expected representation.
-        Otherwise generate a backward compatibility test case: inject the
-        key representation into storage and validate that it can be read
-        correctly.
-        """
-        verb = 'save' if self.forward else 'read'
-        tc = test_case.TestCase()
-        tc.set_description(verb + ' ' + key.description)
-        dependencies = psa_information.automatic_dependencies(
-            key.lifetime.string, key.type.string,
-            key.alg.string, key.alg2.string,
-        )
-        dependencies = psa_information.finish_family_dependencies(dependencies, key.bits)
-        dependencies += psa_information.generate_deps_from_description(key.description)
-        dependencies = psa_information.fix_key_pair_dependencies(dependencies, 'BASIC')
-        tc.set_dependencies(dependencies)
-        tc.set_function('key_storage_' + verb)
-        if self.forward:
-            extra_arguments = []
-        else:
-            flags = []
-            if self.exercise_key_with_algorithm(key.type, key.bits, key.alg):
-                flags.append('TEST_FLAG_EXERCISE')
-            if 'READ_ONLY' in key.lifetime.string:
-                flags.append('TEST_FLAG_READ_ONLY')
-            extra_arguments = [' | '.join(flags) if flags else '0']
-        tc.set_arguments([key.lifetime.string,
-                          key.type.string, str(key.bits),
-                          key.expected_usage.string,
-                          key.alg.string, key.alg2.string,
-                          '"' + key.material.hex() + '"',
-                          '"' + key.hex() + '"',
-                          *extra_arguments])
-        return tc
-
-    def key_for_lifetime(
-            self,
-            lifetime: str,
-    ) -> StorageTestData:
-        """Construct a test key for the given lifetime."""
-        short = lifetime
-        short = re.sub(r'PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION',
-                       r'', short)
-        short = crypto_knowledge.short_expression(short)
-        description = 'lifetime: ' + short
-        key = StorageTestData(version=self.version,
-                              id=1, lifetime=lifetime,
-                              type='PSA_KEY_TYPE_RAW_DATA', bits=8,
-                              usage=['PSA_KEY_USAGE_EXPORT'], alg=0, alg2=0,
-                              material=b'L',
-                              description=description)
-        return key
-
-    def all_keys_for_lifetimes(self) -> Iterator[StorageTestData]:
-        """Generate test keys covering lifetimes."""
-        lifetimes = sorted(self.constructors.lifetimes)
-        expressions = self.constructors.generate_expressions(lifetimes)
-        for lifetime in expressions:
-            # Don't attempt to create or load a volatile key in storage
-            if 'VOLATILE' in lifetime:
-                continue
-            # Don't attempt to create a read-only key in storage,
-            # but do attempt to load one.
-            if 'READ_ONLY' in lifetime and self.forward:
-                continue
-            yield self.key_for_lifetime(lifetime)
-
-    def key_for_usage_flags(
-            self,
-            usage_flags: List[str],
-            short: Optional[str] = None,
-            test_implicit_usage: Optional[bool] = True
-    ) -> StorageTestData:
-        """Construct a test key for the given key usage."""
-        extra_desc = ' without implication' if test_implicit_usage else ''
-        description = 'usage' + extra_desc + ': '
-        key1 = StorageTestData(version=self.version,
-                               id=1, lifetime=0x00000001,
-                               type='PSA_KEY_TYPE_RAW_DATA', bits=8,
-                               expected_usage=usage_flags,
-                               without_implicit_usage=not test_implicit_usage,
-                               usage=usage_flags, alg=0, alg2=0,
-                               material=b'K',
-                               description=description)
-        if short is None:
-            usage_expr = key1.expected_usage.string
-            key1.description += crypto_knowledge.short_expression(usage_expr)
-        else:
-            key1.description += short
-        return key1
-
-    def generate_keys_for_usage_flags(self, **kwargs) -> Iterator[StorageTestData]:
-        """Generate test keys covering usage flags."""
-        known_flags = sorted(self.constructors.key_usage_flags)
-        yield self.key_for_usage_flags(['0'], **kwargs)
-        for usage_flag in known_flags:
-            yield self.key_for_usage_flags([usage_flag], **kwargs)
-        for flag1, flag2 in zip(known_flags,
-                                known_flags[1:] + [known_flags[0]]):
-            yield self.key_for_usage_flags([flag1, flag2], **kwargs)
-
-    def generate_key_for_all_usage_flags(self) -> Iterator[StorageTestData]:
-        known_flags = sorted(self.constructors.key_usage_flags)
-        yield self.key_for_usage_flags(known_flags, short='all known')
-
-    def all_keys_for_usage_flags(self) -> Iterator[StorageTestData]:
-        yield from self.generate_keys_for_usage_flags()
-        yield from self.generate_key_for_all_usage_flags()
-
-    def key_for_type_and_alg(
-            self,
-            kt: crypto_knowledge.KeyType,
-            bits: int,
-            alg: Optional[crypto_knowledge.Algorithm] = None,
-    ) -> StorageTestData:
-        """Construct a test key of the given type.
-
-        If alg is not None, this key allows it.
-        """
-        usage_flags = ['PSA_KEY_USAGE_EXPORT']
-        alg1 = 0 #type: psa_storage.Exprable
-        alg2 = 0
-        if alg is not None:
-            alg1 = alg.expression
-            usage_flags += alg.usage_flags(public=kt.is_public())
-        key_material = kt.key_material(bits)
-        description = 'type: {} {}-bit'.format(kt.short_expression(1), bits)
-        if alg is not None:
-            description += ', ' + alg.short_expression(1)
-        key = StorageTestData(version=self.version,
-                              id=1, lifetime=0x00000001,
-                              type=kt.expression, bits=bits,
-                              usage=usage_flags, alg=alg1, alg2=alg2,
-                              material=key_material,
-                              description=description)
-        return key
-
-    def keys_for_type(
-            self,
-            key_type: str,
-            all_algorithms: List[crypto_knowledge.Algorithm],
-    ) -> Iterator[StorageTestData]:
-        """Generate test keys for the given key type."""
-        kt = crypto_knowledge.KeyType(key_type)
-        for bits in kt.sizes_to_test():
-            # Test a non-exercisable key, as well as exercisable keys for
-            # each compatible algorithm.
-            # To do: test reading a key from storage with an incompatible
-            # or unsupported algorithm.
-            yield self.key_for_type_and_alg(kt, bits)
-            compatible_algorithms = [alg for alg in all_algorithms
-                                     if kt.can_do(alg)]
-            for alg in compatible_algorithms:
-                yield self.key_for_type_and_alg(kt, bits, alg)
-
-    def all_keys_for_types(self) -> Iterator[StorageTestData]:
-        """Generate test keys covering key types and their representations."""
-        key_types = sorted(self.constructors.key_types)
-        all_algorithms = [crypto_knowledge.Algorithm(alg)
-                          for alg in self.constructors.generate_expressions(
-                              sorted(self.constructors.algorithms)
-                          )]
-        for key_type in self.constructors.generate_expressions(key_types):
-            yield from self.keys_for_type(key_type, all_algorithms)
-
-    def keys_for_algorithm(self, alg: str) -> Iterator[StorageTestData]:
-        """Generate test keys for the encoding of the specified algorithm."""
-        # These test cases only validate the encoding of algorithms, not
-        # whether the key read from storage is suitable for an operation.
-        # `keys_for_types` generate read tests with an algorithm and a
-        # compatible key.
-        descr = crypto_knowledge.short_expression(alg, 1)
-        usage = ['PSA_KEY_USAGE_EXPORT']
-        key1 = StorageTestData(version=self.version,
-                               id=1, lifetime=0x00000001,
-                               type='PSA_KEY_TYPE_RAW_DATA', bits=8,
-                               usage=usage, alg=alg, alg2=0,
-                               material=b'K',
-                               description='alg: ' + descr)
-        yield key1
-        key2 = StorageTestData(version=self.version,
-                               id=1, lifetime=0x00000001,
-                               type='PSA_KEY_TYPE_RAW_DATA', bits=8,
-                               usage=usage, alg=0, alg2=alg,
-                               material=b'L',
-                               description='alg2: ' + descr)
-        yield key2
-
-    def all_keys_for_algorithms(self) -> Iterator[StorageTestData]:
-        """Generate test keys covering algorithm encodings."""
-        algorithms = sorted(self.constructors.algorithms)
-        for alg in self.constructors.generate_expressions(algorithms):
-            yield from self.keys_for_algorithm(alg)
-
-    def generate_all_keys(self) -> Iterator[StorageTestData]:
-        """Generate all keys for the test cases."""
-        yield from self.all_keys_for_lifetimes()
-        yield from self.all_keys_for_usage_flags()
-        yield from self.all_keys_for_types()
-        yield from self.all_keys_for_algorithms()
-
-    def all_test_cases(self) -> Iterator[test_case.TestCase]:
-        """Generate all storage format test cases."""
-        # First build a list of all keys, then construct all the corresponding
-        # test cases. This allows all required information to be obtained in
-        # one go, which is a significant performance gain as the information
-        # includes numerical values obtained by compiling a C program.
-        all_keys = list(self.generate_all_keys())
-        for key in all_keys:
-            if key.location_value() != 0:
-                # Skip keys with a non-default location, because they
-                # require a driver and we currently have no mechanism to
-                # determine whether a driver is available.
-                continue
-            yield self.make_test_case(key)
-
-class StorageFormatForward(StorageFormat):
-    """Storage format stability test cases for forward compatibility."""
-
-    def __init__(self, info: psa_information.Information, version: int) -> None:
-        super().__init__(info, version, True)
-
-class StorageFormatV0(StorageFormat):
-    """Storage format stability test cases for version 0 compatibility."""
-
-    def __init__(self, info: psa_information.Information) -> None:
-        super().__init__(info, 0, False)
-
-    def all_keys_for_usage_flags(self) -> Iterator[StorageTestData]:
-        """Generate test keys covering usage flags."""
-        yield from super().all_keys_for_usage_flags()
-        yield from self.generate_keys_for_usage_flags(test_implicit_usage=False)
-
-    def keys_for_implicit_usage(
-            self,
-            implyer_usage: str,
-            alg: str,
-            key_type: crypto_knowledge.KeyType
-    ) -> StorageTestData:
-        # pylint: disable=too-many-locals
-        """Generate test keys for the specified implicit usage flag,
-           algorithm and key type combination.
-        """
-        bits = key_type.sizes_to_test()[0]
-        implicit_usage = StorageKey.IMPLICIT_USAGE_FLAGS[implyer_usage]
-        usage_flags = ['PSA_KEY_USAGE_EXPORT']
-        material_usage_flags = usage_flags + [implyer_usage]
-        expected_usage_flags = material_usage_flags + [implicit_usage]
-        alg2 = 0
-        key_material = key_type.key_material(bits)
-        usage_expression = crypto_knowledge.short_expression(implyer_usage, 1)
-        alg_expression = crypto_knowledge.short_expression(alg, 1)
-        key_type_expression = key_type.short_expression(1)
-        description = 'implied by {}: {} {} {}-bit'.format(
-            usage_expression, alg_expression, key_type_expression, bits)
-        key = StorageTestData(version=self.version,
-                              id=1, lifetime=0x00000001,
-                              type=key_type.expression, bits=bits,
-                              usage=material_usage_flags,
-                              expected_usage=expected_usage_flags,
-                              without_implicit_usage=True,
-                              alg=alg, alg2=alg2,
-                              material=key_material,
-                              description=description)
-        return key
-
-    def gather_key_types_for_sign_alg(self) -> Dict[str, List[str]]:
-        # pylint: disable=too-many-locals
-        """Match possible key types for sign algorithms."""
-        # To create a valid combination both the algorithms and key types
-        # must be filtered. Pair them with keywords created from its names.
-        incompatible_alg_keyword = frozenset(['RAW', 'ANY', 'PURE'])
-        incompatible_key_type_keywords = frozenset(['MONTGOMERY'])
-        keyword_translation = {
-            'ECDSA': 'ECC',
-            'ED[0-9]*.*' : 'EDWARDS'
-        }
-        exclusive_keywords = {
-            'EDWARDS': 'ECC'
-        }
-        key_types = set(self.constructors.generate_expressions(self.constructors.key_types))
-        algorithms = set(self.constructors.generate_expressions(self.constructors.sign_algorithms))
-        alg_with_keys = {} #type: Dict[str, List[str]]
-        translation_table = str.maketrans('(', '_', ')')
-        for alg in algorithms:
-            # Generate keywords from the name of the algorithm
-            alg_keywords = set(alg.partition('(')[0].split(sep='_')[2:])
-            # Translate keywords for better matching with the key types
-            for keyword in alg_keywords.copy():
-                for pattern, replace in keyword_translation.items():
-                    if re.match(pattern, keyword):
-                        alg_keywords.remove(keyword)
-                        alg_keywords.add(replace)
-            # Filter out incompatible algorithms
-            if not alg_keywords.isdisjoint(incompatible_alg_keyword):
-                continue
-
-            for key_type in key_types:
-                # Generate keywords from the of the key type
-                key_type_keywords = set(key_type.translate(translation_table).split(sep='_')[3:])
-
-                # Remove ambiguous keywords
-                for keyword1, keyword2 in exclusive_keywords.items():
-                    if keyword1 in key_type_keywords:
-                        key_type_keywords.remove(keyword2)
-
-                if key_type_keywords.isdisjoint(incompatible_key_type_keywords) and\
-                   not key_type_keywords.isdisjoint(alg_keywords):
-                    if alg in alg_with_keys:
-                        alg_with_keys[alg].append(key_type)
-                    else:
-                        alg_with_keys[alg] = [key_type]
-        return alg_with_keys
-
-    def all_keys_for_implicit_usage(self) -> Iterator[StorageTestData]:
-        """Generate test keys for usage flag extensions."""
-        # Generate a key type and algorithm pair for each extendable usage
-        # flag to generate a valid key for exercising. The key is generated
-        # without usage extension to check the extension compatibility.
-        alg_with_keys = self.gather_key_types_for_sign_alg()
-
-        for usage in sorted(StorageKey.IMPLICIT_USAGE_FLAGS, key=str):
-            for alg in sorted(alg_with_keys):
-                for key_type in sorted(alg_with_keys[alg]):
-                    # The key types must be filtered to fit the specific usage flag.
-                    kt = crypto_knowledge.KeyType(key_type)
-                    if kt.is_public() and '_SIGN_' in usage:
-                        # Can't sign with a public key
-                        continue
-                    yield self.keys_for_implicit_usage(usage, alg, kt)
-
-    def generate_all_keys(self) -> Iterator[StorageTestData]:
-        yield from super().generate_all_keys()
-        yield from self.all_keys_for_implicit_usage()
-
-
-class PSATestGenerator(test_data_generation.TestGenerator):
-    """Test generator subclass including PSA targets and info."""
-    # Note that targets whose names contain 'test_format' have their content
-    # validated by `abi_check.py`.
-    targets = {
-        'test_suite_psa_crypto_generate_key.generated':
-        lambda info: KeyGenerate(info).test_cases_for_key_generation(),
-        'test_suite_psa_crypto_not_supported.generated':
-        lambda info: KeyTypeNotSupported(info).test_cases_for_not_supported(),
-        'test_suite_psa_crypto_low_hash.generated':
-        lambda info: crypto_data_tests.HashPSALowLevel(info).all_test_cases(),
-        'test_suite_psa_crypto_op_fail.generated':
-        lambda info: OpFail(info).all_test_cases(),
-        'test_suite_psa_crypto_storage_format.current':
-        lambda info: StorageFormatForward(info, 0).all_test_cases(),
-        'test_suite_psa_crypto_storage_format.v0':
-        lambda info: StorageFormatV0(info).all_test_cases(),
-    } #type: Dict[str, Callable[[psa_information.Information], Iterable[test_case.TestCase]]]
-
-    def __init__(self, options):
-        super().__init__(options)
-        self.info = psa_information.Information()
-
-    def generate_target(self, name: str, *target_args) -> None:
-        super().generate_target(name, self.info)
-
-
-if __name__ == '__main__':
-    test_data_generation.main(sys.argv[1:], __doc__, PSATestGenerator)
diff --git a/tests/scripts/generate_psa_wrappers.py b/tests/scripts/generate_psa_wrappers.py
deleted file mode 100755
index 07d1450..0000000
--- a/tests/scripts/generate_psa_wrappers.py
+++ /dev/null
@@ -1,257 +0,0 @@
-#!/usr/bin/env python3
-"""Generate wrapper functions for PSA function calls.
-"""
-
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-
-### WARNING: the code in this file has not been extensively reviewed yet.
-### We do not think it is harmful, but it may be below our normal standards
-### for robustness and maintainability.
-
-import argparse
-import itertools
-import os
-from typing import Iterator, List, Optional, Tuple
-
-import scripts_path #pylint: disable=unused-import
-from mbedtls_dev import build_tree
-from mbedtls_dev import c_parsing_helper
-from mbedtls_dev import c_wrapper_generator
-from mbedtls_dev import typing_util
-
-
-class BufferParameter:
-    """Description of an input or output buffer parameter sequence to a PSA function."""
-    #pylint: disable=too-few-public-methods
-
-    def __init__(self, i: int, is_output: bool,
-                 buffer_name: str, size_name: str) -> None:
-        """Initialize the parameter information.
-
-        i is the index of the function argument that is the pointer to the buffer.
-        The size is argument i+1. For a variable-size output, the actual length
-        goes in argument i+2.
-
-        buffer_name and size_names are the names of arguments i and i+1.
-        This class does not yet help with the output length.
-        """
-        self.index = i
-        self.buffer_name = buffer_name
-        self.size_name = size_name
-        self.is_output = is_output
-
-
-class PSAWrapperGenerator(c_wrapper_generator.Base):
-    """Generate a C source file containing wrapper functions for PSA Crypto API calls."""
-
-    _CPP_GUARDS = ('defined(MBEDTLS_PSA_CRYPTO_C) && ' +
-                   'defined(MBEDTLS_TEST_HOOKS) && \\\n    ' +
-                   '!defined(RECORD_PSA_STATUS_COVERAGE_LOG)')
-    _WRAPPER_NAME_PREFIX = 'mbedtls_test_wrap_'
-    _WRAPPER_NAME_SUFFIX = ''
-
-    def gather_data(self) -> None:
-        root_dir = build_tree.guess_mbedtls_root()
-        for header_name in ['crypto.h', 'crypto_extra.h']:
-            header_path = os.path.join(root_dir, 'include', 'psa', header_name)
-            c_parsing_helper.read_function_declarations(self.functions, header_path)
-
-    _SKIP_FUNCTIONS = frozenset([
-        'mbedtls_psa_external_get_random', # not a library function
-        'psa_get_key_domain_parameters', # client-side function
-        'psa_get_key_slot_number', # client-side function
-        'psa_key_derivation_verify_bytes', # not implemented yet
-        'psa_key_derivation_verify_key', # not implemented yet
-        'psa_set_key_domain_parameters', # client-side function
-    ])
-
-    def _skip_function(self, function: c_wrapper_generator.FunctionInfo) -> bool:
-        if function.return_type != 'psa_status_t':
-            return True
-        if function.name in self._SKIP_FUNCTIONS:
-            return True
-        return False
-
-    # PAKE stuff: not implemented yet
-    _PAKE_STUFF = frozenset([
-        'psa_crypto_driver_pake_inputs_t *',
-        'psa_pake_cipher_suite_t *',
-    ])
-
-    def _return_variable_name(self,
-                              function: c_wrapper_generator.FunctionInfo) -> str:
-        """The name of the variable that will contain the return value."""
-        if function.return_type == 'psa_status_t':
-            return 'status'
-        return super()._return_variable_name(function)
-
-    _FUNCTION_GUARDS = c_wrapper_generator.Base._FUNCTION_GUARDS.copy() \
-        #pylint: disable=protected-access
-    _FUNCTION_GUARDS.update({
-        'mbedtls_psa_register_se_key': 'defined(MBEDTLS_PSA_CRYPTO_SE_C)',
-        'mbedtls_psa_inject_entropy': 'defined(MBEDTLS_PSA_INJECT_ENTROPY)',
-        'mbedtls_psa_external_get_random': 'defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)',
-        'mbedtls_psa_platform_get_builtin_key': 'defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)',
-    })
-
-    @staticmethod
-    def _detect_buffer_parameters(arguments: List[c_parsing_helper.ArgumentInfo],
-                                  argument_names: List[str]) -> Iterator[BufferParameter]:
-        """Detect function arguments that are buffers (pointer, size [,length])."""
-        types = ['' if arg.suffix else arg.type for arg in arguments]
-        # pairs = list of (type_of_arg_N, type_of_arg_N+1)
-        # where each type_of_arg_X is the empty string if the type is an array
-        # or there is no argument X.
-        pairs = enumerate(itertools.zip_longest(types, types[1:], fillvalue=''))
-        for i, t01 in pairs:
-            if (t01[0] == 'const uint8_t *' or t01[0] == 'uint8_t *') and \
-               t01[1] == 'size_t':
-                yield BufferParameter(i, not t01[0].startswith('const '),
-                                      argument_names[i], argument_names[i+1])
-
-    @staticmethod
-    def _write_poison_buffer_parameter(out: typing_util.Writable,
-                                       param: BufferParameter,
-                                       poison: bool) -> None:
-        """Write poisoning or unpoisoning code for a buffer parameter.
-
-        Write poisoning code if poison is true, unpoisoning code otherwise.
-        """
-        out.write('    MBEDTLS_TEST_MEMORY_{}({}, {});\n'.format(
-            'POISON' if poison else 'UNPOISON',
-            param.buffer_name, param.size_name
-        ))
-
-    def _write_poison_buffer_parameters(self, out: typing_util.Writable,
-                                        buffer_parameters: List[BufferParameter],
-                                        poison: bool) -> None:
-        """Write poisoning or unpoisoning code for the buffer parameters.
-
-        Write poisoning code if poison is true, unpoisoning code otherwise.
-        """
-        if not buffer_parameters:
-            return
-        out.write('#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\n')
-        for param in buffer_parameters:
-            self._write_poison_buffer_parameter(out, param, poison)
-        out.write('#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */\n')
-
-    @staticmethod
-    def _parameter_should_be_copied(function_name: str,
-                                    _buffer_name: Optional[str]) -> bool:
-        """Whether the specified buffer argument to a PSA function should be copied.
-        """
-        # False-positives that do not need buffer copying
-        if function_name in ('mbedtls_psa_inject_entropy',
-                             'psa_crypto_driver_pake_get_password',
-                             'psa_crypto_driver_pake_get_user',
-                             'psa_crypto_driver_pake_get_peer'):
-            return False
-
-        return True
-
-    def _write_function_call(self, out: typing_util.Writable,
-                             function: c_wrapper_generator.FunctionInfo,
-                             argument_names: List[str]) -> None:
-        buffer_parameters = list(
-            param
-            for param in self._detect_buffer_parameters(function.arguments,
-                                                        argument_names)
-            if self._parameter_should_be_copied(function.name,
-                                                function.arguments[param.index].name))
-        self._write_poison_buffer_parameters(out, buffer_parameters, True)
-        super()._write_function_call(out, function, argument_names)
-        self._write_poison_buffer_parameters(out, buffer_parameters, False)
-
-    def _write_prologue(self, out: typing_util.Writable, header: bool) -> None:
-        super()._write_prologue(out, header)
-        out.write("""
-#if {}
-
-#include <psa/crypto.h>
-
-#include <test/memory.h>
-#include <test/psa_crypto_helpers.h>
-#include <test/psa_test_wrappers.h>
-"""
-                  .format(self._CPP_GUARDS))
-
-    def _write_epilogue(self, out: typing_util.Writable, header: bool) -> None:
-        out.write("""
-#endif /* {} */
-"""
-                  .format(self._CPP_GUARDS))
-        super()._write_epilogue(out, header)
-
-
-class PSALoggingWrapperGenerator(PSAWrapperGenerator, c_wrapper_generator.Logging):
-    """Generate a C source file containing wrapper functions that log PSA Crypto API calls."""
-
-    def __init__(self, stream: str) -> None:
-        super().__init__()
-        self.set_stream(stream)
-
-    _PRINTF_TYPE_CAST = c_wrapper_generator.Logging._PRINTF_TYPE_CAST.copy()
-    _PRINTF_TYPE_CAST.update({
-        'mbedtls_svc_key_id_t': 'unsigned',
-        'psa_algorithm_t': 'unsigned',
-        'psa_drv_slot_number_t': 'unsigned long long',
-        'psa_key_derivation_step_t': 'int',
-        'psa_key_id_t': 'unsigned',
-        'psa_key_slot_number_t': 'unsigned long long',
-        'psa_key_lifetime_t': 'unsigned',
-        'psa_key_type_t': 'unsigned',
-        'psa_key_usage_flags_t': 'unsigned',
-        'psa_pake_role_t': 'int',
-        'psa_pake_step_t': 'int',
-        'psa_status_t': 'int',
-    })
-
-    def _printf_parameters(self, typ: str, var: str) -> Tuple[str, List[str]]:
-        if typ.startswith('const '):
-            typ = typ[6:]
-        if typ == 'uint8_t *':
-            # Skip buffers
-            return '', []
-        if typ.endswith('operation_t *'):
-            return '', []
-        if typ in self._PAKE_STUFF:
-            return '', []
-        if typ == 'psa_key_attributes_t *':
-            return (var + '={id=%u, lifetime=0x%08x, type=0x%08x, bits=%u, alg=%08x, usage=%08x}',
-                    ['(unsigned) psa_get_key_{}({})'.format(field, var)
-                     for field in ['id', 'lifetime', 'type', 'bits', 'algorithm', 'usage_flags']])
-        return super()._printf_parameters(typ, var)
-
-
-DEFAULT_C_OUTPUT_FILE_NAME = 'tests/src/psa_test_wrappers.c'
-DEFAULT_H_OUTPUT_FILE_NAME = 'tests/include/test/psa_test_wrappers.h'
-
-def main() -> None:
-    parser = argparse.ArgumentParser(description=globals()['__doc__'])
-    parser.add_argument('--log',
-                        help='Stream to log to (default: no logging code)')
-    parser.add_argument('--output-c',
-                        metavar='FILENAME',
-                        default=DEFAULT_C_OUTPUT_FILE_NAME,
-                        help=('Output .c file path (default: {}; skip .c output if empty)'
-                              .format(DEFAULT_C_OUTPUT_FILE_NAME)))
-    parser.add_argument('--output-h',
-                        metavar='FILENAME',
-                        default=DEFAULT_H_OUTPUT_FILE_NAME,
-                        help=('Output .h file path (default: {}; skip .h output if empty)'
-                              .format(DEFAULT_H_OUTPUT_FILE_NAME)))
-    options = parser.parse_args()
-    if options.log:
-        generator = PSALoggingWrapperGenerator(options.log) #type: PSAWrapperGenerator
-    else:
-        generator = PSAWrapperGenerator()
-    generator.gather_data()
-    if options.output_h:
-        generator.write_h_file(options.output_h)
-    if options.output_c:
-        generator.write_c_file(options.output_c)
-
-if __name__ == '__main__':
-    main()
diff --git a/tests/scripts/generate_test_cert_macros.py b/tests/scripts/generate_test_cert_macros.py
deleted file mode 100755
index a3bca7e..0000000
--- a/tests/scripts/generate_test_cert_macros.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-Generate `tests/src/test_certs.h` which includes certficaties/keys/certificate list for testing.
-"""
-
-#
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-
-
-import os
-import sys
-import argparse
-import jinja2
-
-class MacroDefineAction(argparse.Action):
-    #pylint: disable=signature-differs, too-few-public-methods
-    def __call__(self, parser, namespace, values, option_string):
-        if not hasattr(namespace, 'values'):
-            setattr(namespace, 'values', [])
-        macro_name, filename = values
-        if self.dest in ('string', 'binary') and not os.path.exists(filename):
-            raise argparse.ArgumentError(
-                None, '`{}`: Input file does not exist.'.format(filename))
-        namespace.values.append((self.dest, macro_name, filename))
-
-
-def macro_define_type(value):
-    ret = value.split('=', 1)
-    if len(ret) != 2:
-        raise argparse.ArgumentTypeError(
-            '`{}` is not MACRO=value format'.format(value))
-    return ret
-
-
-def build_argparser(parser):
-    parser.description = __doc__
-    parser.add_argument('--string', type=macro_define_type, action=MacroDefineAction,
-                        metavar='MACRO_NAME=path/to/file', help='PEM to C string. ')
-    parser.add_argument('--binary', type=macro_define_type, action=MacroDefineAction,
-                        metavar='MACRO_NAME=path/to/file',
-                        help='DER to C arrary.')
-    parser.add_argument('--password', type=macro_define_type, action=MacroDefineAction,
-                        metavar='MACRO_NAME=password', help='Password to C string.')
-    parser.add_argument('--output', type=str, required=True)
-
-
-def main():
-    parser = argparse.ArgumentParser()
-    build_argparser(parser)
-    args = parser.parse_args()
-    return generate(**vars(args))
-
-#pylint: disable=dangerous-default-value, unused-argument
-def generate(values=[], output=None, **kwargs):
-    """Generate C header file.
-    """
-    this_dir = os.path.dirname(os.path.abspath(__file__))
-    template_loader = jinja2.FileSystemLoader(
-        searchpath=os.path.join(this_dir, '..', 'data_files'))
-    template_env = jinja2.Environment(
-        loader=template_loader, lstrip_blocks=True, trim_blocks=True)
-
-    def read_as_c_array(filename):
-        with open(filename, 'rb') as f:
-            data = f.read(12)
-            while data:
-                yield ', '.join(['{:#04x}'.format(b) for b in data])
-                data = f.read(12)
-
-    def read_lines(filename):
-        with open(filename) as f:
-            try:
-                for line in f:
-                    yield line.strip()
-            except:
-                print(filename)
-                raise
-
-    def put_to_column(value, position=0):
-        return ' '*position + value
-
-    template_env.filters['read_as_c_array'] = read_as_c_array
-    template_env.filters['read_lines'] = read_lines
-    template_env.filters['put_to_column'] = put_to_column
-
-    template = template_env.get_template('test_certs.h.jinja2')
-
-    with open(output, 'w') as f:
-        f.write(template.render(macros=values))
-
-
-if __name__ == '__main__':
-    sys.exit(main())
diff --git a/tests/scripts/generate_test_code.py b/tests/scripts/generate_test_code.py
deleted file mode 100755
index 5f711bf..0000000
--- a/tests/scripts/generate_test_code.py
+++ /dev/null
@@ -1,1277 +0,0 @@
-#!/usr/bin/env python3
-# Test suites code generator.
-#
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-
-"""
-This script is a key part of Mbed TLS test suites framework. For
-understanding the script it is important to understand the
-framework. This doc string contains a summary of the framework
-and explains the function of this script.
-
-Mbed TLS test suites:
-=====================
-Scope:
-------
-The test suites focus on unit testing the crypto primitives and also
-include x509 parser tests. Tests can be added to test any Mbed TLS
-module. However, the framework is not capable of testing SSL
-protocol, since that requires full stack execution and that is best
-tested as part of the system test.
-
-Test case definition:
----------------------
-Tests are defined in a test_suite_<module>[.<optional sub module>].data
-file. A test definition contains:
- test name
- optional build macro dependencies
- test function
- test parameters
-
-Test dependencies are build macros that can be specified to indicate
-the build config in which the test is valid. For example if a test
-depends on a feature that is only enabled by defining a macro. Then
-that macro should be specified as a dependency of the test.
-
-Test function is the function that implements the test steps. This
-function is specified for different tests that perform same steps
-with different parameters.
-
-Test parameters are specified in string form separated by ':'.
-Parameters can be of type string, binary data specified as hex
-string and integer constants specified as integer, macro or
-as an expression. Following is an example test definition:
-
- AES 128 GCM Encrypt and decrypt 8 bytes
- depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
- enc_dec_buf:MBEDTLS_CIPHER_AES_128_GCM:"AES-128-GCM":128:8:-1
-
-Test functions:
----------------
-Test functions are coded in C in test_suite_<module>.function files.
-Functions file is itself not compilable and contains special
-format patterns to specify test suite dependencies, start and end
-of functions and function dependencies. Check any existing functions
-file for example.
-
-Execution:
-----------
-Tests are executed in 3 steps:
-- Generating test_suite_<module>[.<optional sub module>].c file
-  for each corresponding .data file.
-- Building each source file into executables.
-- Running each executable and printing report.
-
-Generating C test source requires more than just the test functions.
-Following extras are required:
-- Process main()
-- Reading .data file and dispatching test cases.
-- Platform specific test case execution
-- Dependency checking
-- Integer expression evaluation
-- Test function dispatch
-
-Build dependencies and integer expressions (in the test parameters)
-are specified as strings in the .data file. Their run time value is
-not known at the generation stage. Hence, they need to be translated
-into run time evaluations. This script generates the run time checks
-for dependencies and integer expressions.
-
-Similarly, function names have to be translated into function calls.
-This script also generates code for function dispatch.
-
-The extra code mentioned here is either generated by this script
-or it comes from the input files: helpers file, platform file and
-the template file.
-
-Helper file:
-------------
-Helpers file contains common helper/utility functions and data.
-
-Platform file:
---------------
-Platform file contains platform specific setup code and test case
-dispatch code. For example, host_test.function reads test data
-file from host's file system and dispatches tests.
-
-Template file:
----------
-Template file for example main_test.function is a template C file in
-which generated code and code from input files is substituted to
-generate a compilable C file. It also contains skeleton functions for
-dependency checks, expression evaluation and function dispatch. These
-functions are populated with checks and return codes by this script.
-
-Template file contains "replacement" fields that are formatted
-strings processed by Python string.Template.substitute() method.
-
-This script:
-============
-Core function of this script is to fill the template file with
-code that is generated or read from helpers and platform files.
-
-This script replaces following fields in the template and generates
-the test source file:
-
-__MBEDTLS_TEST_TEMPLATE__TEST_COMMON_HELPERS
-            All common code from helpers.function
-            is substituted here.
-__MBEDTLS_TEST_TEMPLATE__FUNCTIONS_CODE
-            Test functions are substituted here
-            from the input test_suit_xyz.function
-            file. C preprocessor checks are generated
-            for the build dependencies specified
-            in the input file. This script also
-            generates wrappers for the test
-            functions with code to expand the
-            string parameters read from the data
-            file.
-__MBEDTLS_TEST_TEMPLATE__EXPRESSION_CODE
-            This script enumerates the
-            expressions in the .data file and
-            generates code to handle enumerated
-            expression Ids and return the values.
-__MBEDTLS_TEST_TEMPLATE__DEP_CHECK_CODE
-            This script enumerates all
-            build dependencies and generate
-            code to handle enumerated build
-            dependency Id and return status: if
-            the dependency is defined or not.
-__MBEDTLS_TEST_TEMPLATE__DISPATCH_CODE
-            This script enumerates the functions
-            specified in the input test data file
-            and generates the initializer for the
-            function table in the template
-            file.
-__MBEDTLS_TEST_TEMPLATE__PLATFORM_CODE
-            Platform specific setup and test
-            dispatch code.
-
-"""
-
-
-import os
-import re
-import sys
-import string
-import argparse
-
-
-# Types recognized as signed integer arguments in test functions.
-SIGNED_INTEGER_TYPES = frozenset([
-    'char',
-    'short',
-    'short int',
-    'int',
-    'int8_t',
-    'int16_t',
-    'int32_t',
-    'int64_t',
-    'intmax_t',
-    'long',
-    'long int',
-    'long long int',
-    'mbedtls_mpi_sint',
-    'psa_status_t',
-])
-# Types recognized as string arguments in test functions.
-STRING_TYPES = frozenset(['char*', 'const char*', 'char const*'])
-# Types recognized as hex data arguments in test functions.
-DATA_TYPES = frozenset(['data_t*', 'const data_t*', 'data_t const*'])
-
-BEGIN_HEADER_REGEX = r'/\*\s*BEGIN_HEADER\s*\*/'
-END_HEADER_REGEX = r'/\*\s*END_HEADER\s*\*/'
-
-BEGIN_SUITE_HELPERS_REGEX = r'/\*\s*BEGIN_SUITE_HELPERS\s*\*/'
-END_SUITE_HELPERS_REGEX = r'/\*\s*END_SUITE_HELPERS\s*\*/'
-
-BEGIN_DEP_REGEX = r'BEGIN_DEPENDENCIES'
-END_DEP_REGEX = r'END_DEPENDENCIES'
-
-BEGIN_CASE_REGEX = r'/\*\s*BEGIN_CASE\s*(?P<depends_on>.*?)\s*\*/'
-END_CASE_REGEX = r'/\*\s*END_CASE\s*\*/'
-
-DEPENDENCY_REGEX = r'depends_on:(?P<dependencies>.*)'
-C_IDENTIFIER_REGEX = r'!?[a-z_][a-z0-9_]*'
-CONDITION_OPERATOR_REGEX = r'[!=]=|[<>]=?'
-# forbid 0ddd which might be accidentally octal or accidentally decimal
-CONDITION_VALUE_REGEX = r'[-+]?(0x[0-9a-f]+|0|[1-9][0-9]*)'
-CONDITION_REGEX = r'({})(?:\s*({})\s*({}))?$'.format(C_IDENTIFIER_REGEX,
-                                                     CONDITION_OPERATOR_REGEX,
-                                                     CONDITION_VALUE_REGEX)
-TEST_FUNCTION_VALIDATION_REGEX = r'\s*void\s+(?P<func_name>\w+)\s*\('
-FUNCTION_ARG_LIST_END_REGEX = r'.*\)'
-EXIT_LABEL_REGEX = r'^exit:'
-
-
-class GeneratorInputError(Exception):
-    """
-    Exception to indicate error in the input files to this script.
-    This includes missing patterns, test function names and other
-    parsing errors.
-    """
-    pass
-
-
-class FileWrapper:
-    """
-    This class extends the file object with attribute line_no,
-    that indicates line number for the line that is read.
-    """
-
-    def __init__(self, file_name) -> None:
-        """
-        Instantiate the file object and initialize the line number to 0.
-
-        :param file_name: File path to open.
-        """
-        # private mix-in file object
-        self._f = open(file_name, 'rb')
-        self._line_no = 0
-
-    def __iter__(self):
-        return self
-
-    def __next__(self):
-        """
-        This method makes FileWrapper iterable.
-        It counts the line numbers as each line is read.
-
-        :return: Line read from file.
-        """
-        line = self._f.__next__()
-        self._line_no += 1
-        # Convert byte array to string with correct encoding and
-        # strip any whitespaces added in the decoding process.
-        return line.decode(sys.getdefaultencoding()).rstrip()+ '\n'
-
-    def __enter__(self):
-        return self
-
-    def __exit__(self, exc_type, exc_val, exc_tb):
-        self._f.__exit__(exc_type, exc_val, exc_tb)
-
-    @property
-    def line_no(self):
-        """
-        Property that indicates line number for the line that is read.
-        """
-        return self._line_no
-
-    @property
-    def name(self):
-        """
-        Property that indicates name of the file that is read.
-        """
-        return self._f.name
-
-
-def split_dep(dep):
-    """
-    Split NOT character '!' from dependency. Used by gen_dependencies()
-
-    :param dep: Dependency list
-    :return: string tuple. Ex: ('!', MACRO) for !MACRO and ('', MACRO) for
-             MACRO.
-    """
-    return ('!', dep[1:]) if dep[0] == '!' else ('', dep)
-
-
-def gen_dependencies(dependencies):
-    """
-    Test suite data and functions specifies compile time dependencies.
-    This function generates C preprocessor code from the input
-    dependency list. Caller uses the generated preprocessor code to
-    wrap dependent code.
-    A dependency in the input list can have a leading '!' character
-    to negate a condition. '!' is separated from the dependency using
-    function split_dep() and proper preprocessor check is generated
-    accordingly.
-
-    :param dependencies: List of dependencies.
-    :return: if defined and endif code with macro annotations for
-             readability.
-    """
-    dep_start = ''.join(['#if %sdefined(%s)\n' % (x, y) for x, y in
-                         map(split_dep, dependencies)])
-    dep_end = ''.join(['#endif /* %s */\n' %
-                       x for x in reversed(dependencies)])
-
-    return dep_start, dep_end
-
-
-def gen_dependencies_one_line(dependencies):
-    """
-    Similar to gen_dependencies() but generates dependency checks in one line.
-    Useful for generating code with #else block.
-
-    :param dependencies: List of dependencies.
-    :return: Preprocessor check code
-    """
-    defines = '#if ' if dependencies else ''
-    defines += ' && '.join(['%sdefined(%s)' % (x, y) for x, y in map(
-        split_dep, dependencies)])
-    return defines
-
-
-def gen_function_wrapper(name, local_vars, args_dispatch):
-    """
-    Creates test function wrapper code. A wrapper has the code to
-    unpack parameters from parameters[] array.
-
-    :param name: Test function name
-    :param local_vars: Local variables declaration code
-    :param args_dispatch: List of dispatch arguments.
-           Ex: ['(char *) params[0]', '*((int *) params[1])']
-    :return: Test function wrapper.
-    """
-    # Then create the wrapper
-    wrapper = '''
-void {name}_wrapper( void ** params )
-{{
-{unused_params}{locals}
-    {name}( {args} );
-}}
-'''.format(name=name,
-           unused_params='' if args_dispatch else '    (void)params;\n',
-           args=', '.join(args_dispatch),
-           locals=local_vars)
-    return wrapper
-
-
-def gen_dispatch(name, dependencies):
-    """
-    Test suite code template main_test.function defines a C function
-    array to contain test case functions. This function generates an
-    initializer entry for a function in that array. The entry is
-    composed of a compile time check for the test function
-    dependencies. At compile time the test function is assigned when
-    dependencies are met, else NULL is assigned.
-
-    :param name: Test function name
-    :param dependencies: List of dependencies
-    :return: Dispatch code.
-    """
-    if dependencies:
-        preprocessor_check = gen_dependencies_one_line(dependencies)
-        dispatch_code = '''
-{preprocessor_check}
-    {name}_wrapper,
-#else
-    NULL,
-#endif
-'''.format(preprocessor_check=preprocessor_check, name=name)
-    else:
-        dispatch_code = '''
-    {name}_wrapper,
-'''.format(name=name)
-
-    return dispatch_code
-
-
-def parse_until_pattern(funcs_f, end_regex):
-    """
-    Matches pattern end_regex to the lines read from the file object.
-    Returns the lines read until end pattern is matched.
-
-    :param funcs_f: file object for .function file
-    :param end_regex: Pattern to stop parsing
-    :return: Lines read before the end pattern
-    """
-    headers = '#line %d "%s"\n' % (funcs_f.line_no + 1, funcs_f.name)
-    for line in funcs_f:
-        if re.search(end_regex, line):
-            break
-        headers += line
-    else:
-        raise GeneratorInputError("file: %s - end pattern [%s] not found!" %
-                                  (funcs_f.name, end_regex))
-
-    return headers
-
-
-def validate_dependency(dependency):
-    """
-    Validates a C macro and raises GeneratorInputError on invalid input.
-    :param dependency: Input macro dependency
-    :return: input dependency stripped of leading & trailing white spaces.
-    """
-    dependency = dependency.strip()
-    if not re.match(CONDITION_REGEX, dependency, re.I):
-        raise GeneratorInputError('Invalid dependency %s' % dependency)
-    return dependency
-
-
-def parse_dependencies(inp_str):
-    """
-    Parses dependencies out of inp_str, validates them and returns a
-    list of macros.
-
-    :param inp_str: Input string with macros delimited by ':'.
-    :return: list of dependencies
-    """
-    dependencies = list(map(validate_dependency, inp_str.split(':')))
-    return dependencies
-
-
-def parse_suite_dependencies(funcs_f):
-    """
-    Parses test suite dependencies specified at the top of a
-    .function file, that starts with pattern BEGIN_DEPENDENCIES
-    and end with END_DEPENDENCIES. Dependencies are specified
-    after pattern 'depends_on:' and are delimited by ':'.
-
-    :param funcs_f: file object for .function file
-    :return: List of test suite dependencies.
-    """
-    dependencies = []
-    for line in funcs_f:
-        match = re.search(DEPENDENCY_REGEX, line.strip())
-        if match:
-            try:
-                dependencies = parse_dependencies(match.group('dependencies'))
-            except GeneratorInputError as error:
-                raise GeneratorInputError(
-                    str(error) + " - %s:%d" % (funcs_f.name, funcs_f.line_no))
-        if re.search(END_DEP_REGEX, line):
-            break
-    else:
-        raise GeneratorInputError("file: %s - end dependency pattern [%s]"
-                                  " not found!" % (funcs_f.name,
-                                                   END_DEP_REGEX))
-
-    return dependencies
-
-
-def parse_function_dependencies(line):
-    """
-    Parses function dependencies, that are in the same line as
-    comment BEGIN_CASE. Dependencies are specified after pattern
-    'depends_on:' and are delimited by ':'.
-
-    :param line: Line from .function file that has dependencies.
-    :return: List of dependencies.
-    """
-    dependencies = []
-    match = re.search(BEGIN_CASE_REGEX, line)
-    dep_str = match.group('depends_on')
-    if dep_str:
-        match = re.search(DEPENDENCY_REGEX, dep_str)
-        if match:
-            dependencies += parse_dependencies(match.group('dependencies'))
-
-    return dependencies
-
-
-ARGUMENT_DECLARATION_REGEX = re.compile(r'(.+?) ?(?:\bconst\b)? ?(\w+)\Z', re.S)
-def parse_function_argument(arg, arg_idx, args, local_vars, args_dispatch):
-    """
-    Parses one test function's argument declaration.
-
-    :param arg: argument declaration.
-    :param arg_idx: current wrapper argument index.
-    :param args: accumulator of arguments' internal types.
-    :param local_vars: accumulator of internal variable declarations.
-    :param args_dispatch: accumulator of argument usage expressions.
-    :return: the number of new wrapper arguments,
-             or None if the argument declaration is invalid.
-    """
-    # Normalize whitespace
-    arg = arg.strip()
-    arg = re.sub(r'\s*\*\s*', r'*', arg)
-    arg = re.sub(r'\s+', r' ', arg)
-    # Extract name and type
-    m = ARGUMENT_DECLARATION_REGEX.search(arg)
-    if not m:
-        # E.g. "int x[42]"
-        return None
-    typ, _ = m.groups()
-    if typ in SIGNED_INTEGER_TYPES:
-        args.append('int')
-        args_dispatch.append('((mbedtls_test_argument_t *) params[%d])->sint' % arg_idx)
-        return 1
-    if typ in STRING_TYPES:
-        args.append('char*')
-        args_dispatch.append('(char *) params[%d]' % arg_idx)
-        return 1
-    if typ in DATA_TYPES:
-        args.append('hex')
-        # create a structure
-        pointer_initializer = '(uint8_t *) params[%d]' % arg_idx
-        len_initializer = '((mbedtls_test_argument_t *) params[%d])->len' % (arg_idx+1)
-        local_vars.append('    data_t data%d = {%s, %s};\n' %
-                          (arg_idx, pointer_initializer, len_initializer))
-        args_dispatch.append('&data%d' % arg_idx)
-        return 2
-    return None
-
-ARGUMENT_LIST_REGEX = re.compile(r'\((.*?)\)', re.S)
-def parse_function_arguments(line):
-    """
-    Parses test function signature for validation and generates
-    a dispatch wrapper function that translates input test vectors
-    read from the data file into test function arguments.
-
-    :param line: Line from .function file that has a function
-                 signature.
-    :return: argument list, local variables for
-             wrapper function and argument dispatch code.
-    """
-    # Process arguments, ex: <type> arg1, <type> arg2 )
-    # This script assumes that the argument list is terminated by ')'
-    # i.e. the test functions will not have a function pointer
-    # argument.
-    m = ARGUMENT_LIST_REGEX.search(line)
-    arg_list = m.group(1).strip()
-    if arg_list in ['', 'void']:
-        return [], '', []
-    args = []
-    local_vars = []
-    args_dispatch = []
-    arg_idx = 0
-    for arg in arg_list.split(','):
-        indexes = parse_function_argument(arg, arg_idx,
-                                          args, local_vars, args_dispatch)
-        if indexes is None:
-            raise ValueError("Test function arguments can only be 'int', "
-                             "'char *' or 'data_t'\n%s" % line)
-        arg_idx += indexes
-
-    return args, ''.join(local_vars), args_dispatch
-
-
-def generate_function_code(name, code, local_vars, args_dispatch,
-                           dependencies):
-    """
-    Generate function code with preprocessor checks and parameter dispatch
-    wrapper.
-
-    :param name: Function name
-    :param code: Function code
-    :param local_vars: Local variables for function wrapper
-    :param args_dispatch: Argument dispatch code
-    :param dependencies: Preprocessor dependencies list
-    :return: Final function code
-    """
-    # Add exit label if not present
-    if code.find('exit:') == -1:
-        split_code = code.rsplit('}', 1)
-        if len(split_code) == 2:
-            code = """exit:
-    ;
-}""".join(split_code)
-
-    code += gen_function_wrapper(name, local_vars, args_dispatch)
-    preprocessor_check_start, preprocessor_check_end = \
-        gen_dependencies(dependencies)
-    return preprocessor_check_start + code + preprocessor_check_end
-
-COMMENT_START_REGEX = re.compile(r'/[*/]')
-
-def skip_comments(line, stream):
-    """Remove comments in line.
-
-    If the line contains an unfinished comment, read more lines from stream
-    until the line that contains the comment.
-
-    :return: The original line with inner comments replaced by spaces.
-             Trailing comments and whitespace may be removed completely.
-    """
-    pos = 0
-    while True:
-        opening = COMMENT_START_REGEX.search(line, pos)
-        if not opening:
-            break
-        if line[opening.start(0) + 1] == '/': # //...
-            continuation = line
-            # Count the number of line breaks, to keep line numbers aligned
-            # in the output.
-            line_count = 1
-            while continuation.endswith('\\\n'):
-                # This errors out if the file ends with an unfinished line
-                # comment. That's acceptable to not complicate the code further.
-                continuation = next(stream)
-                line_count += 1
-            return line[:opening.start(0)].rstrip() + '\n' * line_count
-        # Parsing /*...*/, looking for the end
-        closing = line.find('*/', opening.end(0))
-        while closing == -1:
-            # This errors out if the file ends with an unfinished block
-            # comment. That's acceptable to not complicate the code further.
-            line += next(stream)
-            closing = line.find('*/', opening.end(0))
-        pos = closing + 2
-        # Replace inner comment by spaces. There needs to be at least one space
-        # for things like 'int/*ihatespaces*/foo'. Go further and preserve the
-        # width of the comment and line breaks, this way positions in error
-        # messages remain correct.
-        line = (line[:opening.start(0)] +
-                re.sub(r'.', r' ', line[opening.start(0):pos]) +
-                line[pos:])
-    # Strip whitespace at the end of lines (it's irrelevant to error messages).
-    return re.sub(r' +(\n|\Z)', r'\1', line)
-
-def parse_function_code(funcs_f, dependencies, suite_dependencies):
-    """
-    Parses out a function from function file object and generates
-    function and dispatch code.
-
-    :param funcs_f: file object of the functions file.
-    :param dependencies: List of dependencies
-    :param suite_dependencies: List of test suite dependencies
-    :return: Function name, arguments, function code and dispatch code.
-    """
-    line_directive = '#line %d "%s"\n' % (funcs_f.line_no + 1, funcs_f.name)
-    code = ''
-    has_exit_label = False
-    for line in funcs_f:
-        # Check function signature. Function signature may be split
-        # across multiple lines. Here we try to find the start of
-        # arguments list, then remove '\n's and apply the regex to
-        # detect function start.
-        line = skip_comments(line, funcs_f)
-        up_to_arg_list_start = code + line[:line.find('(') + 1]
-        match = re.match(TEST_FUNCTION_VALIDATION_REGEX,
-                         up_to_arg_list_start.replace('\n', ' '), re.I)
-        if match:
-            # check if we have full signature i.e. split in more lines
-            name = match.group('func_name')
-            if not re.match(FUNCTION_ARG_LIST_END_REGEX, line):
-                for lin in funcs_f:
-                    line += skip_comments(lin, funcs_f)
-                    if re.search(FUNCTION_ARG_LIST_END_REGEX, line):
-                        break
-            args, local_vars, args_dispatch = parse_function_arguments(
-                line)
-            code += line
-            break
-        code += line
-    else:
-        raise GeneratorInputError("file: %s - Test functions not found!" %
-                                  funcs_f.name)
-
-    # Prefix test function name with 'test_'
-    code = code.replace(name, 'test_' + name, 1)
-    name = 'test_' + name
-
-    # If a test function has no arguments then add 'void' argument to
-    # avoid "-Wstrict-prototypes" warnings from clang
-    if len(args) == 0:
-        code = code.replace('()', '(void)', 1)
-
-    for line in funcs_f:
-        if re.search(END_CASE_REGEX, line):
-            break
-        if not has_exit_label:
-            has_exit_label = \
-                re.search(EXIT_LABEL_REGEX, line.strip()) is not None
-        code += line
-    else:
-        raise GeneratorInputError("file: %s - end case pattern [%s] not "
-                                  "found!" % (funcs_f.name, END_CASE_REGEX))
-
-    code = line_directive + code
-    code = generate_function_code(name, code, local_vars, args_dispatch,
-                                  dependencies)
-    dispatch_code = gen_dispatch(name, suite_dependencies + dependencies)
-    return (name, args, code, dispatch_code)
-
-
-def parse_functions(funcs_f):
-    """
-    Parses a test_suite_xxx.function file and returns information
-    for generating a C source file for the test suite.
-
-    :param funcs_f: file object of the functions file.
-    :return: List of test suite dependencies, test function dispatch
-             code, function code and a dict with function identifiers
-             and arguments info.
-    """
-    suite_helpers = ''
-    suite_dependencies = []
-    suite_functions = ''
-    func_info = {}
-    function_idx = 0
-    dispatch_code = ''
-    for line in funcs_f:
-        if re.search(BEGIN_HEADER_REGEX, line):
-            suite_helpers += parse_until_pattern(funcs_f, END_HEADER_REGEX)
-        elif re.search(BEGIN_SUITE_HELPERS_REGEX, line):
-            suite_helpers += parse_until_pattern(funcs_f,
-                                                 END_SUITE_HELPERS_REGEX)
-        elif re.search(BEGIN_DEP_REGEX, line):
-            suite_dependencies += parse_suite_dependencies(funcs_f)
-        elif re.search(BEGIN_CASE_REGEX, line):
-            try:
-                dependencies = parse_function_dependencies(line)
-            except GeneratorInputError as error:
-                raise GeneratorInputError(
-                    "%s:%d: %s" % (funcs_f.name, funcs_f.line_no,
-                                   str(error)))
-            func_name, args, func_code, func_dispatch =\
-                parse_function_code(funcs_f, dependencies, suite_dependencies)
-            suite_functions += func_code
-            # Generate dispatch code and enumeration info
-            if func_name in func_info:
-                raise GeneratorInputError(
-                    "file: %s - function %s re-declared at line %d" %
-                    (funcs_f.name, func_name, funcs_f.line_no))
-            func_info[func_name] = (function_idx, args)
-            dispatch_code += '/* Function Id: %d */\n' % function_idx
-            dispatch_code += func_dispatch
-            function_idx += 1
-
-    func_code = (suite_helpers +
-                 suite_functions).join(gen_dependencies(suite_dependencies))
-    return suite_dependencies, dispatch_code, func_code, func_info
-
-
-def escaped_split(inp_str, split_char):
-    """
-    Split inp_str on character split_char but ignore if escaped.
-    Since, return value is used to write back to the intermediate
-    data file, any escape characters in the input are retained in the
-    output.
-
-    :param inp_str: String to split
-    :param split_char: Split character
-    :return: List of splits
-    """
-    if len(split_char) > 1:
-        raise ValueError('Expected split character. Found string!')
-    out = re.sub(r'(\\.)|' + split_char,
-                 lambda m: m.group(1) or '\n', inp_str,
-                 len(inp_str)).split('\n')
-    out = [x for x in out if x]
-    return out
-
-
-def parse_test_data(data_f):
-    """
-    Parses .data file for each test case name, test function name,
-    test dependencies and test arguments. This information is
-    correlated with the test functions file for generating an
-    intermediate data file replacing the strings for test function
-    names, dependencies and integer constant expressions with
-    identifiers. Mainly for optimising space for on-target
-    execution.
-
-    :param data_f: file object of the data file.
-    :return: Generator that yields line number, test name, function name,
-             dependency list and function argument list.
-    """
-    __state_read_name = 0
-    __state_read_args = 1
-    state = __state_read_name
-    dependencies = []
-    name = ''
-    for line in data_f:
-        line = line.strip()
-        # Skip comments
-        if line.startswith('#'):
-            continue
-
-        # Blank line indicates end of test
-        if not line:
-            if state == __state_read_args:
-                raise GeneratorInputError("[%s:%d] Newline before arguments. "
-                                          "Test function and arguments "
-                                          "missing for %s" %
-                                          (data_f.name, data_f.line_no, name))
-            continue
-
-        if state == __state_read_name:
-            # Read test name
-            name = line
-            state = __state_read_args
-        elif state == __state_read_args:
-            # Check dependencies
-            match = re.search(DEPENDENCY_REGEX, line)
-            if match:
-                try:
-                    dependencies = parse_dependencies(
-                        match.group('dependencies'))
-                except GeneratorInputError as error:
-                    raise GeneratorInputError(
-                        str(error) + " - %s:%d" %
-                        (data_f.name, data_f.line_no))
-            else:
-                # Read test vectors
-                parts = escaped_split(line, ':')
-                test_function = parts[0]
-                args = parts[1:]
-                yield data_f.line_no, name, test_function, dependencies, args
-                dependencies = []
-                state = __state_read_name
-    if state == __state_read_args:
-        raise GeneratorInputError("[%s:%d] Newline before arguments. "
-                                  "Test function and arguments missing for "
-                                  "%s" % (data_f.name, data_f.line_no, name))
-
-
-def gen_dep_check(dep_id, dep):
-    """
-    Generate code for checking dependency with the associated
-    identifier.
-
-    :param dep_id: Dependency identifier
-    :param dep: Dependency macro
-    :return: Dependency check code
-    """
-    if dep_id < 0:
-        raise GeneratorInputError("Dependency Id should be a positive "
-                                  "integer.")
-    _not, dep = ('!', dep[1:]) if dep[0] == '!' else ('', dep)
-    if not dep:
-        raise GeneratorInputError("Dependency should not be an empty string.")
-
-    dependency = re.match(CONDITION_REGEX, dep, re.I)
-    if not dependency:
-        raise GeneratorInputError('Invalid dependency %s' % dep)
-
-    _defined = '' if dependency.group(2) else 'defined'
-    _cond = dependency.group(2) if dependency.group(2) else ''
-    _value = dependency.group(3) if dependency.group(3) else ''
-
-    dep_check = '''
-        case {id}:
-            {{
-#if {_not}{_defined}({macro}{_cond}{_value})
-                ret = DEPENDENCY_SUPPORTED;
-#else
-                ret = DEPENDENCY_NOT_SUPPORTED;
-#endif
-            }}
-            break;'''.format(_not=_not, _defined=_defined,
-                             macro=dependency.group(1), id=dep_id,
-                             _cond=_cond, _value=_value)
-    return dep_check
-
-
-def gen_expression_check(exp_id, exp):
-    """
-    Generates code for evaluating an integer expression using
-    associated expression Id.
-
-    :param exp_id: Expression Identifier
-    :param exp: Expression/Macro
-    :return: Expression check code
-    """
-    if exp_id < 0:
-        raise GeneratorInputError("Expression Id should be a positive "
-                                  "integer.")
-    if not exp:
-        raise GeneratorInputError("Expression should not be an empty string.")
-    exp_code = '''
-        case {exp_id}:
-            {{
-                *out_value = {expression};
-            }}
-            break;'''.format(exp_id=exp_id, expression=exp)
-    return exp_code
-
-
-def write_dependencies(out_data_f, test_dependencies, unique_dependencies):
-    """
-    Write dependencies to intermediate test data file, replacing
-    the string form with identifiers. Also, generates dependency
-    check code.
-
-    :param out_data_f: Output intermediate data file
-    :param test_dependencies: Dependencies
-    :param unique_dependencies: Mutable list to track unique dependencies
-           that are global to this re-entrant function.
-    :return: returns dependency check code.
-    """
-    dep_check_code = ''
-    if test_dependencies:
-        out_data_f.write('depends_on')
-        for dep in test_dependencies:
-            if dep not in unique_dependencies:
-                unique_dependencies.append(dep)
-                dep_id = unique_dependencies.index(dep)
-                dep_check_code += gen_dep_check(dep_id, dep)
-            else:
-                dep_id = unique_dependencies.index(dep)
-            out_data_f.write(':' + str(dep_id))
-        out_data_f.write('\n')
-    return dep_check_code
-
-
-INT_VAL_REGEX = re.compile(r'-?(\d+|0x[0-9a-f]+)$', re.I)
-def val_is_int(val: str) -> bool:
-    """Whether val is suitable as an 'int' parameter in the .datax file."""
-    if not INT_VAL_REGEX.match(val):
-        return False
-    # Limit the range to what is guaranteed to get through strtol()
-    return abs(int(val, 0)) <= 0x7fffffff
-
-def write_parameters(out_data_f, test_args, func_args, unique_expressions):
-    """
-    Writes test parameters to the intermediate data file, replacing
-    the string form with identifiers. Also, generates expression
-    check code.
-
-    :param out_data_f: Output intermediate data file
-    :param test_args: Test parameters
-    :param func_args: Function arguments
-    :param unique_expressions: Mutable list to track unique
-           expressions that are global to this re-entrant function.
-    :return: Returns expression check code.
-    """
-    expression_code = ''
-    for i, _ in enumerate(test_args):
-        typ = func_args[i]
-        val = test_args[i]
-
-        # Pass small integer constants literally. This reduces the size of
-        # the C code. Register anything else as an expression.
-        if typ == 'int' and not val_is_int(val):
-            typ = 'exp'
-            if val not in unique_expressions:
-                unique_expressions.append(val)
-                # exp_id can be derived from len(). But for
-                # readability and consistency with case of existing
-                # let's use index().
-                exp_id = unique_expressions.index(val)
-                expression_code += gen_expression_check(exp_id, val)
-                val = exp_id
-            else:
-                val = unique_expressions.index(val)
-        out_data_f.write(':' + typ + ':' + str(val))
-    out_data_f.write('\n')
-    return expression_code
-
-
-def gen_suite_dep_checks(suite_dependencies, dep_check_code, expression_code):
-    """
-    Generates preprocessor checks for test suite dependencies.
-
-    :param suite_dependencies: Test suite dependencies read from the
-            .function file.
-    :param dep_check_code: Dependency check code
-    :param expression_code: Expression check code
-    :return: Dependency and expression code guarded by test suite
-             dependencies.
-    """
-    if suite_dependencies:
-        preprocessor_check = gen_dependencies_one_line(suite_dependencies)
-        dep_check_code = '''
-{preprocessor_check}
-{code}
-#endif
-'''.format(preprocessor_check=preprocessor_check, code=dep_check_code)
-        expression_code = '''
-{preprocessor_check}
-{code}
-#endif
-'''.format(preprocessor_check=preprocessor_check, code=expression_code)
-    return dep_check_code, expression_code
-
-
-def get_function_info(func_info, function_name, line_no):
-    """Look up information about a test function by name.
-
-    Raise an informative expression if function_name is not found.
-
-    :param func_info: dictionary mapping function names to their information.
-    :param function_name: the function name as written in the .function and
-                          .data files.
-    :param line_no: line number for error messages.
-    :return Function information (id, args).
-    """
-    test_function_name = 'test_' + function_name
-    if test_function_name not in func_info:
-        raise GeneratorInputError("%d: Function %s not found!" %
-                                  (line_no, test_function_name))
-    return func_info[test_function_name]
-
-
-def gen_from_test_data(data_f, out_data_f, func_info, suite_dependencies):
-    """
-    This function reads test case name, dependencies and test vectors
-    from the .data file. This information is correlated with the test
-    functions file for generating an intermediate data file replacing
-    the strings for test function names, dependencies and integer
-    constant expressions with identifiers. Mainly for optimising
-    space for on-target execution.
-    It also generates test case dependency check code and expression
-    evaluation code.
-
-    :param data_f: Data file object
-    :param out_data_f: Output intermediate data file
-    :param func_info: Dict keyed by function and with function id
-           and arguments info
-    :param suite_dependencies: Test suite dependencies
-    :return: Returns dependency and expression check code
-    """
-    unique_dependencies = []
-    unique_expressions = []
-    dep_check_code = ''
-    expression_code = ''
-    for line_no, test_name, function_name, test_dependencies, test_args in \
-            parse_test_data(data_f):
-        out_data_f.write(test_name + '\n')
-
-        # Write dependencies
-        dep_check_code += write_dependencies(out_data_f, test_dependencies,
-                                             unique_dependencies)
-
-        # Write test function name
-        func_id, func_args = \
-            get_function_info(func_info, function_name, line_no)
-        out_data_f.write(str(func_id))
-
-        # Write parameters
-        if len(test_args) != len(func_args):
-            raise GeneratorInputError("%d: Invalid number of arguments in test "
-                                      "%s. See function %s signature." %
-                                      (line_no, test_name, function_name))
-        expression_code += write_parameters(out_data_f, test_args, func_args,
-                                            unique_expressions)
-
-        # Write a newline as test case separator
-        out_data_f.write('\n')
-
-    dep_check_code, expression_code = gen_suite_dep_checks(
-        suite_dependencies, dep_check_code, expression_code)
-    return dep_check_code, expression_code
-
-
-def add_input_info(funcs_file, data_file, template_file,
-                   c_file, snippets):
-    """
-    Add generator input info in snippets.
-
-    :param funcs_file: Functions file object
-    :param data_file: Data file object
-    :param template_file: Template file object
-    :param c_file: Output C file object
-    :param snippets: Dictionary to contain code pieces to be
-                     substituted in the template.
-    :return:
-    """
-    snippets['test_file'] = c_file
-    snippets['test_main_file'] = template_file
-    snippets['test_case_file'] = funcs_file
-    snippets['test_case_data_file'] = data_file
-
-
-def read_code_from_input_files(platform_file, helpers_file,
-                               out_data_file, snippets):
-    """
-    Read code from input files and create substitutions for replacement
-    strings in the template file.
-
-    :param platform_file: Platform file object
-    :param helpers_file: Helper functions file object
-    :param out_data_file: Output intermediate data file object
-    :param snippets: Dictionary to contain code pieces to be
-                     substituted in the template.
-    :return:
-    """
-    # Read helpers
-    with open(helpers_file, 'r') as help_f, open(platform_file, 'r') as \
-            platform_f:
-        snippets['test_common_helper_file'] = helpers_file
-        snippets['test_common_helpers'] = help_f.read()
-        snippets['test_platform_file'] = platform_file
-        snippets['platform_code'] = platform_f.read().replace(
-            'DATA_FILE', out_data_file.replace('\\', '\\\\'))  # escape '\'
-
-
-def write_test_source_file(template_file, c_file, snippets):
-    """
-    Write output source file with generated source code.
-
-    :param template_file: Template file name
-    :param c_file: Output source file
-    :param snippets: Generated and code snippets
-    :return:
-    """
-
-    # Create a placeholder pattern with the correct named capture groups
-    # to override the default provided with Template.
-    # Match nothing (no way of escaping placeholders).
-    escaped = "(?P<escaped>(?!))"
-    # Match the "__MBEDTLS_TEST_TEMPLATE__PLACEHOLDER_NAME" pattern.
-    named = "__MBEDTLS_TEST_TEMPLATE__(?P<named>[A-Z][_A-Z0-9]*)"
-    # Match nothing (no braced placeholder syntax).
-    braced = "(?P<braced>(?!))"
-    # If not already matched, a "__MBEDTLS_TEST_TEMPLATE__" prefix is invalid.
-    invalid = "(?P<invalid>__MBEDTLS_TEST_TEMPLATE__)"
-    placeholder_pattern = re.compile("|".join([escaped, named, braced, invalid]))
-
-    with open(template_file, 'r') as template_f, open(c_file, 'w') as c_f:
-        for line_no, line in enumerate(template_f.readlines(), 1):
-            # Update line number. +1 as #line directive sets next line number
-            snippets['line_no'] = line_no + 1
-            template = string.Template(line)
-            template.pattern = placeholder_pattern
-            snippets = {k.upper():v for (k, v) in snippets.items()}
-            code = template.substitute(**snippets)
-            c_f.write(code)
-
-
-def parse_function_file(funcs_file, snippets):
-    """
-    Parse function file and generate function dispatch code.
-
-    :param funcs_file: Functions file name
-    :param snippets: Dictionary to contain code pieces to be
-                     substituted in the template.
-    :return:
-    """
-    with FileWrapper(funcs_file) as funcs_f:
-        suite_dependencies, dispatch_code, func_code, func_info = \
-            parse_functions(funcs_f)
-        snippets['functions_code'] = func_code
-        snippets['dispatch_code'] = dispatch_code
-        return suite_dependencies, func_info
-
-
-def generate_intermediate_data_file(data_file, out_data_file,
-                                    suite_dependencies, func_info, snippets):
-    """
-    Generates intermediate data file from input data file and
-    information read from functions file.
-
-    :param data_file: Data file name
-    :param out_data_file: Output/Intermediate data file
-    :param suite_dependencies: List of suite dependencies.
-    :param func_info: Function info parsed from functions file.
-    :param snippets: Dictionary to contain code pieces to be
-                     substituted in the template.
-    :return:
-    """
-    with FileWrapper(data_file) as data_f, \
-            open(out_data_file, 'w') as out_data_f:
-        dep_check_code, expression_code = gen_from_test_data(
-            data_f, out_data_f, func_info, suite_dependencies)
-        snippets['dep_check_code'] = dep_check_code
-        snippets['expression_code'] = expression_code
-
-
-def generate_code(**input_info):
-    """
-    Generates C source code from test suite file, data file, common
-    helpers file and platform file.
-
-    input_info expands to following parameters:
-    funcs_file: Functions file object
-    data_file: Data file object
-    template_file: Template file object
-    platform_file: Platform file object
-    helpers_file: Helper functions file object
-    suites_dir: Test suites dir
-    c_file: Output C file object
-    out_data_file: Output intermediate data file object
-    :return:
-    """
-    funcs_file = input_info['funcs_file']
-    data_file = input_info['data_file']
-    template_file = input_info['template_file']
-    platform_file = input_info['platform_file']
-    helpers_file = input_info['helpers_file']
-    suites_dir = input_info['suites_dir']
-    c_file = input_info['c_file']
-    out_data_file = input_info['out_data_file']
-    for name, path in [('Functions file', funcs_file),
-                       ('Data file', data_file),
-                       ('Template file', template_file),
-                       ('Platform file', platform_file),
-                       ('Helpers code file', helpers_file),
-                       ('Suites dir', suites_dir)]:
-        if not os.path.exists(path):
-            raise IOError("ERROR: %s [%s] not found!" % (name, path))
-
-    snippets = {'generator_script': os.path.basename(__file__)}
-    read_code_from_input_files(platform_file, helpers_file,
-                               out_data_file, snippets)
-    add_input_info(funcs_file, data_file, template_file,
-                   c_file, snippets)
-    suite_dependencies, func_info = parse_function_file(funcs_file, snippets)
-    generate_intermediate_data_file(data_file, out_data_file,
-                                    suite_dependencies, func_info, snippets)
-    write_test_source_file(template_file, c_file, snippets)
-
-
-def main():
-    """
-    Command line parser.
-
-    :return:
-    """
-    parser = argparse.ArgumentParser(
-        description='Dynamically generate test suite code.')
-
-    parser.add_argument("-f", "--functions-file",
-                        dest="funcs_file",
-                        help="Functions file",
-                        metavar="FUNCTIONS_FILE",
-                        required=True)
-
-    parser.add_argument("-d", "--data-file",
-                        dest="data_file",
-                        help="Data file",
-                        metavar="DATA_FILE",
-                        required=True)
-
-    parser.add_argument("-t", "--template-file",
-                        dest="template_file",
-                        help="Template file",
-                        metavar="TEMPLATE_FILE",
-                        required=True)
-
-    parser.add_argument("-s", "--suites-dir",
-                        dest="suites_dir",
-                        help="Suites dir",
-                        metavar="SUITES_DIR",
-                        required=True)
-
-    parser.add_argument("--helpers-file",
-                        dest="helpers_file",
-                        help="Helpers file",
-                        metavar="HELPERS_FILE",
-                        required=True)
-
-    parser.add_argument("-p", "--platform-file",
-                        dest="platform_file",
-                        help="Platform code file",
-                        metavar="PLATFORM_FILE",
-                        required=True)
-
-    parser.add_argument("-o", "--out-dir",
-                        dest="out_dir",
-                        help="Dir where generated code and scripts are copied",
-                        metavar="OUT_DIR",
-                        required=True)
-
-    args = parser.parse_args()
-
-    data_file_name = os.path.basename(args.data_file)
-    data_name = os.path.splitext(data_file_name)[0]
-
-    out_c_file = os.path.join(args.out_dir, data_name + '.c')
-    out_data_file = os.path.join(args.out_dir, data_name + '.datax')
-
-    out_c_file_dir = os.path.dirname(out_c_file)
-    out_data_file_dir = os.path.dirname(out_data_file)
-    for directory in [out_c_file_dir, out_data_file_dir]:
-        if not os.path.exists(directory):
-            os.makedirs(directory)
-
-    generate_code(funcs_file=args.funcs_file, data_file=args.data_file,
-                  template_file=args.template_file,
-                  platform_file=args.platform_file,
-                  helpers_file=args.helpers_file, suites_dir=args.suites_dir,
-                  c_file=out_c_file, out_data_file=out_data_file)
-
-
-if __name__ == "__main__":
-    try:
-        main()
-    except GeneratorInputError as err:
-        sys.exit("%s: input error: %s" %
-                 (os.path.basename(sys.argv[0]), str(err)))
diff --git a/tests/scripts/scripts_path.py b/tests/scripts/scripts_path.py
index 5d83f29..ce2afcf 100644
--- a/tests/scripts/scripts_path.py
+++ b/tests/scripts/scripts_path.py
@@ -15,3 +15,6 @@
 sys.path.append(os.path.join(os.path.dirname(__file__),
                              os.path.pardir, os.path.pardir,
                              'scripts'))
+sys.path.append(os.path.join(os.path.dirname(__file__),
+                             os.path.pardir, os.path.pardir,
+                             'framework', 'scripts'))
diff --git a/tests/scripts/test-ref-configs.pl b/tests/scripts/test-ref-configs.pl
index 055023a..5557de3 100755
--- a/tests/scripts/test-ref-configs.pl
+++ b/tests/scripts/test-ref-configs.pl
@@ -17,32 +17,26 @@
 
 my %configs = (
     'config-ccm-psk-tls1_2.h' => {
-        'compat' => '-m tls12 -f \'^TLS-PSK-WITH-AES-...-CCM-8\'',
-        'test_again_with_use_psa' => 1
+        'compat' => '-m tls12 -f \'^TLS_PSK_WITH_AES_..._CCM_8\'',
     },
     'config-ccm-psk-dtls1_2.h' => {
-        'compat' => '-m dtls12 -f \'^TLS-PSK-WITH-AES-...-CCM-8\'',
+        'compat' => '-m dtls12 -f \'^TLS_PSK_WITH_AES_..._CCM_8\'',
         'opt' => ' ',
         'opt_needs_debug' => 1,
-        'test_again_with_use_psa' => 1
     },
     'config-no-entropy.h' => {
     },
     'config-suite-b.h' => {
-        'compat' => "-m tls12 -f 'ECDHE-ECDSA.*AES.*GCM' -p mbedTLS",
-        'test_again_with_use_psa' => 1,
+        'compat' => "-m tls12 -f 'ECDHE_ECDSA.*AES.*GCM' -p mbedTLS",
         'opt' => ' ',
         'opt_needs_debug' => 1,
     },
     'config-symmetric-only.h' => {
-        'test_again_with_use_psa' => 0, # Uses PSA by default, no need to test it twice
     },
     'config-tfm.h' => {
-        'test_again_with_use_psa' => 0, # Uses PSA by default, no need to test it twice
     },
     'config-thread.h' => {
         'opt' => '-f ECJPAKE.*nolog',
-        'test_again_with_use_psa' => 1,
     },
 );
 
@@ -148,7 +142,10 @@
 }
 
 foreach my $conf ( @configs_to_test ) {
-    my $test_with_psa = $configs{$conf}{'test_again_with_use_psa'};
+    system("grep '//#define MBEDTLS_USE_PSA_CRYPTO' configs/$conf > /dev/null");
+    die "grep ... configs/$conf: $!" if $? != 0 && $? != 0x100;
+    my $test_with_psa = $? == 0;
+
     if ( $test_with_psa )
     {
         perform_test( $conf, $configs{$conf}, $test_with_psa );
diff --git a/tests/scripts/test_generate_test_code.py b/tests/scripts/test_generate_test_code.py
deleted file mode 100755
index abc46a7..0000000
--- a/tests/scripts/test_generate_test_code.py
+++ /dev/null
@@ -1,1915 +0,0 @@
-#!/usr/bin/env python3
-# Unit test for generate_test_code.py
-#
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
-
-"""
-Unit tests for generate_test_code.py
-"""
-
-from io import StringIO
-from unittest import TestCase, main as unittest_main
-from unittest.mock import patch
-
-from generate_test_code import gen_dependencies, gen_dependencies_one_line
-from generate_test_code import gen_function_wrapper, gen_dispatch
-from generate_test_code import parse_until_pattern, GeneratorInputError
-from generate_test_code import parse_suite_dependencies
-from generate_test_code import parse_function_dependencies
-from generate_test_code import parse_function_arguments, parse_function_code
-from generate_test_code import parse_functions, END_HEADER_REGEX
-from generate_test_code import END_SUITE_HELPERS_REGEX, escaped_split
-from generate_test_code import parse_test_data, gen_dep_check
-from generate_test_code import gen_expression_check, write_dependencies
-from generate_test_code import write_parameters, gen_suite_dep_checks
-from generate_test_code import gen_from_test_data
-
-
-class GenDep(TestCase):
-    """
-    Test suite for function gen_dep()
-    """
-
-    def test_dependencies_list(self):
-        """
-        Test that gen_dep() correctly creates dependencies for given
-        dependency list.
-        :return:
-        """
-        dependencies = ['DEP1', 'DEP2']
-        dep_start, dep_end = gen_dependencies(dependencies)
-        preprocessor1, preprocessor2 = dep_start.splitlines()
-        endif1, endif2 = dep_end.splitlines()
-        self.assertEqual(preprocessor1, '#if defined(DEP1)',
-                         'Preprocessor generated incorrectly')
-        self.assertEqual(preprocessor2, '#if defined(DEP2)',
-                         'Preprocessor generated incorrectly')
-        self.assertEqual(endif1, '#endif /* DEP2 */',
-                         'Preprocessor generated incorrectly')
-        self.assertEqual(endif2, '#endif /* DEP1 */',
-                         'Preprocessor generated incorrectly')
-
-    def test_disabled_dependencies_list(self):
-        """
-        Test that gen_dep() correctly creates dependencies for given
-        dependency list.
-        :return:
-        """
-        dependencies = ['!DEP1', '!DEP2']
-        dep_start, dep_end = gen_dependencies(dependencies)
-        preprocessor1, preprocessor2 = dep_start.splitlines()
-        endif1, endif2 = dep_end.splitlines()
-        self.assertEqual(preprocessor1, '#if !defined(DEP1)',
-                         'Preprocessor generated incorrectly')
-        self.assertEqual(preprocessor2, '#if !defined(DEP2)',
-                         'Preprocessor generated incorrectly')
-        self.assertEqual(endif1, '#endif /* !DEP2 */',
-                         'Preprocessor generated incorrectly')
-        self.assertEqual(endif2, '#endif /* !DEP1 */',
-                         'Preprocessor generated incorrectly')
-
-    def test_mixed_dependencies_list(self):
-        """
-        Test that gen_dep() correctly creates dependencies for given
-        dependency list.
-        :return:
-        """
-        dependencies = ['!DEP1', 'DEP2']
-        dep_start, dep_end = gen_dependencies(dependencies)
-        preprocessor1, preprocessor2 = dep_start.splitlines()
-        endif1, endif2 = dep_end.splitlines()
-        self.assertEqual(preprocessor1, '#if !defined(DEP1)',
-                         'Preprocessor generated incorrectly')
-        self.assertEqual(preprocessor2, '#if defined(DEP2)',
-                         'Preprocessor generated incorrectly')
-        self.assertEqual(endif1, '#endif /* DEP2 */',
-                         'Preprocessor generated incorrectly')
-        self.assertEqual(endif2, '#endif /* !DEP1 */',
-                         'Preprocessor generated incorrectly')
-
-    def test_empty_dependencies_list(self):
-        """
-        Test that gen_dep() correctly creates dependencies for given
-        dependency list.
-        :return:
-        """
-        dependencies = []
-        dep_start, dep_end = gen_dependencies(dependencies)
-        self.assertEqual(dep_start, '', 'Preprocessor generated incorrectly')
-        self.assertEqual(dep_end, '', 'Preprocessor generated incorrectly')
-
-    def test_large_dependencies_list(self):
-        """
-        Test that gen_dep() correctly creates dependencies for given
-        dependency list.
-        :return:
-        """
-        dependencies = []
-        count = 10
-        for i in range(count):
-            dependencies.append('DEP%d' % i)
-        dep_start, dep_end = gen_dependencies(dependencies)
-        self.assertEqual(len(dep_start.splitlines()), count,
-                         'Preprocessor generated incorrectly')
-        self.assertEqual(len(dep_end.splitlines()), count,
-                         'Preprocessor generated incorrectly')
-
-
-class GenDepOneLine(TestCase):
-    """
-    Test Suite for testing gen_dependencies_one_line()
-    """
-
-    def test_dependencies_list(self):
-        """
-        Test that gen_dep() correctly creates dependencies for given
-        dependency list.
-        :return:
-        """
-        dependencies = ['DEP1', 'DEP2']
-        dep_str = gen_dependencies_one_line(dependencies)
-        self.assertEqual(dep_str, '#if defined(DEP1) && defined(DEP2)',
-                         'Preprocessor generated incorrectly')
-
-    def test_disabled_dependencies_list(self):
-        """
-        Test that gen_dep() correctly creates dependencies for given
-        dependency list.
-        :return:
-        """
-        dependencies = ['!DEP1', '!DEP2']
-        dep_str = gen_dependencies_one_line(dependencies)
-        self.assertEqual(dep_str, '#if !defined(DEP1) && !defined(DEP2)',
-                         'Preprocessor generated incorrectly')
-
-    def test_mixed_dependencies_list(self):
-        """
-        Test that gen_dep() correctly creates dependencies for given
-        dependency list.
-        :return:
-        """
-        dependencies = ['!DEP1', 'DEP2']
-        dep_str = gen_dependencies_one_line(dependencies)
-        self.assertEqual(dep_str, '#if !defined(DEP1) && defined(DEP2)',
-                         'Preprocessor generated incorrectly')
-
-    def test_empty_dependencies_list(self):
-        """
-        Test that gen_dep() correctly creates dependencies for given
-        dependency list.
-        :return:
-        """
-        dependencies = []
-        dep_str = gen_dependencies_one_line(dependencies)
-        self.assertEqual(dep_str, '', 'Preprocessor generated incorrectly')
-
-    def test_large_dependencies_list(self):
-        """
-        Test that gen_dep() correctly creates dependencies for given
-        dependency list.
-        :return:
-        """
-        dependencies = []
-        count = 10
-        for i in range(count):
-            dependencies.append('DEP%d' % i)
-        dep_str = gen_dependencies_one_line(dependencies)
-        expected = '#if ' + ' && '.join(['defined(%s)' %
-                                         x for x in dependencies])
-        self.assertEqual(dep_str, expected,
-                         'Preprocessor generated incorrectly')
-
-
-class GenFunctionWrapper(TestCase):
-    """
-    Test Suite for testing gen_function_wrapper()
-    """
-
-    def test_params_unpack(self):
-        """
-        Test that params are properly unpacked in the function call.
-
-        :return:
-        """
-        code = gen_function_wrapper('test_a', '', ('a', 'b', 'c', 'd'))
-        expected = '''
-void test_a_wrapper( void ** params )
-{
-
-    test_a( a, b, c, d );
-}
-'''
-        self.assertEqual(code, expected)
-
-    def test_local(self):
-        """
-        Test that params are properly unpacked in the function call.
-
-        :return:
-        """
-        code = gen_function_wrapper('test_a',
-                                    'int x = 1;', ('x', 'b', 'c', 'd'))
-        expected = '''
-void test_a_wrapper( void ** params )
-{
-int x = 1;
-    test_a( x, b, c, d );
-}
-'''
-        self.assertEqual(code, expected)
-
-    def test_empty_params(self):
-        """
-        Test that params are properly unpacked in the function call.
-
-        :return:
-        """
-        code = gen_function_wrapper('test_a', '', ())
-        expected = '''
-void test_a_wrapper( void ** params )
-{
-    (void)params;
-
-    test_a(  );
-}
-'''
-        self.assertEqual(code, expected)
-
-
-class GenDispatch(TestCase):
-    """
-    Test suite for testing gen_dispatch()
-    """
-
-    def test_dispatch(self):
-        """
-        Test that dispatch table entry is generated correctly.
-        :return:
-        """
-        code = gen_dispatch('test_a', ['DEP1', 'DEP2'])
-        expected = '''
-#if defined(DEP1) && defined(DEP2)
-    test_a_wrapper,
-#else
-    NULL,
-#endif
-'''
-        self.assertEqual(code, expected)
-
-    def test_empty_dependencies(self):
-        """
-        Test empty dependency list.
-        :return:
-        """
-        code = gen_dispatch('test_a', [])
-        expected = '''
-    test_a_wrapper,
-'''
-        self.assertEqual(code, expected)
-
-
-class StringIOWrapper(StringIO):
-    """
-    file like class to mock file object in tests.
-    """
-    def __init__(self, file_name, data, line_no=0):
-        """
-        Init file handle.
-
-        :param file_name:
-        :param data:
-        :param line_no:
-        """
-        super(StringIOWrapper, self).__init__(data)
-        self.line_no = line_no
-        self.name = file_name
-
-    def next(self):
-        """
-        Iterator method. This method overrides base class's
-        next method and extends the next method to count the line
-        numbers as each line is read.
-
-        :return: Line read from file.
-        """
-        parent = super(StringIOWrapper, self)
-        line = parent.__next__()
-        return line
-
-    def readline(self, _length=0):
-        """
-        Wrap the base class readline.
-
-        :param length:
-        :return:
-        """
-        line = super(StringIOWrapper, self).readline()
-        if line is not None:
-            self.line_no += 1
-        return line
-
-
-class ParseUntilPattern(TestCase):
-    """
-    Test Suite for testing parse_until_pattern().
-    """
-
-    def test_suite_headers(self):
-        """
-        Test that suite headers are parsed correctly.
-
-        :return:
-        """
-        data = '''#include "mbedtls/ecp.h"
-
-#define ECP_PF_UNKNOWN     -1
-/* END_HEADER */
-'''
-        expected = '''#line 1 "test_suite_ut.function"
-#include "mbedtls/ecp.h"
-
-#define ECP_PF_UNKNOWN     -1
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data, line_no=0)
-        headers = parse_until_pattern(stream, END_HEADER_REGEX)
-        self.assertEqual(headers, expected)
-
-    def test_line_no(self):
-        """
-        Test that #line is set to correct line no. in source .function file.
-
-        :return:
-        """
-        data = '''#include "mbedtls/ecp.h"
-
-#define ECP_PF_UNKNOWN     -1
-/* END_HEADER */
-'''
-        offset_line_no = 5
-        expected = '''#line %d "test_suite_ut.function"
-#include "mbedtls/ecp.h"
-
-#define ECP_PF_UNKNOWN     -1
-''' % (offset_line_no + 1)
-        stream = StringIOWrapper('test_suite_ut.function', data,
-                                 offset_line_no)
-        headers = parse_until_pattern(stream, END_HEADER_REGEX)
-        self.assertEqual(headers, expected)
-
-    def test_no_end_header_comment(self):
-        """
-        Test that InvalidFileFormat is raised when end header comment is
-        missing.
-        :return:
-        """
-        data = '''#include "mbedtls/ecp.h"
-
-#define ECP_PF_UNKNOWN     -1
-
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        self.assertRaises(GeneratorInputError, parse_until_pattern, stream,
-                          END_HEADER_REGEX)
-
-
-class ParseSuiteDependencies(TestCase):
-    """
-    Test Suite for testing parse_suite_dependencies().
-    """
-
-    def test_suite_dependencies(self):
-        """
-
-        :return:
-        """
-        data = '''
- * depends_on:MBEDTLS_ECP_C
- * END_DEPENDENCIES
- */
-'''
-        expected = ['MBEDTLS_ECP_C']
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        dependencies = parse_suite_dependencies(stream)
-        self.assertEqual(dependencies, expected)
-
-    def test_no_end_dep_comment(self):
-        """
-        Test that InvalidFileFormat is raised when end dep comment is missing.
-        :return:
-        """
-        data = '''
-* depends_on:MBEDTLS_ECP_C
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        self.assertRaises(GeneratorInputError, parse_suite_dependencies,
-                          stream)
-
-    def test_dependencies_split(self):
-        """
-        Test that InvalidFileFormat is raised when end dep comment is missing.
-        :return:
-        """
-        data = '''
- * depends_on:MBEDTLS_ECP_C:A:B:   C  : D :F : G: !H
- * END_DEPENDENCIES
- */
-'''
-        expected = ['MBEDTLS_ECP_C', 'A', 'B', 'C', 'D', 'F', 'G', '!H']
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        dependencies = parse_suite_dependencies(stream)
-        self.assertEqual(dependencies, expected)
-
-
-class ParseFuncDependencies(TestCase):
-    """
-    Test Suite for testing parse_function_dependencies()
-    """
-
-    def test_function_dependencies(self):
-        """
-        Test that parse_function_dependencies() correctly parses function
-        dependencies.
-        :return:
-        """
-        line = '/* BEGIN_CASE ' \
-               'depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */'
-        expected = ['MBEDTLS_ENTROPY_NV_SEED', 'MBEDTLS_FS_IO']
-        dependencies = parse_function_dependencies(line)
-        self.assertEqual(dependencies, expected)
-
-    def test_no_dependencies(self):
-        """
-        Test that parse_function_dependencies() correctly parses function
-        dependencies.
-        :return:
-        """
-        line = '/* BEGIN_CASE */'
-        dependencies = parse_function_dependencies(line)
-        self.assertEqual(dependencies, [])
-
-    def test_tolerance(self):
-        """
-        Test that parse_function_dependencies() correctly parses function
-        dependencies.
-        :return:
-        """
-        line = '/* BEGIN_CASE depends_on:MBEDTLS_FS_IO: A : !B:C : F*/'
-        dependencies = parse_function_dependencies(line)
-        self.assertEqual(dependencies, ['MBEDTLS_FS_IO', 'A', '!B', 'C', 'F'])
-
-
-class ParseFuncSignature(TestCase):
-    """
-    Test Suite for parse_function_arguments().
-    """
-
-    def test_int_and_char_params(self):
-        """
-        Test int and char parameters parsing
-        :return:
-        """
-        line = 'void entropy_threshold( char * a, int b, int result )'
-        args, local, arg_dispatch = parse_function_arguments(line)
-        self.assertEqual(args, ['char*', 'int', 'int'])
-        self.assertEqual(local, '')
-        self.assertEqual(arg_dispatch,
-                         ['(char *) params[0]',
-                          '((mbedtls_test_argument_t *) params[1])->sint',
-                          '((mbedtls_test_argument_t *) params[2])->sint'])
-
-    def test_hex_params(self):
-        """
-        Test hex parameters parsing
-        :return:
-        """
-        line = 'void entropy_threshold( char * a, data_t * h, int result )'
-        args, local, arg_dispatch = parse_function_arguments(line)
-        self.assertEqual(args, ['char*', 'hex', 'int'])
-        self.assertEqual(local,
-                         '    data_t data1 = {(uint8_t *) params[1], '
-                         '((mbedtls_test_argument_t *) params[2])->len};\n')
-        self.assertEqual(arg_dispatch, ['(char *) params[0]',
-                                        '&data1',
-                                        '((mbedtls_test_argument_t *) params[3])->sint'])
-
-    def test_unsupported_arg(self):
-        """
-        Test unsupported argument type
-        :return:
-        """
-        line = 'void entropy_threshold( char * a, data_t * h, unknown_t result )'
-        self.assertRaises(ValueError, parse_function_arguments, line)
-
-    def test_empty_params(self):
-        """
-        Test no parameters (nothing between parentheses).
-        :return:
-        """
-        line = 'void entropy_threshold()'
-        args, local, arg_dispatch = parse_function_arguments(line)
-        self.assertEqual(args, [])
-        self.assertEqual(local, '')
-        self.assertEqual(arg_dispatch, [])
-
-    def test_blank_params(self):
-        """
-        Test no parameters (space between parentheses).
-        :return:
-        """
-        line = 'void entropy_threshold( )'
-        args, local, arg_dispatch = parse_function_arguments(line)
-        self.assertEqual(args, [])
-        self.assertEqual(local, '')
-        self.assertEqual(arg_dispatch, [])
-
-    def test_void_params(self):
-        """
-        Test no parameters (void keyword).
-        :return:
-        """
-        line = 'void entropy_threshold(void)'
-        args, local, arg_dispatch = parse_function_arguments(line)
-        self.assertEqual(args, [])
-        self.assertEqual(local, '')
-        self.assertEqual(arg_dispatch, [])
-
-    def test_void_space_params(self):
-        """
-        Test no parameters (void with spaces).
-        :return:
-        """
-        line = 'void entropy_threshold( void )'
-        args, local, arg_dispatch = parse_function_arguments(line)
-        self.assertEqual(args, [])
-        self.assertEqual(local, '')
-        self.assertEqual(arg_dispatch, [])
-
-
-class ParseFunctionCode(TestCase):
-    """
-    Test suite for testing parse_function_code()
-    """
-
-    def test_no_function(self):
-        """
-        Test no test function found.
-        :return:
-        """
-        data = '''
-No
-test
-function
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        err_msg = 'file: test_suite_ut.function - Test functions not found!'
-        self.assertRaisesRegex(GeneratorInputError, err_msg,
-                               parse_function_code, stream, [], [])
-
-    def test_no_end_case_comment(self):
-        """
-        Test missing end case.
-        :return:
-        """
-        data = '''
-void test_func()
-{
-}
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        err_msg = r'file: test_suite_ut.function - '\
-                  'end case pattern .*? not found!'
-        self.assertRaisesRegex(GeneratorInputError, err_msg,
-                               parse_function_code, stream, [], [])
-
-    @patch("generate_test_code.parse_function_arguments")
-    def test_function_called(self,
-                             parse_function_arguments_mock):
-        """
-        Test parse_function_code()
-        :return:
-        """
-        parse_function_arguments_mock.return_value = ([], '', [])
-        data = '''
-void test_func()
-{
-}
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        self.assertRaises(GeneratorInputError, parse_function_code,
-                          stream, [], [])
-        self.assertTrue(parse_function_arguments_mock.called)
-        parse_function_arguments_mock.assert_called_with('void test_func()\n')
-
-    @patch("generate_test_code.gen_dispatch")
-    @patch("generate_test_code.gen_dependencies")
-    @patch("generate_test_code.gen_function_wrapper")
-    @patch("generate_test_code.parse_function_arguments")
-    def test_return(self, parse_function_arguments_mock,
-                    gen_function_wrapper_mock,
-                    gen_dependencies_mock,
-                    gen_dispatch_mock):
-        """
-        Test generated code.
-        :return:
-        """
-        parse_function_arguments_mock.return_value = ([], '', [])
-        gen_function_wrapper_mock.return_value = ''
-        gen_dependencies_mock.side_effect = gen_dependencies
-        gen_dispatch_mock.side_effect = gen_dispatch
-        data = '''
-void func()
-{
-    ba ba black sheep
-    have you any wool
-}
-/* END_CASE */
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        name, arg, code, dispatch_code = parse_function_code(stream, [], [])
-
-        self.assertTrue(parse_function_arguments_mock.called)
-        parse_function_arguments_mock.assert_called_with('void func()\n')
-        gen_function_wrapper_mock.assert_called_with('test_func', '', [])
-        self.assertEqual(name, 'test_func')
-        self.assertEqual(arg, [])
-        expected = '''#line 1 "test_suite_ut.function"
-
-void test_func(void)
-{
-    ba ba black sheep
-    have you any wool
-exit:
-    ;
-}
-'''
-        self.assertEqual(code, expected)
-        self.assertEqual(dispatch_code, "\n    test_func_wrapper,\n")
-
-    @patch("generate_test_code.gen_dispatch")
-    @patch("generate_test_code.gen_dependencies")
-    @patch("generate_test_code.gen_function_wrapper")
-    @patch("generate_test_code.parse_function_arguments")
-    def test_with_exit_label(self, parse_function_arguments_mock,
-                             gen_function_wrapper_mock,
-                             gen_dependencies_mock,
-                             gen_dispatch_mock):
-        """
-        Test when exit label is present.
-        :return:
-        """
-        parse_function_arguments_mock.return_value = ([], '', [])
-        gen_function_wrapper_mock.return_value = ''
-        gen_dependencies_mock.side_effect = gen_dependencies
-        gen_dispatch_mock.side_effect = gen_dispatch
-        data = '''
-void func()
-{
-    ba ba black sheep
-    have you any wool
-exit:
-    yes sir yes sir
-    3 bags full
-}
-/* END_CASE */
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        _, _, code, _ = parse_function_code(stream, [], [])
-
-        expected = '''#line 1 "test_suite_ut.function"
-
-void test_func(void)
-{
-    ba ba black sheep
-    have you any wool
-exit:
-    yes sir yes sir
-    3 bags full
-}
-'''
-        self.assertEqual(code, expected)
-
-    def test_non_void_function(self):
-        """
-        Test invalid signature (non void).
-        :return:
-        """
-        data = 'int entropy_threshold( char * a, data_t * h, int result )'
-        err_msg = 'file: test_suite_ut.function - Test functions not found!'
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        self.assertRaisesRegex(GeneratorInputError, err_msg,
-                               parse_function_code, stream, [], [])
-
-    @patch("generate_test_code.gen_dispatch")
-    @patch("generate_test_code.gen_dependencies")
-    @patch("generate_test_code.gen_function_wrapper")
-    @patch("generate_test_code.parse_function_arguments")
-    def test_function_name_on_newline(self, parse_function_arguments_mock,
-                                      gen_function_wrapper_mock,
-                                      gen_dependencies_mock,
-                                      gen_dispatch_mock):
-        """
-        Test with line break before the function name.
-        :return:
-        """
-        parse_function_arguments_mock.return_value = ([], '', [])
-        gen_function_wrapper_mock.return_value = ''
-        gen_dependencies_mock.side_effect = gen_dependencies
-        gen_dispatch_mock.side_effect = gen_dispatch
-        data = '''
-void
-
-
-func()
-{
-    ba ba black sheep
-    have you any wool
-exit:
-    yes sir yes sir
-    3 bags full
-}
-/* END_CASE */
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        _, _, code, _ = parse_function_code(stream, [], [])
-
-        expected = '''#line 1 "test_suite_ut.function"
-
-void
-
-
-test_func(void)
-{
-    ba ba black sheep
-    have you any wool
-exit:
-    yes sir yes sir
-    3 bags full
-}
-'''
-        self.assertEqual(code, expected)
-
-    @patch("generate_test_code.gen_dispatch")
-    @patch("generate_test_code.gen_dependencies")
-    @patch("generate_test_code.gen_function_wrapper")
-    @patch("generate_test_code.parse_function_arguments")
-    def test_case_starting_with_comment(self, parse_function_arguments_mock,
-                                        gen_function_wrapper_mock,
-                                        gen_dependencies_mock,
-                                        gen_dispatch_mock):
-        """
-        Test with comments before the function signature
-        :return:
-        """
-        parse_function_arguments_mock.return_value = ([], '', [])
-        gen_function_wrapper_mock.return_value = ''
-        gen_dependencies_mock.side_effect = gen_dependencies
-        gen_dispatch_mock.side_effect = gen_dispatch
-        data = '''/* comment */
-/* more
- * comment */
-// this is\\
-still \\
-a comment
-void func()
-{
-    ba ba black sheep
-    have you any wool
-exit:
-    yes sir yes sir
-    3 bags full
-}
-/* END_CASE */
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        _, _, code, _ = parse_function_code(stream, [], [])
-
-        expected = '''#line 1 "test_suite_ut.function"
-
-
-
-
-
-
-void test_func(void)
-{
-    ba ba black sheep
-    have you any wool
-exit:
-    yes sir yes sir
-    3 bags full
-}
-'''
-        self.assertEqual(code, expected)
-
-    @patch("generate_test_code.gen_dispatch")
-    @patch("generate_test_code.gen_dependencies")
-    @patch("generate_test_code.gen_function_wrapper")
-    @patch("generate_test_code.parse_function_arguments")
-    def test_comment_in_prototype(self, parse_function_arguments_mock,
-                                  gen_function_wrapper_mock,
-                                  gen_dependencies_mock,
-                                  gen_dispatch_mock):
-        """
-        Test with comments in the function prototype
-        :return:
-        """
-        parse_function_arguments_mock.return_value = ([], '', [])
-        gen_function_wrapper_mock.return_value = ''
-        gen_dependencies_mock.side_effect = gen_dependencies
-        gen_dispatch_mock.side_effect = gen_dispatch
-        data = '''
-void func( int x, // (line \\
-                     comment)
-           int y /* lone closing parenthesis) */ )
-{
-    ba ba black sheep
-    have you any wool
-exit:
-    yes sir yes sir
-    3 bags full
-}
-/* END_CASE */
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        _, _, code, _ = parse_function_code(stream, [], [])
-
-        expected = '''#line 1 "test_suite_ut.function"
-
-void test_func( int x,
-
-           int y                                 )
-{
-    ba ba black sheep
-    have you any wool
-exit:
-    yes sir yes sir
-    3 bags full
-}
-'''
-        self.assertEqual(code, expected)
-
-    @patch("generate_test_code.gen_dispatch")
-    @patch("generate_test_code.gen_dependencies")
-    @patch("generate_test_code.gen_function_wrapper")
-    @patch("generate_test_code.parse_function_arguments")
-    def test_line_comment_in_block_comment(self, parse_function_arguments_mock,
-                                           gen_function_wrapper_mock,
-                                           gen_dependencies_mock,
-                                           gen_dispatch_mock):
-        """
-        Test with line comment in block comment.
-        :return:
-        """
-        parse_function_arguments_mock.return_value = ([], '', [])
-        gen_function_wrapper_mock.return_value = ''
-        gen_dependencies_mock.side_effect = gen_dependencies
-        gen_dispatch_mock.side_effect = gen_dispatch
-        data = '''
-void func( int x /* // */ )
-{
-    ba ba black sheep
-    have you any wool
-exit:
-    yes sir yes sir
-    3 bags full
-}
-/* END_CASE */
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        _, _, code, _ = parse_function_code(stream, [], [])
-
-        expected = '''#line 1 "test_suite_ut.function"
-
-void test_func( int x          )
-{
-    ba ba black sheep
-    have you any wool
-exit:
-    yes sir yes sir
-    3 bags full
-}
-'''
-        self.assertEqual(code, expected)
-
-    @patch("generate_test_code.gen_dispatch")
-    @patch("generate_test_code.gen_dependencies")
-    @patch("generate_test_code.gen_function_wrapper")
-    @patch("generate_test_code.parse_function_arguments")
-    def test_block_comment_in_line_comment(self, parse_function_arguments_mock,
-                                           gen_function_wrapper_mock,
-                                           gen_dependencies_mock,
-                                           gen_dispatch_mock):
-        """
-        Test with block comment in line comment.
-        :return:
-        """
-        parse_function_arguments_mock.return_value = ([], '', [])
-        gen_function_wrapper_mock.return_value = ''
-        gen_dependencies_mock.side_effect = gen_dependencies
-        gen_dispatch_mock.side_effect = gen_dispatch
-        data = '''
-// /*
-void func( int x )
-{
-    ba ba black sheep
-    have you any wool
-exit:
-    yes sir yes sir
-    3 bags full
-}
-/* END_CASE */
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        _, _, code, _ = parse_function_code(stream, [], [])
-
-        expected = '''#line 1 "test_suite_ut.function"
-
-
-void test_func( int x )
-{
-    ba ba black sheep
-    have you any wool
-exit:
-    yes sir yes sir
-    3 bags full
-}
-'''
-        self.assertEqual(code, expected)
-
-
-class ParseFunction(TestCase):
-    """
-    Test Suite for testing parse_functions()
-    """
-
-    @patch("generate_test_code.parse_until_pattern")
-    def test_begin_header(self, parse_until_pattern_mock):
-        """
-        Test that begin header is checked and parse_until_pattern() is called.
-        :return:
-        """
-        def stop(*_unused):
-            """Stop when parse_until_pattern is called."""
-            raise Exception
-        parse_until_pattern_mock.side_effect = stop
-        data = '''/* BEGIN_HEADER */
-#include "mbedtls/ecp.h"
-
-#define ECP_PF_UNKNOWN     -1
-/* END_HEADER */
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        self.assertRaises(Exception, parse_functions, stream)
-        parse_until_pattern_mock.assert_called_with(stream, END_HEADER_REGEX)
-        self.assertEqual(stream.line_no, 1)
-
-    @patch("generate_test_code.parse_until_pattern")
-    def test_begin_helper(self, parse_until_pattern_mock):
-        """
-        Test that begin helper is checked and parse_until_pattern() is called.
-        :return:
-        """
-        def stop(*_unused):
-            """Stop when parse_until_pattern is called."""
-            raise Exception
-        parse_until_pattern_mock.side_effect = stop
-        data = '''/* BEGIN_SUITE_HELPERS */
-void print_hello_world()
-{
-    printf("Hello World!\n");
-}
-/* END_SUITE_HELPERS */
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        self.assertRaises(Exception, parse_functions, stream)
-        parse_until_pattern_mock.assert_called_with(stream,
-                                                    END_SUITE_HELPERS_REGEX)
-        self.assertEqual(stream.line_no, 1)
-
-    @patch("generate_test_code.parse_suite_dependencies")
-    def test_begin_dep(self, parse_suite_dependencies_mock):
-        """
-        Test that begin dep is checked and parse_suite_dependencies() is
-        called.
-        :return:
-        """
-        def stop(*_unused):
-            """Stop when parse_until_pattern is called."""
-            raise Exception
-        parse_suite_dependencies_mock.side_effect = stop
-        data = '''/* BEGIN_DEPENDENCIES
- * depends_on:MBEDTLS_ECP_C
- * END_DEPENDENCIES
- */
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        self.assertRaises(Exception, parse_functions, stream)
-        parse_suite_dependencies_mock.assert_called_with(stream)
-        self.assertEqual(stream.line_no, 1)
-
-    @patch("generate_test_code.parse_function_dependencies")
-    def test_begin_function_dep(self, func_mock):
-        """
-        Test that begin dep is checked and parse_function_dependencies() is
-        called.
-        :return:
-        """
-        def stop(*_unused):
-            """Stop when parse_until_pattern is called."""
-            raise Exception
-        func_mock.side_effect = stop
-
-        dependencies_str = '/* BEGIN_CASE ' \
-            'depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */\n'
-        data = '''%svoid test_func()
-{
-}
-''' % dependencies_str
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        self.assertRaises(Exception, parse_functions, stream)
-        func_mock.assert_called_with(dependencies_str)
-        self.assertEqual(stream.line_no, 1)
-
-    @patch("generate_test_code.parse_function_code")
-    @patch("generate_test_code.parse_function_dependencies")
-    def test_return(self, func_mock1, func_mock2):
-        """
-        Test that begin case is checked and parse_function_code() is called.
-        :return:
-        """
-        func_mock1.return_value = []
-        in_func_code = '''void test_func()
-{
-}
-'''
-        func_dispatch = '''
-    test_func_wrapper,
-'''
-        func_mock2.return_value = 'test_func', [],\
-            in_func_code, func_dispatch
-        dependencies_str = '/* BEGIN_CASE ' \
-            'depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */\n'
-        data = '''%svoid test_func()
-{
-}
-''' % dependencies_str
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        suite_dependencies, dispatch_code, func_code, func_info = \
-            parse_functions(stream)
-        func_mock1.assert_called_with(dependencies_str)
-        func_mock2.assert_called_with(stream, [], [])
-        self.assertEqual(stream.line_no, 5)
-        self.assertEqual(suite_dependencies, [])
-        expected_dispatch_code = '''/* Function Id: 0 */
-
-    test_func_wrapper,
-'''
-        self.assertEqual(dispatch_code, expected_dispatch_code)
-        self.assertEqual(func_code, in_func_code)
-        self.assertEqual(func_info, {'test_func': (0, [])})
-
-    def test_parsing(self):
-        """
-        Test case parsing.
-        :return:
-        """
-        data = '''/* BEGIN_HEADER */
-#include "mbedtls/ecp.h"
-
-#define ECP_PF_UNKNOWN     -1
-/* END_HEADER */
-
-/* BEGIN_DEPENDENCIES
- * depends_on:MBEDTLS_ECP_C
- * END_DEPENDENCIES
- */
-
-/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
-void func1()
-{
-}
-/* END_CASE */
-
-/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
-void func2()
-{
-}
-/* END_CASE */
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        suite_dependencies, dispatch_code, func_code, func_info = \
-            parse_functions(stream)
-        self.assertEqual(stream.line_no, 23)
-        self.assertEqual(suite_dependencies, ['MBEDTLS_ECP_C'])
-
-        expected_dispatch_code = '''/* Function Id: 0 */
-
-#if defined(MBEDTLS_ECP_C) && defined(MBEDTLS_ENTROPY_NV_SEED) && defined(MBEDTLS_FS_IO)
-    test_func1_wrapper,
-#else
-    NULL,
-#endif
-/* Function Id: 1 */
-
-#if defined(MBEDTLS_ECP_C) && defined(MBEDTLS_ENTROPY_NV_SEED) && defined(MBEDTLS_FS_IO)
-    test_func2_wrapper,
-#else
-    NULL,
-#endif
-'''
-        self.assertEqual(dispatch_code, expected_dispatch_code)
-        expected_func_code = '''#if defined(MBEDTLS_ECP_C)
-#line 2 "test_suite_ut.function"
-#include "mbedtls/ecp.h"
-
-#define ECP_PF_UNKNOWN     -1
-#if defined(MBEDTLS_ENTROPY_NV_SEED)
-#if defined(MBEDTLS_FS_IO)
-#line 13 "test_suite_ut.function"
-void test_func1(void)
-{
-exit:
-    ;
-}
-
-void test_func1_wrapper( void ** params )
-{
-    (void)params;
-
-    test_func1(  );
-}
-#endif /* MBEDTLS_FS_IO */
-#endif /* MBEDTLS_ENTROPY_NV_SEED */
-#if defined(MBEDTLS_ENTROPY_NV_SEED)
-#if defined(MBEDTLS_FS_IO)
-#line 19 "test_suite_ut.function"
-void test_func2(void)
-{
-exit:
-    ;
-}
-
-void test_func2_wrapper( void ** params )
-{
-    (void)params;
-
-    test_func2(  );
-}
-#endif /* MBEDTLS_FS_IO */
-#endif /* MBEDTLS_ENTROPY_NV_SEED */
-#endif /* MBEDTLS_ECP_C */
-'''
-        self.assertEqual(func_code, expected_func_code)
-        self.assertEqual(func_info, {'test_func1': (0, []),
-                                     'test_func2': (1, [])})
-
-    def test_same_function_name(self):
-        """
-        Test name conflict.
-        :return:
-        """
-        data = '''/* BEGIN_HEADER */
-#include "mbedtls/ecp.h"
-
-#define ECP_PF_UNKNOWN     -1
-/* END_HEADER */
-
-/* BEGIN_DEPENDENCIES
- * depends_on:MBEDTLS_ECP_C
- * END_DEPENDENCIES
- */
-
-/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
-void func()
-{
-}
-/* END_CASE */
-
-/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
-void func()
-{
-}
-/* END_CASE */
-'''
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        self.assertRaises(GeneratorInputError, parse_functions, stream)
-
-
-class EscapedSplit(TestCase):
-    """
-    Test suite for testing escaped_split().
-    Note: Since escaped_split() output is used to write back to the
-    intermediate data file. Any escape characters in the input are
-    retained in the output.
-    """
-
-    def test_invalid_input(self):
-        """
-        Test when input split character is not a character.
-        :return:
-        """
-        self.assertRaises(ValueError, escaped_split, '', 'string')
-
-    def test_empty_string(self):
-        """
-        Test empty string input.
-        :return:
-        """
-        splits = escaped_split('', ':')
-        self.assertEqual(splits, [])
-
-    def test_no_escape(self):
-        """
-        Test with no escape character. The behaviour should be same as
-        str.split()
-        :return:
-        """
-        test_str = 'yahoo:google'
-        splits = escaped_split(test_str, ':')
-        self.assertEqual(splits, test_str.split(':'))
-
-    def test_escaped_input(self):
-        """
-        Test input that has escaped delimiter.
-        :return:
-        """
-        test_str = r'yahoo\:google:facebook'
-        splits = escaped_split(test_str, ':')
-        self.assertEqual(splits, [r'yahoo\:google', 'facebook'])
-
-    def test_escaped_escape(self):
-        """
-        Test input that has escaped delimiter.
-        :return:
-        """
-        test_str = r'yahoo\\:google:facebook'
-        splits = escaped_split(test_str, ':')
-        self.assertEqual(splits, [r'yahoo\\', 'google', 'facebook'])
-
-    def test_all_at_once(self):
-        """
-        Test input that has escaped delimiter.
-        :return:
-        """
-        test_str = r'yahoo\\:google:facebook\:instagram\\:bbc\\:wikipedia'
-        splits = escaped_split(test_str, ':')
-        self.assertEqual(splits, [r'yahoo\\', r'google',
-                                  r'facebook\:instagram\\',
-                                  r'bbc\\', r'wikipedia'])
-
-
-class ParseTestData(TestCase):
-    """
-    Test suite for parse test data.
-    """
-
-    def test_parser(self):
-        """
-        Test that tests are parsed correctly from data file.
-        :return:
-        """
-        data = """
-Diffie-Hellman full exchange #1
-dhm_do_dhm:10:"23":10:"5"
-
-Diffie-Hellman full exchange #2
-dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
-
-Diffie-Hellman full exchange #3
-dhm_do_dhm:10:"9345098382739712938719287391879381271":10:"9345098792137312973297123912791271"
-
-Diffie-Hellman selftest
-dhm_selftest:
-"""
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        # List of (name, function_name, dependencies, args)
-        tests = list(parse_test_data(stream))
-        test1, test2, test3, test4 = tests
-        self.assertEqual(test1[0], 3)
-        self.assertEqual(test1[1], 'Diffie-Hellman full exchange #1')
-        self.assertEqual(test1[2], 'dhm_do_dhm')
-        self.assertEqual(test1[3], [])
-        self.assertEqual(test1[4], ['10', '"23"', '10', '"5"'])
-
-        self.assertEqual(test2[0], 6)
-        self.assertEqual(test2[1], 'Diffie-Hellman full exchange #2')
-        self.assertEqual(test2[2], 'dhm_do_dhm')
-        self.assertEqual(test2[3], [])
-        self.assertEqual(test2[4], ['10', '"93450983094850938450983409623"',
-                                    '10', '"9345098304850938450983409622"'])
-
-        self.assertEqual(test3[0], 9)
-        self.assertEqual(test3[1], 'Diffie-Hellman full exchange #3')
-        self.assertEqual(test3[2], 'dhm_do_dhm')
-        self.assertEqual(test3[3], [])
-        self.assertEqual(test3[4], ['10',
-                                    '"9345098382739712938719287391879381271"',
-                                    '10',
-                                    '"9345098792137312973297123912791271"'])
-
-        self.assertEqual(test4[0], 12)
-        self.assertEqual(test4[1], 'Diffie-Hellman selftest')
-        self.assertEqual(test4[2], 'dhm_selftest')
-        self.assertEqual(test4[3], [])
-        self.assertEqual(test4[4], [])
-
-    def test_with_dependencies(self):
-        """
-        Test that tests with dependencies are parsed.
-        :return:
-        """
-        data = """
-Diffie-Hellman full exchange #1
-depends_on:YAHOO
-dhm_do_dhm:10:"23":10:"5"
-
-Diffie-Hellman full exchange #2
-dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
-
-"""
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        # List of (name, function_name, dependencies, args)
-        tests = list(parse_test_data(stream))
-        test1, test2 = tests
-        self.assertEqual(test1[0], 4)
-        self.assertEqual(test1[1], 'Diffie-Hellman full exchange #1')
-        self.assertEqual(test1[2], 'dhm_do_dhm')
-        self.assertEqual(test1[3], ['YAHOO'])
-        self.assertEqual(test1[4], ['10', '"23"', '10', '"5"'])
-
-        self.assertEqual(test2[0], 7)
-        self.assertEqual(test2[1], 'Diffie-Hellman full exchange #2')
-        self.assertEqual(test2[2], 'dhm_do_dhm')
-        self.assertEqual(test2[3], [])
-        self.assertEqual(test2[4], ['10', '"93450983094850938450983409623"',
-                                    '10', '"9345098304850938450983409622"'])
-
-    def test_no_args(self):
-        """
-        Test GeneratorInputError is raised when test function name and
-        args line is missing.
-        :return:
-        """
-        data = """
-Diffie-Hellman full exchange #1
-depends_on:YAHOO
-
-
-Diffie-Hellman full exchange #2
-dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
-
-"""
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        err = None
-        try:
-            for _, _, _, _, _ in parse_test_data(stream):
-                pass
-        except GeneratorInputError as err:
-            self.assertEqual(type(err), GeneratorInputError)
-
-    def test_incomplete_data(self):
-        """
-        Test GeneratorInputError is raised when test function name
-        and args line is missing.
-        :return:
-        """
-        data = """
-Diffie-Hellman full exchange #1
-depends_on:YAHOO
-"""
-        stream = StringIOWrapper('test_suite_ut.function', data)
-        err = None
-        try:
-            for _, _, _, _, _ in parse_test_data(stream):
-                pass
-        except GeneratorInputError as err:
-            self.assertEqual(type(err), GeneratorInputError)
-
-
-class GenDepCheck(TestCase):
-    """
-    Test suite for gen_dep_check(). It is assumed this function is
-    called with valid inputs.
-    """
-
-    def test_gen_dep_check(self):
-        """
-        Test that dependency check code generated correctly.
-        :return:
-        """
-        expected = """
-        case 5:
-            {
-#if defined(YAHOO)
-                ret = DEPENDENCY_SUPPORTED;
-#else
-                ret = DEPENDENCY_NOT_SUPPORTED;
-#endif
-            }
-            break;"""
-        out = gen_dep_check(5, 'YAHOO')
-        self.assertEqual(out, expected)
-
-    def test_not_defined_dependency(self):
-        """
-        Test dependency with !.
-        :return:
-        """
-        expected = """
-        case 5:
-            {
-#if !defined(YAHOO)
-                ret = DEPENDENCY_SUPPORTED;
-#else
-                ret = DEPENDENCY_NOT_SUPPORTED;
-#endif
-            }
-            break;"""
-        out = gen_dep_check(5, '!YAHOO')
-        self.assertEqual(out, expected)
-
-    def test_empty_dependency(self):
-        """
-        Test invalid dependency input.
-        :return:
-        """
-        self.assertRaises(GeneratorInputError, gen_dep_check, 5, '!')
-
-    def test_negative_dep_id(self):
-        """
-        Test invalid dependency input.
-        :return:
-        """
-        self.assertRaises(GeneratorInputError, gen_dep_check, -1, 'YAHOO')
-
-
-class GenExpCheck(TestCase):
-    """
-    Test suite for gen_expression_check(). It is assumed this function
-    is called with valid inputs.
-    """
-
-    def test_gen_exp_check(self):
-        """
-        Test that expression check code generated correctly.
-        :return:
-        """
-        expected = """
-        case 5:
-            {
-                *out_value = YAHOO;
-            }
-            break;"""
-        out = gen_expression_check(5, 'YAHOO')
-        self.assertEqual(out, expected)
-
-    def test_invalid_expression(self):
-        """
-        Test invalid expression input.
-        :return:
-        """
-        self.assertRaises(GeneratorInputError, gen_expression_check, 5, '')
-
-    def test_negative_exp_id(self):
-        """
-        Test invalid expression id.
-        :return:
-        """
-        self.assertRaises(GeneratorInputError, gen_expression_check,
-                          -1, 'YAHOO')
-
-
-class WriteDependencies(TestCase):
-    """
-    Test suite for testing write_dependencies.
-    """
-
-    def test_no_test_dependencies(self):
-        """
-        Test when test dependencies input is empty.
-        :return:
-        """
-        stream = StringIOWrapper('test_suite_ut.data', '')
-        unique_dependencies = []
-        dep_check_code = write_dependencies(stream, [], unique_dependencies)
-        self.assertEqual(dep_check_code, '')
-        self.assertEqual(len(unique_dependencies), 0)
-        self.assertEqual(stream.getvalue(), '')
-
-    def test_unique_dep_ids(self):
-        """
-
-        :return:
-        """
-        stream = StringIOWrapper('test_suite_ut.data', '')
-        unique_dependencies = []
-        dep_check_code = write_dependencies(stream, ['DEP3', 'DEP2', 'DEP1'],
-                                            unique_dependencies)
-        expect_dep_check_code = '''
-        case 0:
-            {
-#if defined(DEP3)
-                ret = DEPENDENCY_SUPPORTED;
-#else
-                ret = DEPENDENCY_NOT_SUPPORTED;
-#endif
-            }
-            break;
-        case 1:
-            {
-#if defined(DEP2)
-                ret = DEPENDENCY_SUPPORTED;
-#else
-                ret = DEPENDENCY_NOT_SUPPORTED;
-#endif
-            }
-            break;
-        case 2:
-            {
-#if defined(DEP1)
-                ret = DEPENDENCY_SUPPORTED;
-#else
-                ret = DEPENDENCY_NOT_SUPPORTED;
-#endif
-            }
-            break;'''
-        self.assertEqual(dep_check_code, expect_dep_check_code)
-        self.assertEqual(len(unique_dependencies), 3)
-        self.assertEqual(stream.getvalue(), 'depends_on:0:1:2\n')
-
-    def test_dep_id_repeat(self):
-        """
-
-        :return:
-        """
-        stream = StringIOWrapper('test_suite_ut.data', '')
-        unique_dependencies = []
-        dep_check_code = ''
-        dep_check_code += write_dependencies(stream, ['DEP3', 'DEP2'],
-                                             unique_dependencies)
-        dep_check_code += write_dependencies(stream, ['DEP2', 'DEP1'],
-                                             unique_dependencies)
-        dep_check_code += write_dependencies(stream, ['DEP1', 'DEP3'],
-                                             unique_dependencies)
-        expect_dep_check_code = '''
-        case 0:
-            {
-#if defined(DEP3)
-                ret = DEPENDENCY_SUPPORTED;
-#else
-                ret = DEPENDENCY_NOT_SUPPORTED;
-#endif
-            }
-            break;
-        case 1:
-            {
-#if defined(DEP2)
-                ret = DEPENDENCY_SUPPORTED;
-#else
-                ret = DEPENDENCY_NOT_SUPPORTED;
-#endif
-            }
-            break;
-        case 2:
-            {
-#if defined(DEP1)
-                ret = DEPENDENCY_SUPPORTED;
-#else
-                ret = DEPENDENCY_NOT_SUPPORTED;
-#endif
-            }
-            break;'''
-        self.assertEqual(dep_check_code, expect_dep_check_code)
-        self.assertEqual(len(unique_dependencies), 3)
-        self.assertEqual(stream.getvalue(),
-                         'depends_on:0:1\ndepends_on:1:2\ndepends_on:2:0\n')
-
-
-class WriteParams(TestCase):
-    """
-    Test Suite for testing write_parameters().
-    """
-
-    def test_no_params(self):
-        """
-        Test with empty test_args
-        :return:
-        """
-        stream = StringIOWrapper('test_suite_ut.data', '')
-        unique_expressions = []
-        expression_code = write_parameters(stream, [], [], unique_expressions)
-        self.assertEqual(len(unique_expressions), 0)
-        self.assertEqual(expression_code, '')
-        self.assertEqual(stream.getvalue(), '\n')
-
-    def test_no_exp_param(self):
-        """
-        Test when there is no macro or expression in the params.
-        :return:
-        """
-        stream = StringIOWrapper('test_suite_ut.data', '')
-        unique_expressions = []
-        expression_code = write_parameters(stream, ['"Yahoo"', '"abcdef00"',
-                                                    '0'],
-                                           ['char*', 'hex', 'int'],
-                                           unique_expressions)
-        self.assertEqual(len(unique_expressions), 0)
-        self.assertEqual(expression_code, '')
-        self.assertEqual(stream.getvalue(),
-                         ':char*:"Yahoo":hex:"abcdef00":int:0\n')
-
-    def test_hex_format_int_param(self):
-        """
-        Test int parameter in hex format.
-        :return:
-        """
-        stream = StringIOWrapper('test_suite_ut.data', '')
-        unique_expressions = []
-        expression_code = write_parameters(stream,
-                                           ['"Yahoo"', '"abcdef00"', '0xAA'],
-                                           ['char*', 'hex', 'int'],
-                                           unique_expressions)
-        self.assertEqual(len(unique_expressions), 0)
-        self.assertEqual(expression_code, '')
-        self.assertEqual(stream.getvalue(),
-                         ':char*:"Yahoo":hex:"abcdef00":int:0xAA\n')
-
-    def test_with_exp_param(self):
-        """
-        Test when there is macro or expression in the params.
-        :return:
-        """
-        stream = StringIOWrapper('test_suite_ut.data', '')
-        unique_expressions = []
-        expression_code = write_parameters(stream,
-                                           ['"Yahoo"', '"abcdef00"', '0',
-                                            'MACRO1', 'MACRO2', 'MACRO3'],
-                                           ['char*', 'hex', 'int',
-                                            'int', 'int', 'int'],
-                                           unique_expressions)
-        self.assertEqual(len(unique_expressions), 3)
-        self.assertEqual(unique_expressions, ['MACRO1', 'MACRO2', 'MACRO3'])
-        expected_expression_code = '''
-        case 0:
-            {
-                *out_value = MACRO1;
-            }
-            break;
-        case 1:
-            {
-                *out_value = MACRO2;
-            }
-            break;
-        case 2:
-            {
-                *out_value = MACRO3;
-            }
-            break;'''
-        self.assertEqual(expression_code, expected_expression_code)
-        self.assertEqual(stream.getvalue(),
-                         ':char*:"Yahoo":hex:"abcdef00":int:0:exp:0:exp:1'
-                         ':exp:2\n')
-
-    def test_with_repeat_calls(self):
-        """
-        Test when write_parameter() is called with same macro or expression.
-        :return:
-        """
-        stream = StringIOWrapper('test_suite_ut.data', '')
-        unique_expressions = []
-        expression_code = ''
-        expression_code += write_parameters(stream,
-                                            ['"Yahoo"', 'MACRO1', 'MACRO2'],
-                                            ['char*', 'int', 'int'],
-                                            unique_expressions)
-        expression_code += write_parameters(stream,
-                                            ['"abcdef00"', 'MACRO2', 'MACRO3'],
-                                            ['hex', 'int', 'int'],
-                                            unique_expressions)
-        expression_code += write_parameters(stream,
-                                            ['0', 'MACRO3', 'MACRO1'],
-                                            ['int', 'int', 'int'],
-                                            unique_expressions)
-        self.assertEqual(len(unique_expressions), 3)
-        self.assertEqual(unique_expressions, ['MACRO1', 'MACRO2', 'MACRO3'])
-        expected_expression_code = '''
-        case 0:
-            {
-                *out_value = MACRO1;
-            }
-            break;
-        case 1:
-            {
-                *out_value = MACRO2;
-            }
-            break;
-        case 2:
-            {
-                *out_value = MACRO3;
-            }
-            break;'''
-        self.assertEqual(expression_code, expected_expression_code)
-        expected_data_file = ''':char*:"Yahoo":exp:0:exp:1
-:hex:"abcdef00":exp:1:exp:2
-:int:0:exp:2:exp:0
-'''
-        self.assertEqual(stream.getvalue(), expected_data_file)
-
-
-class GenTestSuiteDependenciesChecks(TestCase):
-    """
-    Test suite for testing gen_suite_dep_checks()
-    """
-    def test_empty_suite_dependencies(self):
-        """
-        Test with empty suite_dependencies list.
-
-        :return:
-        """
-        dep_check_code, expression_code = \
-            gen_suite_dep_checks([], 'DEP_CHECK_CODE', 'EXPRESSION_CODE')
-        self.assertEqual(dep_check_code, 'DEP_CHECK_CODE')
-        self.assertEqual(expression_code, 'EXPRESSION_CODE')
-
-    def test_suite_dependencies(self):
-        """
-        Test with suite_dependencies list.
-
-        :return:
-        """
-        dep_check_code, expression_code = \
-            gen_suite_dep_checks(['SUITE_DEP'], 'DEP_CHECK_CODE',
-                                 'EXPRESSION_CODE')
-        expected_dep_check_code = '''
-#if defined(SUITE_DEP)
-DEP_CHECK_CODE
-#endif
-'''
-        expected_expression_code = '''
-#if defined(SUITE_DEP)
-EXPRESSION_CODE
-#endif
-'''
-        self.assertEqual(dep_check_code, expected_dep_check_code)
-        self.assertEqual(expression_code, expected_expression_code)
-
-    def test_no_dep_no_exp(self):
-        """
-        Test when there are no dependency and expression code.
-        :return:
-        """
-        dep_check_code, expression_code = gen_suite_dep_checks([], '', '')
-        self.assertEqual(dep_check_code, '')
-        self.assertEqual(expression_code, '')
-
-
-class GenFromTestData(TestCase):
-    """
-    Test suite for gen_from_test_data()
-    """
-
-    @staticmethod
-    @patch("generate_test_code.write_dependencies")
-    @patch("generate_test_code.write_parameters")
-    @patch("generate_test_code.gen_suite_dep_checks")
-    def test_intermediate_data_file(func_mock1,
-                                    write_parameters_mock,
-                                    write_dependencies_mock):
-        """
-        Test that intermediate data file is written with expected data.
-        :return:
-        """
-        data = '''
-My test
-depends_on:DEP1
-func1:0
-'''
-        data_f = StringIOWrapper('test_suite_ut.data', data)
-        out_data_f = StringIOWrapper('test_suite_ut.datax', '')
-        func_info = {'test_func1': (1, ('int',))}
-        suite_dependencies = []
-        write_parameters_mock.side_effect = write_parameters
-        write_dependencies_mock.side_effect = write_dependencies
-        func_mock1.side_effect = gen_suite_dep_checks
-        gen_from_test_data(data_f, out_data_f, func_info, suite_dependencies)
-        write_dependencies_mock.assert_called_with(out_data_f,
-                                                   ['DEP1'], ['DEP1'])
-        write_parameters_mock.assert_called_with(out_data_f, ['0'],
-                                                 ('int',), [])
-        expected_dep_check_code = '''
-        case 0:
-            {
-#if defined(DEP1)
-                ret = DEPENDENCY_SUPPORTED;
-#else
-                ret = DEPENDENCY_NOT_SUPPORTED;
-#endif
-            }
-            break;'''
-        func_mock1.assert_called_with(
-            suite_dependencies, expected_dep_check_code, '')
-
-    def test_function_not_found(self):
-        """
-        Test that AssertError is raised when function info in not found.
-        :return:
-        """
-        data = '''
-My test
-depends_on:DEP1
-func1:0
-'''
-        data_f = StringIOWrapper('test_suite_ut.data', data)
-        out_data_f = StringIOWrapper('test_suite_ut.datax', '')
-        func_info = {'test_func2': (1, ('int',))}
-        suite_dependencies = []
-        self.assertRaises(GeneratorInputError, gen_from_test_data,
-                          data_f, out_data_f, func_info, suite_dependencies)
-
-    def test_different_func_args(self):
-        """
-        Test that AssertError is raised when no. of parameters and
-        function args differ.
-        :return:
-        """
-        data = '''
-My test
-depends_on:DEP1
-func1:0
-'''
-        data_f = StringIOWrapper('test_suite_ut.data', data)
-        out_data_f = StringIOWrapper('test_suite_ut.datax', '')
-        func_info = {'test_func2': (1, ('int', 'hex'))}
-        suite_dependencies = []
-        self.assertRaises(GeneratorInputError, gen_from_test_data, data_f,
-                          out_data_f, func_info, suite_dependencies)
-
-    def test_output(self):
-        """
-        Test that intermediate data file is written with expected data.
-        :return:
-        """
-        data = '''
-My test 1
-depends_on:DEP1
-func1:0:0xfa:MACRO1:MACRO2
-
-My test 2
-depends_on:DEP1:DEP2
-func2:"yahoo":88:MACRO1
-'''
-        data_f = StringIOWrapper('test_suite_ut.data', data)
-        out_data_f = StringIOWrapper('test_suite_ut.datax', '')
-        func_info = {'test_func1': (0, ('int', 'int', 'int', 'int')),
-                     'test_func2': (1, ('char*', 'int', 'int'))}
-        suite_dependencies = []
-        dep_check_code, expression_code = \
-            gen_from_test_data(data_f, out_data_f, func_info,
-                               suite_dependencies)
-        expected_dep_check_code = '''
-        case 0:
-            {
-#if defined(DEP1)
-                ret = DEPENDENCY_SUPPORTED;
-#else
-                ret = DEPENDENCY_NOT_SUPPORTED;
-#endif
-            }
-            break;
-        case 1:
-            {
-#if defined(DEP2)
-                ret = DEPENDENCY_SUPPORTED;
-#else
-                ret = DEPENDENCY_NOT_SUPPORTED;
-#endif
-            }
-            break;'''
-        expected_data = '''My test 1
-depends_on:0
-0:int:0:int:0xfa:exp:0:exp:1
-
-My test 2
-depends_on:0:1
-1:char*:"yahoo":int:88:exp:0
-
-'''
-        expected_expression_code = '''
-        case 0:
-            {
-                *out_value = MACRO1;
-            }
-            break;
-        case 1:
-            {
-                *out_value = MACRO2;
-            }
-            break;'''
-        self.assertEqual(dep_check_code, expected_dep_check_code)
-        self.assertEqual(out_data_f.getvalue(), expected_data)
-        self.assertEqual(expression_code, expected_expression_code)
-
-
-if __name__ == '__main__':
-    unittest_main()
diff --git a/tests/scripts/test_psa_compliance.py b/tests/scripts/test_psa_compliance.py
index 8d70cbc..f7d1895 100755
--- a/tests/scripts/test_psa_compliance.py
+++ b/tests/scripts/test_psa_compliance.py
@@ -20,7 +20,7 @@
 
 #pylint: disable=unused-import
 import scripts_path
-from mbedtls_dev import build_tree
+from mbedtls_framework import build_tree
 
 # PSA Compliance tests we expect to fail due to known defects in Mbed TLS /
 # TF-PSA-Crypto (or the test suite).
diff --git a/tests/scripts/test_psa_constant_names.py b/tests/scripts/test_psa_constant_names.py
index 6883e27..86d9e6f 100755
--- a/tests/scripts/test_psa_constant_names.py
+++ b/tests/scripts/test_psa_constant_names.py
@@ -19,9 +19,9 @@
 from typing import Iterable, List, Optional, Tuple
 
 import scripts_path # pylint: disable=unused-import
-from mbedtls_dev import c_build_helper
-from mbedtls_dev.macro_collector import InputsForTest, PSAMacroEnumerator
-from mbedtls_dev import typing_util
+from mbedtls_framework import c_build_helper
+from mbedtls_framework.macro_collector import InputsForTest, PSAMacroEnumerator
+from mbedtls_framework import typing_util
 
 def gather_inputs(headers: Iterable[str],
                   test_suites: Iterable[str],
diff --git a/tests/src/test_certs.h b/tests/src/test_certs.h
deleted file mode 100644
index b313ea8..0000000
--- a/tests/src/test_certs.h
+++ /dev/null
@@ -1,1226 +0,0 @@
-/*
- *  X.509 test certificates
- *
- *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
- */
-
-/* THIS FILE is generated by `tests/scripts/generate_test_cert_macros.py` */
-/* *INDENT-OFF* */
-
-/* This is taken from test-ca2.crt. */
-/* BEGIN FILE string macro TEST_CA_CRT_EC_PEM test-ca2.crt */
-#define TEST_CA_CRT_EC_PEM                                                     \
-    "-----BEGIN CERTIFICATE-----\r\n"                                          \
-    "MIICBzCCAYugAwIBAgIJAMFD4n5iQ8zoMAwGCCqGSM49BAMCBQAwPjELMAkGA1UE\r\n"     \
-    "BhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRwwGgYDVQQDDBNQb2xhcnNzbCBUZXN0\r\n"     \
-    "IEVDIENBMB4XDTE5MDIxMDE0NDQwMFoXDTI5MDIxMDE0NDQwMFowPjELMAkGA1UE\r\n"     \
-    "BhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRwwGgYDVQQDDBNQb2xhcnNzbCBUZXN0\r\n"     \
-    "IEVDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEw9orNEE3WC+HVv78ibopQ0tO\r\n"     \
-    "4G7DDldTMzlY1FK0kZU5CyPfXxckYkj8GpUpziwth8KIUoCv1mqrId240xxuWLjK\r\n"     \
-    "6LJpjvNBrSnDtF91p0dv1RkpVWmaUzsgtGYWYDMeo1MwUTAPBgNVHRMBAf8EBTAD\r\n"     \
-    "AQH/MB0GA1UdDgQWBBSdbSAkSQE/K8t4tRm8fiTJ2/s2fDAfBgNVHSMEGDAWgBSd\r\n"     \
-    "bSAkSQE/K8t4tRm8fiTJ2/s2fDAMBggqhkjOPQQDAgUAA2gAMGUCMQDpNWfBIlzq\r\n"     \
-    "6xV2UwQD/1YGz9fQUM7AfNKzVa2PVBpf/QD1TAylTYTF4GI6qlb6EPYCMF/YVa29\r\n"     \
-    "N5yC1mFAir19jb9Pl9iiIkRm17dM4y6m5VIMepEPm/VlWAa8H5p1+BPbGw==\r\n"         \
-    "-----END CERTIFICATE-----\r\n"
-/* END FILE */
-
-/* This is generated from test-ca2.crt.der. */
-/* BEGIN FILE binary macro TEST_CA_CRT_EC_DER test-ca2.crt.der */
-#define TEST_CA_CRT_EC_DER {                                                    \
-        0x30, 0x82, 0x02, 0x07, 0x30, 0x82, 0x01, 0x8b, 0xa0, 0x03, 0x02, 0x01, \
-        0x02, 0x02, 0x09, 0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8, \
-        0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, \
-        0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, \
-        0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, \
-        0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \
-        0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x50, \
-        0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, \
-        0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39, \
-        0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, 0x5a, 0x17, \
-        0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, \
-        0x30, 0x5a, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, \
-        0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, \
-        0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \
-        0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, 0x50, \
-        0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, \
-        0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, \
-        0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, \
-        0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xc3, 0xda, 0x2b, 0x34, 0x41, 0x37, \
-        0x58, 0x2f, 0x87, 0x56, 0xfe, 0xfc, 0x89, 0xba, 0x29, 0x43, 0x4b, 0x4e, \
-        0xe0, 0x6e, 0xc3, 0x0e, 0x57, 0x53, 0x33, 0x39, 0x58, 0xd4, 0x52, 0xb4, \
-        0x91, 0x95, 0x39, 0x0b, 0x23, 0xdf, 0x5f, 0x17, 0x24, 0x62, 0x48, 0xfc, \
-        0x1a, 0x95, 0x29, 0xce, 0x2c, 0x2d, 0x87, 0xc2, 0x88, 0x52, 0x80, 0xaf, \
-        0xd6, 0x6a, 0xab, 0x21, 0xdd, 0xb8, 0xd3, 0x1c, 0x6e, 0x58, 0xb8, 0xca, \
-        0xe8, 0xb2, 0x69, 0x8e, 0xf3, 0x41, 0xad, 0x29, 0xc3, 0xb4, 0x5f, 0x75, \
-        0xa7, 0x47, 0x6f, 0xd5, 0x19, 0x29, 0x55, 0x69, 0x9a, 0x53, 0x3b, 0x20, \
-        0xb4, 0x66, 0x16, 0x60, 0x33, 0x1e, 0xa3, 0x53, 0x30, 0x51, 0x30, 0x0f, \
-        0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, \
-        0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, \
-        0x04, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, 0x01, 0x3f, 0x2b, 0xcb, 0x78, \
-        0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, 0xfb, 0x36, 0x7c, 0x30, 0x1f, \
-        0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9d, \
-        0x6d, 0x20, 0x24, 0x49, 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, \
-        0x7e, 0x24, 0xc9, 0xdb, 0xfb, 0x36, 0x7c, 0x30, 0x0c, 0x06, 0x08, 0x2a, \
-        0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x68, 0x00, \
-        0x30, 0x65, 0x02, 0x31, 0x00, 0xe9, 0x35, 0x67, 0xc1, 0x22, 0x5c, 0xea, \
-        0xeb, 0x15, 0x76, 0x53, 0x04, 0x03, 0xff, 0x56, 0x06, 0xcf, 0xd7, 0xd0, \
-        0x50, 0xce, 0xc0, 0x7c, 0xd2, 0xb3, 0x55, 0xad, 0x8f, 0x54, 0x1a, 0x5f, \
-        0xfd, 0x00, 0xf5, 0x4c, 0x0c, 0xa5, 0x4d, 0x84, 0xc5, 0xe0, 0x62, 0x3a, \
-        0xaa, 0x56, 0xfa, 0x10, 0xf6, 0x02, 0x30, 0x5f, 0xd8, 0x55, 0xad, 0xbd, \
-        0x37, 0x9c, 0x82, 0xd6, 0x61, 0x40, 0x8a, 0xbd, 0x7d, 0x8d, 0xbf, 0x4f, \
-        0x97, 0xd8, 0xa2, 0x22, 0x44, 0x66, 0xd7, 0xb7, 0x4c, 0xe3, 0x2e, 0xa6, \
-        0xe5, 0x52, 0x0c, 0x7a, 0x91, 0x0f, 0x9b, 0xf5, 0x65, 0x58, 0x06, 0xbc, \
-        0x1f, 0x9a, 0x75, 0xf8, 0x13, 0xdb, 0x1b                                \
-}
-/* END FILE */
-
-/* This is taken from test-ca2.key.enc. */
-/* BEGIN FILE string macro TEST_CA_KEY_EC_PEM test-ca2.key.enc */
-#define TEST_CA_KEY_EC_PEM                                                     \
-    "-----BEGIN EC PRIVATE KEY-----\r\n"                                       \
-    "Proc-Type: 4,ENCRYPTED\r\n"                                               \
-    "DEK-Info: DES-EDE3-CBC,307EAB469933D64E\r\n"                              \
-    "\r\n"                                                                     \
-    "IxbrRmKcAzctJqPdTQLA4SWyBYYGYJVkYEna+F7Pa5t5Yg/gKADrFKcm6B72e7DG\r\n"     \
-    "ihExtZI648s0zdYw6qSJ74vrPSuWDe5qm93BqsfVH9svtCzWHW0pm1p0KTBCFfUq\r\n"     \
-    "UsuWTITwJImcnlAs1gaRZ3sAWm7cOUidL0fo2G0fYUFNcYoCSLffCFTEHBuPnagb\r\n"     \
-    "a77x/sY1Bvii8S9/XhDTb6pTMx06wzrm\r\n"                                     \
-    "-----END EC PRIVATE KEY-----\r\n"
-/* END FILE */
-
-#define TEST_CA_PWD_EC_PEM "PolarSSLTest"
-
-/* This is generated from test-ca2.key.der. */
-/* BEGIN FILE binary macro TEST_CA_KEY_EC_DER test-ca2.key.der */
-#define TEST_CA_KEY_EC_DER {                                                    \
-        0x30, 0x81, 0xa4, 0x02, 0x01, 0x01, 0x04, 0x30, 0x83, 0xd9, 0x15, 0x0e, \
-        0xa0, 0x71, 0xf0, 0x57, 0x10, 0x33, 0xa3, 0x38, 0xb8, 0x86, 0xc1, 0xa6, \
-        0x11, 0x5d, 0x6d, 0xb4, 0x03, 0xe1, 0x29, 0x76, 0x45, 0xd7, 0x87, 0x6f, \
-        0x23, 0xab, 0x44, 0x20, 0xea, 0x64, 0x7b, 0x85, 0xb1, 0x76, 0xe7, 0x85, \
-        0x95, 0xaa, 0x74, 0xd6, 0xd1, 0xa4, 0x5e, 0xea, 0xa0, 0x07, 0x06, 0x05, \
-        0x2b, 0x81, 0x04, 0x00, 0x22, 0xa1, 0x64, 0x03, 0x62, 0x00, 0x04, 0xc3, \
-        0xda, 0x2b, 0x34, 0x41, 0x37, 0x58, 0x2f, 0x87, 0x56, 0xfe, 0xfc, 0x89, \
-        0xba, 0x29, 0x43, 0x4b, 0x4e, 0xe0, 0x6e, 0xc3, 0x0e, 0x57, 0x53, 0x33, \
-        0x39, 0x58, 0xd4, 0x52, 0xb4, 0x91, 0x95, 0x39, 0x0b, 0x23, 0xdf, 0x5f, \
-        0x17, 0x24, 0x62, 0x48, 0xfc, 0x1a, 0x95, 0x29, 0xce, 0x2c, 0x2d, 0x87, \
-        0xc2, 0x88, 0x52, 0x80, 0xaf, 0xd6, 0x6a, 0xab, 0x21, 0xdd, 0xb8, 0xd3, \
-        0x1c, 0x6e, 0x58, 0xb8, 0xca, 0xe8, 0xb2, 0x69, 0x8e, 0xf3, 0x41, 0xad, \
-        0x29, 0xc3, 0xb4, 0x5f, 0x75, 0xa7, 0x47, 0x6f, 0xd5, 0x19, 0x29, 0x55, \
-        0x69, 0x9a, 0x53, 0x3b, 0x20, 0xb4, 0x66, 0x16, 0x60, 0x33, 0x1e        \
-}
-/* END FILE */
-
-/* This is taken from test-ca-sha256.crt. */
-/* BEGIN FILE string macro TEST_CA_CRT_RSA_SHA256_PEM test-ca-sha256.crt */
-#define TEST_CA_CRT_RSA_SHA256_PEM                                             \
-    "-----BEGIN CERTIFICATE-----\r\n"                                          \
-    "MIIDQTCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n"     \
-    "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"     \
-    "MTkwMjEwMTQ0NDAwWhcNMjkwMjEwMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n"     \
-    "A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n"     \
-    "CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n"     \
-    "mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n"     \
-    "50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n"     \
-    "YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n"     \
-    "R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n"     \
-    "KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n"     \
-    "UDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/\r\n"     \
-    "MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEBCwUA\r\n"     \
-    "A4IBAQA4qFSCth2q22uJIdE4KGHJsJjVEfw2/xn+MkTvCMfxVrvmRvqCtjE4tKDl\r\n"     \
-    "oK4MxFOek07oDZwvtAT9ijn1hHftTNS7RH9zd/fxNpfcHnMZXVC4w4DNA1fSANtW\r\n"     \
-    "5sY1JB5Je9jScrsLSS+mAjyv0Ow3Hb2Bix8wu7xNNrV5fIf7Ubm+wt6SqEBxu3Kb\r\n"     \
-    "+EfObAT4huf3czznhH3C17ed6NSbXwoXfby7stWUDeRJv08RaFOykf/Aae7bY5PL\r\n"     \
-    "yTVrkAnikMntJ9YI+hNNYt3inqq11A5cN0+rVTst8UKCxzQ4GpvroSwPKTFkbMw4\r\n"     \
-    "/anT1dVxr/BtwJfiESoK3/4CeXR1\r\n"                                         \
-    "-----END CERTIFICATE-----\r\n"
-/* END FILE */
-
-/* This is generated from test-ca-sha256.crt.der. */
-/* BEGIN FILE binary macro TEST_CA_CRT_RSA_SHA256_DER test-ca-sha256.crt.der */
-#define TEST_CA_CRT_RSA_SHA256_DER {                                            \
-        0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xa0, 0x03, 0x02, 0x01, \
-        0x02, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \
-        0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \
-        0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \
-        0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \
-        0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \
-        0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \
-        0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \
-        0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, \
-        0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \
-        0x34, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \
-        0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \
-        0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \
-        0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \
-        0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x54, 0x65, \
-        0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, \
-        0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, \
-        0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, \
-        0x01, 0x00, 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, \
-        0x86, 0xde, 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, \
-        0x99, 0xd4, 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, \
-        0x9b, 0xc5, 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, \
-        0xc0, 0x8d, 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, \
-        0x93, 0xe8, 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, \
-        0xe7, 0x40, 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, \
-        0xf9, 0x3e, 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, \
-        0x29, 0x00, 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, \
-        0xbd, 0x83, 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, \
-        0x60, 0xc3, 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, \
-        0x32, 0xbe, 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, \
-        0xfb, 0xf5, 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, \
-        0xee, 0xe2, 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, \
-        0x47, 0xb1, 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, \
-        0xf1, 0x79, 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, \
-        0x6f, 0x27, 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, \
-        0xa1, 0x30, 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, \
-        0x28, 0xd1, 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, \
-        0x09, 0xea, 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, \
-        0xc9, 0xab, 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, \
-        0x9e, 0x99, 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, \
-        0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, \
-        0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, \
-        0x04, 0x16, 0x04, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, \
-        0xf6, 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, \
-        0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, \
-        0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, \
-        0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, \
-        0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, \
-        0x03, 0x82, 0x01, 0x01, 0x00, 0x38, 0xa8, 0x54, 0x82, 0xb6, 0x1d, 0xaa, \
-        0xdb, 0x6b, 0x89, 0x21, 0xd1, 0x38, 0x28, 0x61, 0xc9, 0xb0, 0x98, 0xd5, \
-        0x11, 0xfc, 0x36, 0xff, 0x19, 0xfe, 0x32, 0x44, 0xef, 0x08, 0xc7, 0xf1, \
-        0x56, 0xbb, 0xe6, 0x46, 0xfa, 0x82, 0xb6, 0x31, 0x38, 0xb4, 0xa0, 0xe5, \
-        0xa0, 0xae, 0x0c, 0xc4, 0x53, 0x9e, 0x93, 0x4e, 0xe8, 0x0d, 0x9c, 0x2f, \
-        0xb4, 0x04, 0xfd, 0x8a, 0x39, 0xf5, 0x84, 0x77, 0xed, 0x4c, 0xd4, 0xbb, \
-        0x44, 0x7f, 0x73, 0x77, 0xf7, 0xf1, 0x36, 0x97, 0xdc, 0x1e, 0x73, 0x19, \
-        0x5d, 0x50, 0xb8, 0xc3, 0x80, 0xcd, 0x03, 0x57, 0xd2, 0x00, 0xdb, 0x56, \
-        0xe6, 0xc6, 0x35, 0x24, 0x1e, 0x49, 0x7b, 0xd8, 0xd2, 0x72, 0xbb, 0x0b, \
-        0x49, 0x2f, 0xa6, 0x02, 0x3c, 0xaf, 0xd0, 0xec, 0x37, 0x1d, 0xbd, 0x81, \
-        0x8b, 0x1f, 0x30, 0xbb, 0xbc, 0x4d, 0x36, 0xb5, 0x79, 0x7c, 0x87, 0xfb, \
-        0x51, 0xb9, 0xbe, 0xc2, 0xde, 0x92, 0xa8, 0x40, 0x71, 0xbb, 0x72, 0x9b, \
-        0xf8, 0x47, 0xce, 0x6c, 0x04, 0xf8, 0x86, 0xe7, 0xf7, 0x73, 0x3c, 0xe7, \
-        0x84, 0x7d, 0xc2, 0xd7, 0xb7, 0x9d, 0xe8, 0xd4, 0x9b, 0x5f, 0x0a, 0x17, \
-        0x7d, 0xbc, 0xbb, 0xb2, 0xd5, 0x94, 0x0d, 0xe4, 0x49, 0xbf, 0x4f, 0x11, \
-        0x68, 0x53, 0xb2, 0x91, 0xff, 0xc0, 0x69, 0xee, 0xdb, 0x63, 0x93, 0xcb, \
-        0xc9, 0x35, 0x6b, 0x90, 0x09, 0xe2, 0x90, 0xc9, 0xed, 0x27, 0xd6, 0x08, \
-        0xfa, 0x13, 0x4d, 0x62, 0xdd, 0xe2, 0x9e, 0xaa, 0xb5, 0xd4, 0x0e, 0x5c, \
-        0x37, 0x4f, 0xab, 0x55, 0x3b, 0x2d, 0xf1, 0x42, 0x82, 0xc7, 0x34, 0x38, \
-        0x1a, 0x9b, 0xeb, 0xa1, 0x2c, 0x0f, 0x29, 0x31, 0x64, 0x6c, 0xcc, 0x38, \
-        0xfd, 0xa9, 0xd3, 0xd5, 0xd5, 0x71, 0xaf, 0xf0, 0x6d, 0xc0, 0x97, 0xe2, \
-        0x11, 0x2a, 0x0a, 0xdf, 0xfe, 0x02, 0x79, 0x74, 0x75                    \
-}
-/* END FILE */
-
-/* This is taken from test-ca-sha1.crt. */
-/* BEGIN FILE string macro TEST_CA_CRT_RSA_SHA1_PEM test-ca-sha1.crt */
-#define TEST_CA_CRT_RSA_SHA1_PEM                                               \
-    "-----BEGIN CERTIFICATE-----\r\n"                                          \
-    "MIIDQTCCAimgAwIBAgIBAzANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"     \
-    "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"     \
-    "MTkwMjEwMTQ0NDAwWhcNMjkwMjEwMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n"     \
-    "A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n"     \
-    "CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n"     \
-    "mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n"     \
-    "50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n"     \
-    "YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n"     \
-    "R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n"     \
-    "KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n"     \
-    "UDBOMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/\r\n"     \
-    "MB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3DQEBBQUA\r\n"     \
-    "A4IBAQB0ZiNRFdia6kskaPnhrqejIRq8YMEGAf2oIPnyZ78xoyERgc35lHGyMtsL\r\n"     \
-    "hWicNjP4d/hS9As4j5KA2gdNGi5ETA1X7SowWOGsryivSpMSHVy1+HdfWlsYQOzm\r\n"     \
-    "8o+faQNUm8XzPVmttfAVspxeHSxJZ36Oo+QWZ5wZlCIEyjEdLUId+Tm4Bz3B5jRD\r\n"     \
-    "zZa/SaqDokq66N2zpbgKKAl3GU2O++fBqP2dSkdQykmTxhLLWRN8FJqhYATyQntZ\r\n"     \
-    "0QSi3W9HfSZPnFTcPIXeoiPd2pLlxt1hZu8dws2LTXE63uP6MM4LHvWxiuJaWkP/\r\n"     \
-    "mtxyUALj2pQxRitopORFQdn7AOY5\r\n"                                         \
-    "-----END CERTIFICATE-----\r\n"
-/* END FILE */
-
-/* This is generated from test-ca-sha1.crt.der. */
-/* BEGIN FILE binary macro TEST_CA_CRT_RSA_SHA1_DER test-ca-sha1.crt.der */
-#define TEST_CA_CRT_RSA_SHA1_DER {                                              \
-        0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xa0, 0x03, 0x02, 0x01, \
-        0x02, 0x02, 0x01, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \
-        0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \
-        0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \
-        0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \
-        0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \
-        0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \
-        0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \
-        0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x30, \
-        0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \
-        0x34, 0x30, 0x30, 0x5a, 0x30, 0x3b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \
-        0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \
-        0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \
-        0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \
-        0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x54, 0x65, \
-        0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, \
-        0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, \
-        0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, \
-        0x01, 0x00, 0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, \
-        0x86, 0xde, 0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, \
-        0x99, 0xd4, 0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, \
-        0x9b, 0xc5, 0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, \
-        0xc0, 0x8d, 0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, \
-        0x93, 0xe8, 0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, \
-        0xe7, 0x40, 0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, \
-        0xf9, 0x3e, 0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, \
-        0x29, 0x00, 0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, \
-        0xbd, 0x83, 0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, \
-        0x60, 0xc3, 0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, \
-        0x32, 0xbe, 0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, \
-        0xfb, 0xf5, 0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, \
-        0xee, 0xe2, 0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, \
-        0x47, 0xb1, 0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, \
-        0xf1, 0x79, 0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, \
-        0x6f, 0x27, 0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, \
-        0xa1, 0x30, 0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, \
-        0x28, 0xd1, 0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, \
-        0x09, 0xea, 0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, \
-        0xc9, 0xab, 0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, \
-        0x9e, 0x99, 0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, \
-        0x50, 0x30, 0x4e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, \
-        0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, \
-        0x04, 0x16, 0x04, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, \
-        0xf6, 0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, \
-        0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, \
-        0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, \
-        0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, \
-        0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, \
-        0x03, 0x82, 0x01, 0x01, 0x00, 0x74, 0x66, 0x23, 0x51, 0x15, 0xd8, 0x9a, \
-        0xea, 0x4b, 0x24, 0x68, 0xf9, 0xe1, 0xae, 0xa7, 0xa3, 0x21, 0x1a, 0xbc, \
-        0x60, 0xc1, 0x06, 0x01, 0xfd, 0xa8, 0x20, 0xf9, 0xf2, 0x67, 0xbf, 0x31, \
-        0xa3, 0x21, 0x11, 0x81, 0xcd, 0xf9, 0x94, 0x71, 0xb2, 0x32, 0xdb, 0x0b, \
-        0x85, 0x68, 0x9c, 0x36, 0x33, 0xf8, 0x77, 0xf8, 0x52, 0xf4, 0x0b, 0x38, \
-        0x8f, 0x92, 0x80, 0xda, 0x07, 0x4d, 0x1a, 0x2e, 0x44, 0x4c, 0x0d, 0x57, \
-        0xed, 0x2a, 0x30, 0x58, 0xe1, 0xac, 0xaf, 0x28, 0xaf, 0x4a, 0x93, 0x12, \
-        0x1d, 0x5c, 0xb5, 0xf8, 0x77, 0x5f, 0x5a, 0x5b, 0x18, 0x40, 0xec, 0xe6, \
-        0xf2, 0x8f, 0x9f, 0x69, 0x03, 0x54, 0x9b, 0xc5, 0xf3, 0x3d, 0x59, 0xad, \
-        0xb5, 0xf0, 0x15, 0xb2, 0x9c, 0x5e, 0x1d, 0x2c, 0x49, 0x67, 0x7e, 0x8e, \
-        0xa3, 0xe4, 0x16, 0x67, 0x9c, 0x19, 0x94, 0x22, 0x04, 0xca, 0x31, 0x1d, \
-        0x2d, 0x42, 0x1d, 0xf9, 0x39, 0xb8, 0x07, 0x3d, 0xc1, 0xe6, 0x34, 0x43, \
-        0xcd, 0x96, 0xbf, 0x49, 0xaa, 0x83, 0xa2, 0x4a, 0xba, 0xe8, 0xdd, 0xb3, \
-        0xa5, 0xb8, 0x0a, 0x28, 0x09, 0x77, 0x19, 0x4d, 0x8e, 0xfb, 0xe7, 0xc1, \
-        0xa8, 0xfd, 0x9d, 0x4a, 0x47, 0x50, 0xca, 0x49, 0x93, 0xc6, 0x12, 0xcb, \
-        0x59, 0x13, 0x7c, 0x14, 0x9a, 0xa1, 0x60, 0x04, 0xf2, 0x42, 0x7b, 0x59, \
-        0xd1, 0x04, 0xa2, 0xdd, 0x6f, 0x47, 0x7d, 0x26, 0x4f, 0x9c, 0x54, 0xdc, \
-        0x3c, 0x85, 0xde, 0xa2, 0x23, 0xdd, 0xda, 0x92, 0xe5, 0xc6, 0xdd, 0x61, \
-        0x66, 0xef, 0x1d, 0xc2, 0xcd, 0x8b, 0x4d, 0x71, 0x3a, 0xde, 0xe3, 0xfa, \
-        0x30, 0xce, 0x0b, 0x1e, 0xf5, 0xb1, 0x8a, 0xe2, 0x5a, 0x5a, 0x43, 0xff, \
-        0x9a, 0xdc, 0x72, 0x50, 0x02, 0xe3, 0xda, 0x94, 0x31, 0x46, 0x2b, 0x68, \
-        0xa4, 0xe4, 0x45, 0x41, 0xd9, 0xfb, 0x00, 0xe6, 0x39                    \
-}
-/* END FILE */
-
-/* This is taken from test-ca.key. */
-/* BEGIN FILE string macro TEST_CA_KEY_RSA_PEM test-ca.key */
-#define TEST_CA_KEY_RSA_PEM                                                    \
-    "-----BEGIN RSA PRIVATE KEY-----\r\n"                                      \
-    "Proc-Type: 4,ENCRYPTED\r\n"                                               \
-    "DEK-Info: AES-128-CBC,781840E6B804AE83D2AF71127C4CE314\r\n"               \
-    "\r\n"                                                                     \
-    "etQ3xgGLbuYF9vR1km03TH5fwfly1hOlix0PtfQ+t9HG065vTtSEHYc/OyHwdy79\r\n"     \
-    "NCLX5RUrPh06E/XlKzMNVHAXqkwFnIwNzRLsOozeP1L7iZEZb9QMeiN5Org+btCO\r\n"     \
-    "bylXPB4YirfuE7GSJalWY/pq3FQtD33zTIKmNhXfVj3sbwGI/8D9XjaKUb8PODOB\r\n"     \
-    "skOalmx6RvYRvg0lmRxB3+T3wejIsrrDPweYqte9B6dVHIVG1ZmvoA6/wnKZZZeV\r\n"     \
-    "sjj8OpL3OwUBrjuGSknE9Rs6kCuSCbHOYVK8VzcZmCYpie0TFnb3Sk8M6vjfW+45\r\n"     \
-    "U7WUMlSAPxKH6lJDzWdwHqLvsVJwuNnaAaBXg9/8U/rzQEWuq8Ar3s8fw2Jg3F1G\r\n"     \
-    "L6N5ZAEfCz3Sa0N9WKafR/RSQj+rq8Z3w4POAafhbzk249uo5K8B1Z3cQwLxeXIl\r\n"     \
-    "UbRQz1TZy4oNTfQzCahYruPNyvwgTkfwAFFvbLAdaiJd2ZtLBoqYE64TYakYnvcC\r\n"     \
-    "itim1bmySIKoxlMfBGFmMuF03epT0pSx701jlGzGi0l0m16NEjoVxDwo5j93SmiM\r\n"     \
-    "sQdjC1lOGk2iCLkphIQqHFjFJYWjvh1UUIqWZf+ZWOOxlf4x9a1pUVj6FvtECxNB\r\n"     \
-    "/mA/m4Iq4LAuVXHE1MpHeq067lJ6wWlrsb2WVmiNGfQ2AC7fMtpcPuunBVT9NV1m\r\n"     \
-    "1rbDzIgLIWAzqz/cy3N8Q8vfxnrFtmNUyM191Zyq+YF14hIKWX9J1qR4LXwWAzVV\r\n"     \
-    "UrC8IL4pA2mtRkW4qFsB0EmHAxO/cedDTPjVFty5WSzhNuvYZxX45HAkGIfK6d21\r\n"     \
-    "7WHPhHG+zaaUTWMUVixB0IcKp6RecjYPFzBHS0YeX88Ue2cyT/90jMiQ9ssOgRrG\r\n"     \
-    "ZJRJvZAc3TSCnY9sNPYoGrJPiZuCnlUj3ENNurYVy12ai0WFxwnNUZjRUhDS6hjm\r\n"     \
-    "cDHD5TlI9MZ6M+Mb/Bw4Ig8HuTHOtQBYD9vhtXsG+B7H/j6cS+1umaKjrnG/kK4W\r\n"     \
-    "R6YXwM2faAi+DwgjjoMXSzRqSTF8PdTIWbAXo3bc2qsXPTMBA8PEp4nb5scHZ4Ts\r\n"     \
-    "EcBNp2jv0j4gBkRmGIab17cWMrlagjFy89DhqZUFwKdeZs+yJ92A5xstWxOUfpEP\r\n"     \
-    "90T/bsp1G5d7WW5fl2TRJvYJNDM+djkKIh0zCkduiZ36oVM6nDdbjmXqjQXopeSD\r\n"     \
-    "gtOourBRF8g99W0fW8QT+yPhP0Pkyz6EG8eQO6Zwh439xdoVwu9jUzQAPmZ0uNeR\r\n"     \
-    "xTXXihYyv72z27rInjLiIPXL25K9eDVLlcSR3RyG7YYgjdQAL2VJDLcBz5jox1uQ\r\n"     \
-    "0guoD5wmfu2FWLqYE7HeTYntdY53lCflwq0GHRMjrrsVpx+5VDQ6Yi47Ny9SWLcp\r\n"     \
-    "fPI3iBkXuGRWupzs6N4pQdSO0dU28KfpMM5QvFoLIn67brCHEQij4dgFrCTYEyBX\r\n"     \
-    "9+jiNImUFYUhAFuxvUbfZt4O/ABLIElvHLfJs1oYCmI/nWpvLFqXB5rnzPNfEi0H\r\n"     \
-    "PGGe1Hj/t+CJIp/6ios3yNy2QtXO754TZH2UVu51Ykyig5PFjZVoUkbRvHQYcWfU\r\n"     \
-    "-----END RSA PRIVATE KEY-----\r\n"
-/* END FILE */
-
-#define TEST_CA_PWD_RSA_PEM "PolarSSLTest"
-
-/* This is generated from test-ca.key.der. */
-/* BEGIN FILE binary macro TEST_CA_KEY_RSA_DER test-ca.key.der */
-#define TEST_CA_KEY_RSA_DER {                                                   \
-        0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \
-        0xc0, 0xdf, 0x37, 0xfc, 0x17, 0xbb, 0xe0, 0x96, 0x9d, 0x3f, 0x86, 0xde, \
-        0x96, 0x32, 0x7d, 0x44, 0xa5, 0x16, 0xa0, 0xcd, 0x21, 0xf1, 0x99, 0xd4, \
-        0xec, 0xea, 0xcb, 0x7c, 0x18, 0x58, 0x08, 0x94, 0xa5, 0xec, 0x9b, 0xc5, \
-        0x8b, 0xdf, 0x1a, 0x1e, 0x99, 0x38, 0x99, 0x87, 0x1e, 0x7b, 0xc0, 0x8d, \
-        0x39, 0xdf, 0x38, 0x5d, 0x70, 0x78, 0x07, 0xd3, 0x9e, 0xd9, 0x93, 0xe8, \
-        0xb9, 0x72, 0x51, 0xc5, 0xce, 0xa3, 0x30, 0x52, 0xa9, 0xf2, 0xe7, 0x40, \
-        0x70, 0x14, 0xcb, 0x44, 0xa2, 0x72, 0x0b, 0xc2, 0xe5, 0x40, 0xf9, 0x3e, \
-        0xe5, 0xa6, 0x0e, 0xb3, 0xf9, 0xec, 0x4a, 0x63, 0xc0, 0xb8, 0x29, 0x00, \
-        0x74, 0x9c, 0x57, 0x3b, 0xa8, 0xa5, 0x04, 0x90, 0x71, 0xf1, 0xbd, 0x83, \
-        0xd9, 0x3f, 0xd6, 0xa5, 0xe2, 0x3c, 0x2a, 0x8f, 0xef, 0x27, 0x60, 0xc3, \
-        0xc6, 0x9f, 0xcb, 0xba, 0xec, 0x60, 0x7d, 0xb7, 0xe6, 0x84, 0x32, 0xbe, \
-        0x4f, 0xfb, 0x58, 0x26, 0x22, 0x03, 0x5b, 0xd4, 0xb4, 0xd5, 0xfb, 0xf5, \
-        0xe3, 0x96, 0x2e, 0x70, 0xc0, 0xe4, 0x2e, 0xbd, 0xfc, 0x2e, 0xee, 0xe2, \
-        0x41, 0x55, 0xc0, 0x34, 0x2e, 0x7d, 0x24, 0x72, 0x69, 0xcb, 0x47, 0xb1, \
-        0x14, 0x40, 0x83, 0x7d, 0x67, 0xf4, 0x86, 0xf6, 0x31, 0xab, 0xf1, 0x79, \
-        0xa4, 0xb2, 0xb5, 0x2e, 0x12, 0xf9, 0x84, 0x17, 0xf0, 0x62, 0x6f, 0x27, \
-        0x3e, 0x13, 0x58, 0xb1, 0x54, 0x0d, 0x21, 0x9a, 0x73, 0x37, 0xa1, 0x30, \
-        0xcf, 0x6f, 0x92, 0xdc, 0xf6, 0xe9, 0xfc, 0xac, 0xdb, 0x2e, 0x28, 0xd1, \
-        0x7e, 0x02, 0x4b, 0x23, 0xa0, 0x15, 0xf2, 0x38, 0x65, 0x64, 0x09, 0xea, \
-        0x0c, 0x6e, 0x8e, 0x1b, 0x17, 0xa0, 0x71, 0xc8, 0xb3, 0x9b, 0xc9, 0xab, \
-        0xe9, 0xc3, 0xf2, 0xcf, 0x87, 0x96, 0x8f, 0x80, 0x02, 0x32, 0x9e, 0x99, \
-        0x58, 0x6f, 0xa2, 0xd5, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \
-        0x00, 0x3f, 0xf7, 0x07, 0xd3, 0x34, 0x6f, 0xdb, 0xc9, 0x37, 0xb7, 0x84, \
-        0xdc, 0x37, 0x45, 0xe1, 0x63, 0xad, 0xb8, 0xb6, 0x75, 0xb1, 0xc7, 0x35, \
-        0xb4, 0x77, 0x2a, 0x5b, 0x77, 0xf9, 0x7e, 0xe0, 0xc1, 0xa3, 0xd1, 0xb7, \
-        0xcb, 0xa9, 0x5a, 0xc1, 0x87, 0xda, 0x5a, 0xfa, 0x17, 0xe4, 0xd5, 0x38, \
-        0x03, 0xde, 0x68, 0x98, 0x81, 0xec, 0xb5, 0xf2, 0x2a, 0x8d, 0xe9, 0x2c, \
-        0xf3, 0xa6, 0xe5, 0x32, 0x17, 0x7f, 0x33, 0x81, 0xe8, 0x38, 0x72, 0xd5, \
-        0x9c, 0xfa, 0x4e, 0xfb, 0x26, 0xf5, 0x15, 0x0b, 0xaf, 0x84, 0x66, 0xab, \
-        0x02, 0xe0, 0x18, 0xd5, 0x91, 0x7c, 0xd6, 0x8f, 0xc9, 0x4b, 0x76, 0x08, \
-        0x2b, 0x1d, 0x81, 0x68, 0x30, 0xe1, 0xfa, 0x70, 0x6c, 0x13, 0x4e, 0x10, \
-        0x03, 0x35, 0x3e, 0xc5, 0xca, 0x58, 0x20, 0x8a, 0x21, 0x18, 0x38, 0xa0, \
-        0x0f, 0xed, 0xc4, 0xbb, 0x45, 0x6f, 0xf5, 0x84, 0x5b, 0xb0, 0xcf, 0x4e, \
-        0x9d, 0x58, 0x13, 0x6b, 0x35, 0x35, 0x69, 0xa1, 0xd2, 0xc4, 0xf2, 0xc1, \
-        0x48, 0x04, 0x20, 0x51, 0xb9, 0x6b, 0xa4, 0x5d, 0xa5, 0x4b, 0x84, 0x88, \
-        0x43, 0x48, 0x99, 0x2c, 0xbb, 0xa4, 0x97, 0xd6, 0xd6, 0x18, 0xf6, 0xec, \
-        0x5c, 0xd1, 0x31, 0x49, 0xc9, 0xf2, 0x8f, 0x0b, 0x4d, 0xef, 0x09, 0x02, \
-        0xfe, 0x7d, 0xfd, 0xbb, 0xaf, 0x2b, 0x83, 0x94, 0x22, 0xc4, 0xa7, 0x3e, \
-        0x66, 0xf5, 0xe0, 0x57, 0xdc, 0xf2, 0xed, 0x2c, 0x3e, 0x81, 0x74, 0x76, \
-        0x1e, 0x96, 0x6f, 0x74, 0x1e, 0x32, 0x0e, 0x14, 0x31, 0xd0, 0x74, 0xf0, \
-        0xf4, 0x07, 0xbd, 0xc3, 0xd1, 0x22, 0xc2, 0xa8, 0x95, 0x92, 0x06, 0x7f, \
-        0x43, 0x02, 0x91, 0xbc, 0xdd, 0x23, 0x01, 0x89, 0x94, 0x20, 0x44, 0x64, \
-        0xf5, 0x1d, 0x67, 0xd2, 0x8f, 0xe8, 0x69, 0xa5, 0x29, 0x25, 0xe6, 0x50, \
-        0x9c, 0xe3, 0xe9, 0xcb, 0x75, 0x02, 0x81, 0x81, 0x00, 0xe2, 0x29, 0x3e, \
-        0xaa, 0x6b, 0xd5, 0x59, 0x1e, 0x9c, 0xe6, 0x47, 0xd5, 0xb6, 0xd7, 0xe3, \
-        0xf1, 0x8e, 0x9e, 0xe9, 0x83, 0x5f, 0x10, 0x9f, 0x63, 0xec, 0x04, 0x44, \
-        0xcc, 0x3f, 0xf8, 0xd9, 0x3a, 0x17, 0xe0, 0x4f, 0xfe, 0xd8, 0x4d, 0xcd, \
-        0x46, 0x54, 0x74, 0xbf, 0x0a, 0xc4, 0x67, 0x9c, 0xa7, 0xd8, 0x89, 0x65, \
-        0x4c, 0xfd, 0x58, 0x2a, 0x47, 0x0f, 0xf4, 0x37, 0xb6, 0x55, 0xb0, 0x1d, \
-        0xed, 0xa7, 0x39, 0xfc, 0x4f, 0xa3, 0xc4, 0x75, 0x3a, 0xa3, 0x98, 0xa7, \
-        0x45, 0xf5, 0x66, 0xcb, 0x7c, 0x65, 0xfb, 0x80, 0x23, 0xe6, 0xff, 0xfd, \
-        0x99, 0x1f, 0x8e, 0x6b, 0xff, 0x5e, 0x93, 0x66, 0xdf, 0x6c, 0x6f, 0xc3, \
-        0xf6, 0x38, 0x2e, 0xff, 0x69, 0xb5, 0xac, 0xae, 0xbb, 0xc6, 0x71, 0x16, \
-        0x6b, 0xd0, 0xf8, 0x22, 0xd9, 0xf8, 0xa2, 0x72, 0x20, 0xd2, 0xe2, 0x3a, \
-        0x70, 0x4b, 0xde, 0xab, 0x2f, 0x02, 0x81, 0x81, 0x00, 0xda, 0x51, 0x9b, \
-        0xb8, 0xb2, 0x2a, 0x14, 0x75, 0x58, 0x40, 0x8d, 0x27, 0x70, 0xfa, 0x31, \
-        0x48, 0xb0, 0x20, 0x21, 0x34, 0xfa, 0x4c, 0x57, 0xa8, 0x11, 0x88, 0xf3, \
-        0xa7, 0xae, 0x21, 0xe9, 0xb6, 0x2b, 0xd1, 0xcd, 0xa7, 0xf8, 0xd8, 0x0c, \
-        0x8a, 0x76, 0x22, 0x35, 0x44, 0xce, 0x3f, 0x25, 0x29, 0x83, 0x7d, 0x79, \
-        0xa7, 0x31, 0xd6, 0xec, 0xb2, 0xbf, 0xda, 0x34, 0xb6, 0xf6, 0xb2, 0x3b, \
-        0xf3, 0x78, 0x5a, 0x04, 0x83, 0x33, 0x3e, 0xa2, 0xe2, 0x81, 0x82, 0x13, \
-        0xd4, 0x35, 0x17, 0x63, 0x9b, 0x9e, 0xc4, 0x8d, 0x91, 0x4c, 0x03, 0x77, \
-        0xc7, 0x71, 0x5b, 0xee, 0x83, 0x6d, 0xd5, 0x78, 0x88, 0xf6, 0x2c, 0x79, \
-        0xc2, 0x4a, 0xb4, 0x79, 0x90, 0x70, 0xbf, 0xdf, 0x34, 0x56, 0x96, 0x71, \
-        0xe3, 0x0e, 0x68, 0x91, 0xbc, 0xea, 0xcb, 0x33, 0xc0, 0xbe, 0x45, 0xd7, \
-        0xfc, 0x30, 0xfd, 0x01, 0x3b, 0x02, 0x81, 0x81, 0x00, 0xd2, 0x9f, 0x2a, \
-        0xb7, 0x38, 0x19, 0xc7, 0x17, 0x95, 0x73, 0x78, 0xae, 0xf5, 0xcb, 0x75, \
-        0x83, 0x7f, 0x19, 0x4b, 0xcb, 0x86, 0xfb, 0x4a, 0x15, 0x9a, 0xb6, 0x17, \
-        0x04, 0x49, 0x07, 0x8d, 0xf6, 0x66, 0x4a, 0x06, 0xf6, 0x05, 0xa7, 0xdf, \
-        0x66, 0x82, 0x3c, 0xff, 0xb6, 0x1d, 0x57, 0x89, 0x33, 0x5f, 0x9c, 0x05, \
-        0x75, 0x7f, 0xf3, 0x5d, 0xdc, 0x34, 0x65, 0x72, 0x85, 0x22, 0xa4, 0x14, \
-        0x1b, 0x41, 0xc3, 0xe4, 0xd0, 0x9e, 0x69, 0xd5, 0xeb, 0x38, 0x74, 0x70, \
-        0x43, 0xdc, 0xd9, 0x50, 0xe4, 0x97, 0x6d, 0x73, 0xd6, 0xfb, 0xc8, 0xa7, \
-        0xfa, 0xb4, 0xc2, 0xc4, 0x9d, 0x5d, 0x0c, 0xd5, 0x9f, 0x79, 0xb3, 0x54, \
-        0xc2, 0xb7, 0x6c, 0x3d, 0x7d, 0xcb, 0x2d, 0xf8, 0xc4, 0xf3, 0x78, 0x5a, \
-        0x33, 0x2a, 0xb8, 0x0c, 0x6d, 0x06, 0xfa, 0xf2, 0x62, 0xd3, 0x42, 0xd0, \
-        0xbd, 0xc8, 0x4a, 0xa5, 0x0d, 0x02, 0x81, 0x81, 0x00, 0xd4, 0xa9, 0x90, \
-        0x15, 0xde, 0xbf, 0x2c, 0xc4, 0x8d, 0x9d, 0xfb, 0xa1, 0xc2, 0xe4, 0x83, \
-        0xe3, 0x79, 0x65, 0x22, 0xd3, 0xb7, 0x49, 0x6c, 0x4d, 0x94, 0x1f, 0x22, \
-        0xb1, 0x60, 0xe7, 0x3a, 0x00, 0xb1, 0x38, 0xa2, 0xab, 0x0f, 0xb4, 0x6c, \
-        0xaa, 0xe7, 0x9e, 0x34, 0xe3, 0x7c, 0x40, 0x78, 0x53, 0xb2, 0xf9, 0x23, \
-        0xea, 0xa0, 0x9a, 0xea, 0x60, 0xc8, 0x8f, 0xa6, 0xaf, 0xdf, 0x29, 0x09, \
-        0x4b, 0x06, 0x1e, 0x31, 0xad, 0x17, 0xda, 0xd8, 0xd1, 0xe9, 0x33, 0xab, \
-        0x5b, 0x18, 0x08, 0x5b, 0x87, 0xf8, 0xa5, 0x1f, 0xfd, 0xbb, 0xdc, 0xd8, \
-        0xed, 0x97, 0x57, 0xe4, 0xc3, 0x73, 0xd6, 0xf0, 0x9e, 0x01, 0xa6, 0x9b, \
-        0x48, 0x8e, 0x7a, 0xb4, 0xbb, 0xe5, 0x88, 0x91, 0xc5, 0x2a, 0xdf, 0x4b, \
-        0xba, 0xd0, 0x8b, 0x3e, 0x03, 0x97, 0x77, 0x2f, 0x47, 0x7e, 0x51, 0x0c, \
-        0xae, 0x65, 0x8d, 0xde, 0x87, 0x02, 0x81, 0x80, 0x20, 0x24, 0x0f, 0xd2, \
-        0xaf, 0xc2, 0x28, 0x3b, 0x97, 0x20, 0xb2, 0x92, 0x49, 0xeb, 0x09, 0x68, \
-        0x40, 0xb2, 0xbe, 0xd1, 0xc3, 0x83, 0x94, 0x34, 0x38, 0xd6, 0xc9, 0xec, \
-        0x34, 0x09, 0xf9, 0x41, 0x6d, 0x5c, 0x42, 0x94, 0xf7, 0x04, 0xfc, 0x32, \
-        0x39, 0x69, 0xbc, 0x1c, 0xfb, 0x3e, 0x61, 0x98, 0xc0, 0x80, 0xd8, 0x36, \
-        0x47, 0xc3, 0x6d, 0xc2, 0x2e, 0xe7, 0x81, 0x2a, 0x17, 0x34, 0x64, 0x30, \
-        0x4e, 0x96, 0xbb, 0x26, 0x16, 0xb9, 0x41, 0x36, 0xfe, 0x8a, 0xd6, 0x53, \
-        0x7c, 0xaa, 0xec, 0x39, 0x42, 0x50, 0xef, 0xe3, 0xb3, 0x01, 0x28, 0x32, \
-        0xca, 0x6d, 0xf5, 0x9a, 0x1e, 0x9f, 0x37, 0xbe, 0xfe, 0x38, 0x20, 0x22, \
-        0x91, 0x8c, 0xcd, 0x95, 0x02, 0xf2, 0x4d, 0x6f, 0x1a, 0xb4, 0x43, 0xf0, \
-        0x19, 0xdf, 0x65, 0xc0, 0x92, 0xe7, 0x9d, 0x2f, 0x09, 0xe7, 0xec, 0x69, \
-        0xa8, 0xc2, 0x8f, 0x0d                                                  \
-}
-/* END FILE */
-
-/* This is taken from server5.crt. */
-/* BEGIN FILE string macro TEST_SRV_CRT_EC_PEM server5.crt */
-#define TEST_SRV_CRT_EC_PEM                                                    \
-    "-----BEGIN CERTIFICATE-----\r\n"                                          \
-    "MIICIDCCAaWgAwIBAgIBCTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n"     \
-    "A1UECgwIUG9sYXJTU0wxHDAaBgNVBAMME1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n"     \
-    "MjMwNTE3MDcxMDM2WhcNMzMwNTE0MDcxMDM2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n"     \
-    "A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG\r\n"     \
-    "CCqGSM49AwEHA0IABDfMVtl2CR5acj7HWS3/IG7ufPkGkXTQrRS192giWWKSTuUA\r\n"     \
-    "2CMR/+ov0jRdXRa9iojCa3cNVc2KKg76Aci07f+jgZ0wgZowCQYDVR0TBAIwADAd\r\n"     \
-    "BgNVHQ4EFgQUUGGlj9QH2deCAQzlZX+MY0anE74wbgYDVR0jBGcwZYAUnW0gJEkB\r\n"     \
-    "PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKDAhQb2xh\r\n"     \
-    "clNTTDEcMBoGA1UEAwwTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG\r\n"     \
-    "CCqGSM49BAMCA2kAMGYCMQDg6p7PPfr2+n7nGvya3pU4ust3k7Obk4/tZX+uHHRQ\r\n"     \
-    "qaccsyULeFNzkyRvWHFeT5sCMQCzDJX79Ii7hILYza/iXWJe/BjJEE8MteCRGXDN\r\n"     \
-    "06jC+BLgOH1KQV9ArqEh3AhOhEg=\r\n"                                         \
-    "-----END CERTIFICATE-----\r\n"
-/* END FILE */
-
-/* This is generated from server5.crt.der. */
-/* BEGIN FILE binary macro TEST_SRV_CRT_EC_DER server5.crt.der */
-#define TEST_SRV_CRT_EC_DER {                                                   \
-        0x30, 0x82, 0x02, 0x20, 0x30, 0x82, 0x01, 0xa5, 0xa0, 0x03, 0x02, 0x01, \
-        0x02, 0x02, 0x01, 0x09, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \
-        0x3d, 0x04, 0x03, 0x02, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \
-        0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \
-        0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \
-        0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \
-        0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, \
-        0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \
-        0x32, 0x33, 0x30, 0x35, 0x31, 0x37, 0x30, 0x37, 0x31, 0x30, 0x33, 0x36, \
-        0x5a, 0x17, 0x0d, 0x33, 0x33, 0x30, 0x35, 0x31, 0x34, 0x30, 0x37, 0x31, \
-        0x30, 0x33, 0x36, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \
-        0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \
-        0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \
-        0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \
-        0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x59, \
-        0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, \
-        0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, \
-        0x04, 0x37, 0xcc, 0x56, 0xd9, 0x76, 0x09, 0x1e, 0x5a, 0x72, 0x3e, 0xc7, \
-        0x59, 0x2d, 0xff, 0x20, 0x6e, 0xee, 0x7c, 0xf9, 0x06, 0x91, 0x74, 0xd0, \
-        0xad, 0x14, 0xb5, 0xf7, 0x68, 0x22, 0x59, 0x62, 0x92, 0x4e, 0xe5, 0x00, \
-        0xd8, 0x23, 0x11, 0xff, 0xea, 0x2f, 0xd2, 0x34, 0x5d, 0x5d, 0x16, 0xbd, \
-        0x8a, 0x88, 0xc2, 0x6b, 0x77, 0x0d, 0x55, 0xcd, 0x8a, 0x2a, 0x0e, 0xfa, \
-        0x01, 0xc8, 0xb4, 0xed, 0xff, 0xa3, 0x81, 0x9d, 0x30, 0x81, 0x9a, 0x30, \
-        0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, \
-        0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x50, 0x61, 0xa5, \
-        0x8f, 0xd4, 0x07, 0xd9, 0xd7, 0x82, 0x01, 0x0c, 0xe5, 0x65, 0x7f, 0x8c, \
-        0x63, 0x46, 0xa7, 0x13, 0xbe, 0x30, 0x6e, 0x06, 0x03, 0x55, 0x1d, 0x23, \
-        0x04, 0x67, 0x30, 0x65, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, 0x01, \
-        0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, 0xfb, \
-        0x36, 0x7c, 0xa1, 0x42, 0xa4, 0x40, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, \
-        0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \
-        0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \
-        0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, \
-        0x03, 0x0c, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, \
-        0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x82, 0x09, \
-        0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8, 0x30, 0x0a, 0x06, \
-        0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x69, 0x00, \
-        0x30, 0x66, 0x02, 0x31, 0x00, 0xe0, 0xea, 0x9e, 0xcf, 0x3d, 0xfa, 0xf6, \
-        0xfa, 0x7e, 0xe7, 0x1a, 0xfc, 0x9a, 0xde, 0x95, 0x38, 0xba, 0xcb, 0x77, \
-        0x93, 0xb3, 0x9b, 0x93, 0x8f, 0xed, 0x65, 0x7f, 0xae, 0x1c, 0x74, 0x50, \
-        0xa9, 0xa7, 0x1c, 0xb3, 0x25, 0x0b, 0x78, 0x53, 0x73, 0x93, 0x24, 0x6f, \
-        0x58, 0x71, 0x5e, 0x4f, 0x9b, 0x02, 0x31, 0x00, 0xb3, 0x0c, 0x95, 0xfb, \
-        0xf4, 0x88, 0xbb, 0x84, 0x82, 0xd8, 0xcd, 0xaf, 0xe2, 0x5d, 0x62, 0x5e, \
-        0xfc, 0x18, 0xc9, 0x10, 0x4f, 0x0c, 0xb5, 0xe0, 0x91, 0x19, 0x70, 0xcd, \
-        0xd3, 0xa8, 0xc2, 0xf8, 0x12, 0xe0, 0x38, 0x7d, 0x4a, 0x41, 0x5f, 0x40, \
-        0xae, 0xa1, 0x21, 0xdc, 0x08, 0x4e, 0x84, 0x48                          \
-}
-/* END FILE */
-
-/* This is taken from server5.key. */
-/* BEGIN FILE string macro TEST_SRV_KEY_EC_PEM server5.key */
-#define TEST_SRV_KEY_EC_PEM                                                    \
-    "-----BEGIN EC PRIVATE KEY-----\r\n"                                       \
-    "MHcCAQEEIPEqEyB2AnCoPL/9U/YDHvdqXYbIogTywwyp6/UfDw6noAoGCCqGSM49\r\n"     \
-    "AwEHoUQDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/\r\n"     \
-    "6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/w==\r\n"                                 \
-    "-----END EC PRIVATE KEY-----\r\n"
-/* END FILE */
-
-/* This is generated from server5.key.der. */
-/* BEGIN FILE binary macro TEST_SRV_KEY_EC_DER server5.key.der */
-#define TEST_SRV_KEY_EC_DER {                                                   \
-        0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf1, 0x2a, 0x13, 0x20, 0x76, \
-        0x02, 0x70, 0xa8, 0x3c, 0xbf, 0xfd, 0x53, 0xf6, 0x03, 0x1e, 0xf7, 0x6a, \
-        0x5d, 0x86, 0xc8, 0xa2, 0x04, 0xf2, 0xc3, 0x0c, 0xa9, 0xeb, 0xf5, 0x1f, \
-        0x0f, 0x0e, 0xa7, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \
-        0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x37, 0xcc, 0x56, \
-        0xd9, 0x76, 0x09, 0x1e, 0x5a, 0x72, 0x3e, 0xc7, 0x59, 0x2d, 0xff, 0x20, \
-        0x6e, 0xee, 0x7c, 0xf9, 0x06, 0x91, 0x74, 0xd0, 0xad, 0x14, 0xb5, 0xf7, \
-        0x68, 0x22, 0x59, 0x62, 0x92, 0x4e, 0xe5, 0x00, 0xd8, 0x23, 0x11, 0xff, \
-        0xea, 0x2f, 0xd2, 0x34, 0x5d, 0x5d, 0x16, 0xbd, 0x8a, 0x88, 0xc2, 0x6b, \
-        0x77, 0x0d, 0x55, 0xcd, 0x8a, 0x2a, 0x0e, 0xfa, 0x01, 0xc8, 0xb4, 0xed, \
-        0xff                                                                    \
-}
-/* END FILE */
-
-/* This is taken from server2-sha256.crt. */
-/* BEGIN FILE string macro TEST_SRV_CRT_RSA_SHA256_PEM server2-sha256.crt */
-#define TEST_SRV_CRT_RSA_SHA256_PEM                                            \
-    "-----BEGIN CERTIFICATE-----\r\n"                                          \
-    "MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n"     \
-    "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"     \
-    "MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n"     \
-    "A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n"     \
-    "AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n"     \
-    "owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n"     \
-    "NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n"     \
-    "tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n"     \
-    "hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n"     \
-    "HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n"     \
-    "VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n"     \
-    "FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQELBQADggEBAC465FJh\r\n"     \
-    "Pqel7zJngHIHJrqj/wVAxGAFOTF396XKATGAp+HRCqJ81Ry60CNK1jDzk8dv6M6U\r\n"     \
-    "HoS7RIFiM/9rXQCbJfiPD5xMTejZp5n5UYHAmxsxDaazfA5FuBhkfokKK6jD4Eq9\r\n"     \
-    "1C94xGKb6X4/VkaPF7cqoBBw/bHxawXc0UEPjqayiBpCYU/rJoVZgLqFVP7Px3sv\r\n"     \
-    "a1nOrNx8rPPI1hJ+ZOg8maiPTxHZnBVLakSSLQy/sWeWyazO1RnrbxjrbgQtYKz0\r\n"     \
-    "e3nwGpu1w13vfckFmUSBhHXH7AAS/HpKC4IH7G2GAk3+n8iSSN71sZzpxonQwVbo\r\n"     \
-    "pMZqLmbBm/7WPLc=\r\n"                                                     \
-    "-----END CERTIFICATE-----\r\n"
-/* END FILE */
-
-/* This is generated from server2-sha256.crt.der. */
-/* BEGIN FILE binary macro TEST_SRV_CRT_RSA_SHA256_DER server2-sha256.crt.der */
-#define TEST_SRV_CRT_RSA_SHA256_DER {                                           \
-        0x30, 0x82, 0x03, 0x37, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, \
-        0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \
-        0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \
-        0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \
-        0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \
-        0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \
-        0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \
-        0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \
-        0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \
-        0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \
-        0x34, 0x30, 0x36, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \
-        0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \
-        0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \
-        0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \
-        0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82, \
-        0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, \
-        0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, \
-        0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, \
-        0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, 0xb8, 0x99, 0xac, 0x0e, 0x78, \
-        0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, 0x16, 0xd0, 0x5a, 0xe4, 0xcd, \
-        0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, 0x96, 0xa7, 0x52, 0xb4, 0x90, \
-        0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, 0xfc, 0xb6, 0x34, 0xac, 0x24, \
-        0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, 0xb0, 0x28, 0x7d, 0xa1, 0xda, \
-        0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, 0xfe, 0xc1, 0x04, 0x52, 0xb3, \
-        0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, 0xd8, 0x90, 0xc1, 0x61, 0xb4, \
-        0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, 0xab, 0x74, 0x5e, 0x07, 0x7d, \
-        0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, 0xd9, 0x0d, 0x1c, 0x2d, 0x49, \
-        0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, 0x0b, 0x8a, 0x4f, 0x69, 0x0c, \
-        0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, 0x66, 0x7d, 0xae, 0x54, 0x2b, \
-        0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, 0xc3, 0xcd, 0x40, 0x49, 0x08, \
-        0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, 0x46, 0xbf, 0xd0, 0xb8, 0xaa, \
-        0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, 0x1e, 0x44, 0x18, 0x0f, 0x0f, \
-        0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, 0x18, 0xc6, 0x62, 0x2f, 0xc7, \
-        0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, 0x27, 0x89, 0x29, 0x01, 0xc5, \
-        0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, 0x4a, 0x0e, 0xef, 0xd6, 0xde, \
-        0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, 0x7a, 0xc4, 0x02, 0x3c, 0x9a, \
-        0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, 0xcb, 0x73, 0x4b, 0x52, 0x96, \
-        0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, 0x39, 0x5a, 0xd3, 0x0f, 0xb0, \
-        0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, 0x12, 0x01, 0x30, 0x97, 0x02, \
-        0x03, 0x01, 0x00, 0x01, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, \
-        0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, \
-        0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa5, 0x05, 0xe8, 0x64, 0xb8, 0xdc, \
-        0xdf, 0x60, 0x0f, 0x50, 0x12, 0x4d, 0x60, 0xa8, 0x64, 0xaf, 0x4d, 0x8b, \
-        0x43, 0x93, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, \
-        0x16, 0x80, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, \
-        0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, \
-        0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, \
-        0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x2e, 0x3a, 0xe4, 0x52, 0x61, \
-        0x3e, 0xa7, 0xa5, 0xef, 0x32, 0x67, 0x80, 0x72, 0x07, 0x26, 0xba, 0xa3, \
-        0xff, 0x05, 0x40, 0xc4, 0x60, 0x05, 0x39, 0x31, 0x77, 0xf7, 0xa5, 0xca, \
-        0x01, 0x31, 0x80, 0xa7, 0xe1, 0xd1, 0x0a, 0xa2, 0x7c, 0xd5, 0x1c, 0xba, \
-        0xd0, 0x23, 0x4a, 0xd6, 0x30, 0xf3, 0x93, 0xc7, 0x6f, 0xe8, 0xce, 0x94, \
-        0x1e, 0x84, 0xbb, 0x44, 0x81, 0x62, 0x33, 0xff, 0x6b, 0x5d, 0x00, 0x9b, \
-        0x25, 0xf8, 0x8f, 0x0f, 0x9c, 0x4c, 0x4d, 0xe8, 0xd9, 0xa7, 0x99, 0xf9, \
-        0x51, 0x81, 0xc0, 0x9b, 0x1b, 0x31, 0x0d, 0xa6, 0xb3, 0x7c, 0x0e, 0x45, \
-        0xb8, 0x18, 0x64, 0x7e, 0x89, 0x0a, 0x2b, 0xa8, 0xc3, 0xe0, 0x4a, 0xbd, \
-        0xd4, 0x2f, 0x78, 0xc4, 0x62, 0x9b, 0xe9, 0x7e, 0x3f, 0x56, 0x46, 0x8f, \
-        0x17, 0xb7, 0x2a, 0xa0, 0x10, 0x70, 0xfd, 0xb1, 0xf1, 0x6b, 0x05, 0xdc, \
-        0xd1, 0x41, 0x0f, 0x8e, 0xa6, 0xb2, 0x88, 0x1a, 0x42, 0x61, 0x4f, 0xeb, \
-        0x26, 0x85, 0x59, 0x80, 0xba, 0x85, 0x54, 0xfe, 0xcf, 0xc7, 0x7b, 0x2f, \
-        0x6b, 0x59, 0xce, 0xac, 0xdc, 0x7c, 0xac, 0xf3, 0xc8, 0xd6, 0x12, 0x7e, \
-        0x64, 0xe8, 0x3c, 0x99, 0xa8, 0x8f, 0x4f, 0x11, 0xd9, 0x9c, 0x15, 0x4b, \
-        0x6a, 0x44, 0x92, 0x2d, 0x0c, 0xbf, 0xb1, 0x67, 0x96, 0xc9, 0xac, 0xce, \
-        0xd5, 0x19, 0xeb, 0x6f, 0x18, 0xeb, 0x6e, 0x04, 0x2d, 0x60, 0xac, 0xf4, \
-        0x7b, 0x79, 0xf0, 0x1a, 0x9b, 0xb5, 0xc3, 0x5d, 0xef, 0x7d, 0xc9, 0x05, \
-        0x99, 0x44, 0x81, 0x84, 0x75, 0xc7, 0xec, 0x00, 0x12, 0xfc, 0x7a, 0x4a, \
-        0x0b, 0x82, 0x07, 0xec, 0x6d, 0x86, 0x02, 0x4d, 0xfe, 0x9f, 0xc8, 0x92, \
-        0x48, 0xde, 0xf5, 0xb1, 0x9c, 0xe9, 0xc6, 0x89, 0xd0, 0xc1, 0x56, 0xe8, \
-        0xa4, 0xc6, 0x6a, 0x2e, 0x66, 0xc1, 0x9b, 0xfe, 0xd6, 0x3c, 0xb7        \
-}
-/* END FILE */
-
-/* This is taken from server2.crt. */
-/* BEGIN FILE string macro TEST_SRV_CRT_RSA_SHA1_PEM server2.crt */
-#define TEST_SRV_CRT_RSA_SHA1_PEM                                              \
-    "-----BEGIN CERTIFICATE-----\r\n"                                          \
-    "MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"     \
-    "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"     \
-    "MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n"     \
-    "A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n"     \
-    "AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n"     \
-    "owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n"     \
-    "NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n"     \
-    "tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n"     \
-    "hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n"     \
-    "HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n"     \
-    "VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n"     \
-    "FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJklg3Q4\r\n"     \
-    "cB7v7BzsxM/vLyKccO6op0/gZzM4ghuLq2Y32kl0sM6kSNUUmduuq3u/+GmUZN2A\r\n"     \
-    "O/7c+Hw7hDFEIvZk98aBGjCLqn3DmgHIv8ToQ67nellQxx2Uj309PdgjNi/r9HOc\r\n"     \
-    "KNAYPbBcg6MJGWWj2TI6vNaceios/DhOYx5V0j5nfqSJ/pnU0g9Ign2LAhgYpGJE\r\n"     \
-    "iEM9wW7hEMkwmk0h/sqZsrJsGH5YsF/VThSq/JVO1e2mZH2vruyZKJVBq+8tDNYp\r\n"     \
-    "HkK6tSyVYQhzIt3StMJWKMl/o5k2AYz6tSC164+1oG+ML3LWg8XrGKa91H4UOKap\r\n"     \
-    "Awgk0+4m0T25cNs=\r\n"                                                     \
-    "-----END CERTIFICATE-----\r\n"
-/* END FILE */
-
-/* This is generated from server2.crt.der. */
-/* BEGIN FILE binary macro TEST_SRV_CRT_RSA_SHA1_DER server2.crt.der */
-#define TEST_SRV_CRT_RSA_SHA1_DER {                                             \
-        0x30, 0x82, 0x03, 0x37, 0x30, 0x82, 0x02, 0x1f, 0xa0, 0x03, 0x02, 0x01, \
-        0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \
-        0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \
-        0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \
-        0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \
-        0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \
-        0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \
-        0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \
-        0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \
-        0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \
-        0x34, 0x30, 0x36, 0x5a, 0x30, 0x34, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \
-        0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \
-        0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \
-        0x53, 0x4c, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \
-        0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30, 0x82, \
-        0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, \
-        0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, \
-        0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc1, 0x4d, 0xa3, 0xdd, 0xe7, \
-        0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, 0xb8, 0x99, 0xac, 0x0e, 0x78, \
-        0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, 0x16, 0xd0, 0x5a, 0xe4, 0xcd, \
-        0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, 0x96, 0xa7, 0x52, 0xb4, 0x90, \
-        0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, 0xfc, 0xb6, 0x34, 0xac, 0x24, \
-        0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, 0xb0, 0x28, 0x7d, 0xa1, 0xda, \
-        0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, 0xfe, 0xc1, 0x04, 0x52, 0xb3, \
-        0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, 0xd8, 0x90, 0xc1, 0x61, 0xb4, \
-        0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, 0xab, 0x74, 0x5e, 0x07, 0x7d, \
-        0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, 0xd9, 0x0d, 0x1c, 0x2d, 0x49, \
-        0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, 0x0b, 0x8a, 0x4f, 0x69, 0x0c, \
-        0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, 0x66, 0x7d, 0xae, 0x54, 0x2b, \
-        0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, 0xc3, 0xcd, 0x40, 0x49, 0x08, \
-        0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, 0x46, 0xbf, 0xd0, 0xb8, 0xaa, \
-        0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, 0x1e, 0x44, 0x18, 0x0f, 0x0f, \
-        0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, 0x18, 0xc6, 0x62, 0x2f, 0xc7, \
-        0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, 0x27, 0x89, 0x29, 0x01, 0xc5, \
-        0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, 0x4a, 0x0e, 0xef, 0xd6, 0xde, \
-        0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, 0x7a, 0xc4, 0x02, 0x3c, 0x9a, \
-        0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, 0xcb, 0x73, 0x4b, 0x52, 0x96, \
-        0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, 0x39, 0x5a, 0xd3, 0x0f, 0xb0, \
-        0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, 0x12, 0x01, 0x30, 0x97, 0x02, \
-        0x03, 0x01, 0x00, 0x01, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, \
-        0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, \
-        0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa5, 0x05, 0xe8, 0x64, 0xb8, 0xdc, \
-        0xdf, 0x60, 0x0f, 0x50, 0x12, 0x4d, 0x60, 0xa8, 0x64, 0xaf, 0x4d, 0x8b, \
-        0x43, 0x93, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, \
-        0x16, 0x80, 0x14, 0xb4, 0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, \
-        0xb9, 0xd5, 0xa6, 0x95, 0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, \
-        0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, \
-        0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x99, 0x25, 0x83, 0x74, 0x38, \
-        0x70, 0x1e, 0xef, 0xec, 0x1c, 0xec, 0xc4, 0xcf, 0xef, 0x2f, 0x22, 0x9c, \
-        0x70, 0xee, 0xa8, 0xa7, 0x4f, 0xe0, 0x67, 0x33, 0x38, 0x82, 0x1b, 0x8b, \
-        0xab, 0x66, 0x37, 0xda, 0x49, 0x74, 0xb0, 0xce, 0xa4, 0x48, 0xd5, 0x14, \
-        0x99, 0xdb, 0xae, 0xab, 0x7b, 0xbf, 0xf8, 0x69, 0x94, 0x64, 0xdd, 0x80, \
-        0x3b, 0xfe, 0xdc, 0xf8, 0x7c, 0x3b, 0x84, 0x31, 0x44, 0x22, 0xf6, 0x64, \
-        0xf7, 0xc6, 0x81, 0x1a, 0x30, 0x8b, 0xaa, 0x7d, 0xc3, 0x9a, 0x01, 0xc8, \
-        0xbf, 0xc4, 0xe8, 0x43, 0xae, 0xe7, 0x7a, 0x59, 0x50, 0xc7, 0x1d, 0x94, \
-        0x8f, 0x7d, 0x3d, 0x3d, 0xd8, 0x23, 0x36, 0x2f, 0xeb, 0xf4, 0x73, 0x9c, \
-        0x28, 0xd0, 0x18, 0x3d, 0xb0, 0x5c, 0x83, 0xa3, 0x09, 0x19, 0x65, 0xa3, \
-        0xd9, 0x32, 0x3a, 0xbc, 0xd6, 0x9c, 0x7a, 0x2a, 0x2c, 0xfc, 0x38, 0x4e, \
-        0x63, 0x1e, 0x55, 0xd2, 0x3e, 0x67, 0x7e, 0xa4, 0x89, 0xfe, 0x99, 0xd4, \
-        0xd2, 0x0f, 0x48, 0x82, 0x7d, 0x8b, 0x02, 0x18, 0x18, 0xa4, 0x62, 0x44, \
-        0x88, 0x43, 0x3d, 0xc1, 0x6e, 0xe1, 0x10, 0xc9, 0x30, 0x9a, 0x4d, 0x21, \
-        0xfe, 0xca, 0x99, 0xb2, 0xb2, 0x6c, 0x18, 0x7e, 0x58, 0xb0, 0x5f, 0xd5, \
-        0x4e, 0x14, 0xaa, 0xfc, 0x95, 0x4e, 0xd5, 0xed, 0xa6, 0x64, 0x7d, 0xaf, \
-        0xae, 0xec, 0x99, 0x28, 0x95, 0x41, 0xab, 0xef, 0x2d, 0x0c, 0xd6, 0x29, \
-        0x1e, 0x42, 0xba, 0xb5, 0x2c, 0x95, 0x61, 0x08, 0x73, 0x22, 0xdd, 0xd2, \
-        0xb4, 0xc2, 0x56, 0x28, 0xc9, 0x7f, 0xa3, 0x99, 0x36, 0x01, 0x8c, 0xfa, \
-        0xb5, 0x20, 0xb5, 0xeb, 0x8f, 0xb5, 0xa0, 0x6f, 0x8c, 0x2f, 0x72, 0xd6, \
-        0x83, 0xc5, 0xeb, 0x18, 0xa6, 0xbd, 0xd4, 0x7e, 0x14, 0x38, 0xa6, 0xa9, \
-        0x03, 0x08, 0x24, 0xd3, 0xee, 0x26, 0xd1, 0x3d, 0xb9, 0x70, 0xdb        \
-}
-/* END FILE */
-
-/* This is taken from server2.key. */
-/* BEGIN FILE string macro TEST_SRV_KEY_RSA_PEM server2.key */
-#define TEST_SRV_KEY_RSA_PEM                                                   \
-    "-----BEGIN RSA PRIVATE KEY-----\r\n"                                      \
-    "MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n"     \
-    "lqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\r\n"     \
-    "2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\r\n"     \
-    "Zn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\r\n"     \
-    "GMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\r\n"     \
-    "y3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\r\n"     \
-    "++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\r\n"     \
-    "Z0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\r\n"     \
-    "/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\r\n"     \
-    "WYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\r\n"     \
-    "GTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\r\n"     \
-    "TWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\r\n"     \
-    "CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n"     \
-    "nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n"     \
-    "AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n"     \
-    "sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n"     \
-    "mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n"     \
-    "BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n"     \
-    "whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n"     \
-    "vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n"     \
-    "3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n"     \
-    "3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n"     \
-    "ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n"     \
-    "4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n"     \
-    "TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n"             \
-    "-----END RSA PRIVATE KEY-----\r\n"
-/* END FILE */
-
-/* This is generated from server2.key.der. */
-/* BEGIN FILE binary macro TEST_SRV_KEY_RSA_DER server2.key.der */
-#define TEST_SRV_KEY_RSA_DER {                                                  \
-        0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \
-        0xc1, 0x4d, 0xa3, 0xdd, 0xe7, 0xcd, 0x1d, 0xd1, 0x04, 0xd7, 0x49, 0x72, \
-        0xb8, 0x99, 0xac, 0x0e, 0x78, 0xe4, 0x3a, 0x3c, 0x4a, 0xcf, 0x3a, 0x13, \
-        0x16, 0xd0, 0x5a, 0xe4, 0xcd, 0xa3, 0x00, 0x88, 0xa7, 0xee, 0x1e, 0x6b, \
-        0x96, 0xa7, 0x52, 0xb4, 0x90, 0xef, 0x2d, 0x72, 0x7a, 0x3e, 0x24, 0x9a, \
-        0xfc, 0xb6, 0x34, 0xac, 0x24, 0xf5, 0x77, 0xe0, 0x26, 0x64, 0x8c, 0x9c, \
-        0xb0, 0x28, 0x7d, 0xa1, 0xda, 0xea, 0x8c, 0xe6, 0xc9, 0x1c, 0x96, 0xbc, \
-        0xfe, 0xc1, 0x04, 0x52, 0xb3, 0x36, 0xd4, 0xa3, 0xfa, 0xe1, 0xb1, 0x76, \
-        0xd8, 0x90, 0xc1, 0x61, 0xb4, 0x66, 0x52, 0x36, 0xa2, 0x26, 0x53, 0xaa, \
-        0xab, 0x74, 0x5e, 0x07, 0x7d, 0x19, 0x82, 0xdb, 0x2a, 0xd8, 0x1f, 0xa0, \
-        0xd9, 0x0d, 0x1c, 0x2d, 0x49, 0x66, 0xf7, 0x5b, 0x25, 0x73, 0x46, 0xe8, \
-        0x0b, 0x8a, 0x4f, 0x69, 0x0c, 0xb5, 0x00, 0x90, 0xe1, 0xda, 0x82, 0x10, \
-        0x66, 0x7d, 0xae, 0x54, 0x2b, 0x8b, 0x65, 0x79, 0x91, 0xa1, 0xe2, 0x61, \
-        0xc3, 0xcd, 0x40, 0x49, 0x08, 0xee, 0x68, 0x0c, 0xf1, 0x8b, 0x86, 0xd2, \
-        0x46, 0xbf, 0xd0, 0xb8, 0xaa, 0x11, 0x03, 0x1e, 0x7f, 0x56, 0xa8, 0x1a, \
-        0x1e, 0x44, 0x18, 0x0f, 0x0f, 0x85, 0x8b, 0xda, 0x8b, 0x44, 0x5e, 0xe2, \
-        0x18, 0xc6, 0x62, 0x2f, 0xc7, 0x66, 0x8d, 0xfa, 0x5d, 0xd8, 0x7d, 0xf3, \
-        0x27, 0x89, 0x29, 0x01, 0xc5, 0x90, 0x0e, 0x3f, 0x27, 0xf1, 0x30, 0xc8, \
-        0x4a, 0x0e, 0xef, 0xd6, 0xde, 0xc7, 0xc7, 0x27, 0x6b, 0xc7, 0x05, 0x3d, \
-        0x7a, 0xc4, 0x02, 0x3c, 0x9a, 0x1d, 0x3e, 0x0f, 0xe8, 0x34, 0x98, 0x5b, \
-        0xcb, 0x73, 0x4b, 0x52, 0x96, 0xd8, 0x11, 0xa2, 0x2c, 0x80, 0x88, 0x69, \
-        0x39, 0x5a, 0xd3, 0x0f, 0xb0, 0xde, 0x59, 0x2f, 0x11, 0xc7, 0xf7, 0xea, \
-        0x12, 0x01, 0x30, 0x97, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \
-        0x01, 0x00, 0x97, 0x47, 0x44, 0xbc, 0x10, 0x81, 0xc5, 0x18, 0xe4, 0x59, \
-        0xfb, 0xe0, 0x2d, 0x3a, 0x0e, 0x9e, 0x10, 0xdc, 0x43, 0xfb, 0x15, 0x6c, \
-        0xd1, 0xfd, 0x48, 0x78, 0x6c, 0xf9, 0xed, 0x38, 0xe8, 0xdd, 0x09, 0xd7, \
-        0x5f, 0xb5, 0x41, 0x64, 0xd7, 0x63, 0xfa, 0x9d, 0x44, 0x0a, 0xf8, 0x42, \
-        0x13, 0xf1, 0xbb, 0x5e, 0x79, 0x20, 0x53, 0x98, 0x4b, 0x65, 0x7f, 0x86, \
-        0x67, 0x48, 0xe4, 0xcf, 0xfb, 0x6a, 0x24, 0xe2, 0x34, 0xbd, 0x14, 0x9d, \
-        0x2c, 0x16, 0xe2, 0xa4, 0x79, 0xd6, 0xa2, 0xec, 0x81, 0x43, 0x87, 0xbf, \
-        0x03, 0x5c, 0x88, 0x25, 0xd9, 0x41, 0xb6, 0xa5, 0xf1, 0x27, 0x52, 0x84, \
-        0xfe, 0x2b, 0x6e, 0x1d, 0x16, 0xcd, 0x73, 0x88, 0xf8, 0x90, 0xbf, 0x19, \
-        0xfe, 0xbe, 0xa9, 0xbf, 0x09, 0xd3, 0x23, 0x43, 0xd2, 0xc7, 0x61, 0x2a, \
-        0xb3, 0x4e, 0x3c, 0x61, 0xd4, 0xbd, 0xd8, 0xb4, 0xfa, 0xa8, 0x0b, 0xf8, \
-        0x7e, 0x56, 0xcd, 0x0f, 0x13, 0x27, 0xda, 0xe6, 0x3b, 0xb3, 0x8c, 0x9c, \
-        0x4b, 0x84, 0x3c, 0xc3, 0x52, 0x57, 0x9c, 0x27, 0x9a, 0x02, 0x76, 0x26, \
-        0x59, 0x82, 0x39, 0xc3, 0x13, 0xbe, 0x6e, 0xf4, 0x44, 0x2d, 0x1d, 0x8c, \
-        0x73, 0x3e, 0x43, 0x99, 0x59, 0xcb, 0xf2, 0x34, 0x72, 0x9a, 0x5e, 0xa5, \
-        0xeb, 0x9f, 0x36, 0x6d, 0x2b, 0xf9, 0xa2, 0xe7, 0xd1, 0x78, 0x52, 0x1b, \
-        0xc8, 0xf6, 0x5b, 0x41, 0x69, 0x57, 0x81, 0x89, 0xe9, 0xbb, 0xa1, 0xde, \
-        0x19, 0x37, 0x3b, 0x13, 0x5c, 0xca, 0x61, 0x01, 0x86, 0xff, 0xdf, 0x83, \
-        0x41, 0x49, 0x7f, 0xd6, 0xf4, 0x2e, 0x08, 0xfa, 0x90, 0xc2, 0x7c, 0xb4, \
-        0xb5, 0x0a, 0x17, 0xdb, 0x0e, 0x6d, 0x75, 0x8a, 0x5d, 0x31, 0xd5, 0x66, \
-        0xfb, 0x39, 0x0b, 0xb5, 0xb6, 0xa3, 0xcd, 0xd4, 0xef, 0x88, 0x92, 0x5a, \
-        0x4d, 0x6c, 0xcb, 0xea, 0x5b, 0x79, 0x02, 0x81, 0x81, 0x00, 0xdf, 0x3a, \
-        0xf9, 0x25, 0x5e, 0x24, 0x37, 0x26, 0x40, 0x97, 0x2f, 0xe0, 0x4a, 0xba, \
-        0x52, 0x1b, 0x51, 0xaf, 0x84, 0x06, 0x32, 0x24, 0x0c, 0xcf, 0x44, 0xa8, \
-        0x77, 0xa7, 0xad, 0xb5, 0x8c, 0x58, 0xcc, 0xc8, 0x31, 0xb7, 0x0d, 0xbc, \
-        0x08, 0x8a, 0xe0, 0xa6, 0x8c, 0xc2, 0x73, 0xe5, 0x1a, 0x64, 0x92, 0xe8, \
-        0xed, 0x4c, 0x6f, 0x0b, 0xa6, 0xa7, 0xf3, 0x9a, 0xf5, 0x6f, 0x69, 0xca, \
-        0x3c, 0x22, 0xd0, 0x15, 0xa8, 0x20, 0x27, 0x41, 0xf8, 0x43, 0x42, 0x7f, \
-        0xb1, 0x93, 0xa1, 0x04, 0x85, 0xda, 0xa0, 0x1c, 0xd6, 0xc6, 0xf7, 0x8a, \
-        0x9e, 0xea, 0x5c, 0x78, 0xa7, 0x55, 0xc4, 0x6b, 0x05, 0x8b, 0xc0, 0x83, \
-        0xcb, 0xce, 0x83, 0x05, 0xf8, 0xb2, 0x16, 0x2b, 0xdf, 0x06, 0x3f, 0xb8, \
-        0xec, 0x16, 0xda, 0x43, 0x33, 0xc1, 0x8f, 0xb0, 0xb8, 0xac, 0xae, 0xd4, \
-        0x94, 0xb8, 0xda, 0x6f, 0x6a, 0xc3, 0x02, 0x81, 0x81, 0x00, 0xdd, 0xae, \
-        0x00, 0xcd, 0xa0, 0x72, 0x1a, 0x05, 0x8a, 0xee, 0x2f, 0xd4, 0x71, 0x4b, \
-        0xf0, 0x3e, 0xe5, 0xc1, 0xe1, 0x29, 0x8b, 0xa6, 0x67, 0x30, 0x98, 0xe7, \
-        0x12, 0xef, 0xdd, 0x12, 0x01, 0x90, 0x24, 0x58, 0xf0, 0x76, 0x92, 0xe7, \
-        0x3d, 0xbb, 0x23, 0xe1, 0xce, 0xf9, 0xa1, 0xd4, 0x38, 0x1b, 0x3f, 0x20, \
-        0xb3, 0x0f, 0x65, 0x6a, 0x8f, 0x55, 0x57, 0x36, 0xee, 0xb2, 0x84, 0x44, \
-        0xfc, 0x91, 0x88, 0xe1, 0xa4, 0xdd, 0x3b, 0x4a, 0x40, 0x4d, 0x7c, 0x86, \
-        0xed, 0xe1, 0xb5, 0x42, 0xef, 0xb9, 0x61, 0xcd, 0x58, 0x19, 0x77, 0x02, \
-        0xae, 0x58, 0x80, 0xdb, 0x13, 0x3d, 0xc7, 0x1f, 0x9d, 0xed, 0xff, 0xac, \
-        0x98, 0xfc, 0xcd, 0xf9, 0x62, 0x04, 0x83, 0x91, 0x89, 0x0d, 0x86, 0x43, \
-        0x8c, 0x0c, 0xc7, 0x1b, 0x90, 0x4d, 0xbe, 0x2f, 0xc5, 0x7c, 0xcd, 0x42, \
-        0xf5, 0xd3, 0xad, 0x8e, 0xfd, 0x9d, 0x02, 0x81, 0x80, 0x17, 0x4b, 0x79, \
-        0x2a, 0x6c, 0x1b, 0x8d, 0x61, 0xc1, 0x85, 0xc5, 0x6a, 0x3b, 0x82, 0x1c, \
-        0x05, 0x5b, 0xcd, 0xdc, 0x12, 0x25, 0x73, 0x5b, 0x9e, 0xd9, 0x84, 0x57, \
-        0x10, 0x39, 0x71, 0x63, 0x96, 0xf4, 0xaf, 0xc3, 0x78, 0x5d, 0xc7, 0x8c, \
-        0x80, 0xa9, 0x96, 0xd7, 0xc3, 0x87, 0x02, 0x96, 0x71, 0x7e, 0x5f, 0x2e, \
-        0x3c, 0x36, 0xae, 0x59, 0x92, 0xd7, 0x3a, 0x09, 0x78, 0xb9, 0xea, 0x6f, \
-        0xc2, 0x16, 0x42, 0xdc, 0x4b, 0x96, 0xad, 0x2c, 0xb2, 0x20, 0x23, 0x61, \
-        0x2d, 0x8d, 0xb5, 0x02, 0x1e, 0xe1, 0x6c, 0x81, 0x01, 0x3c, 0x5d, 0xcb, \
-        0xdd, 0x9b, 0x0e, 0xc0, 0x2f, 0x94, 0x12, 0xb2, 0xfe, 0x75, 0x75, 0x8b, \
-        0x74, 0x1e, 0x7a, 0x26, 0x0c, 0xb7, 0x81, 0x96, 0x81, 0x79, 0x6e, 0xdb, \
-        0xbc, 0x3a, 0xc4, 0x9e, 0x87, 0x09, 0x6e, 0xa0, 0xa6, 0xec, 0x8b, 0xa4, \
-        0x85, 0x71, 0xce, 0x04, 0xaf, 0x02, 0x81, 0x81, 0x00, 0xc2, 0xa7, 0x47, \
-        0x07, 0x48, 0x6a, 0xc8, 0xd4, 0xb3, 0x20, 0xe1, 0x98, 0xee, 0xff, 0x5a, \
-        0x6f, 0x30, 0x7a, 0xa5, 0x47, 0x40, 0xdc, 0x16, 0x62, 0x42, 0xf1, 0x2c, \
-        0xdc, 0xb8, 0xc7, 0x55, 0xde, 0x07, 0x3c, 0x9d, 0xb1, 0xd0, 0xdf, 0x02, \
-        0x82, 0xb0, 0x48, 0x58, 0xe1, 0x34, 0xab, 0xcf, 0xb4, 0x85, 0x23, 0x26, \
-        0x78, 0x4f, 0x7a, 0x59, 0x6f, 0xfb, 0x8c, 0x3d, 0xdf, 0x3d, 0x6c, 0x02, \
-        0x47, 0x9c, 0xe5, 0x5e, 0x49, 0xf1, 0x05, 0x0b, 0x1f, 0xbf, 0x48, 0x0f, \
-        0xdc, 0x10, 0xb9, 0x3d, 0x1d, 0x10, 0x77, 0x2a, 0x73, 0xf9, 0xdf, 0xbd, \
-        0xcd, 0xf3, 0x1f, 0xeb, 0x6e, 0x64, 0xca, 0x2b, 0x78, 0x4f, 0xf8, 0x73, \
-        0xc2, 0x10, 0xef, 0x79, 0x95, 0x33, 0x1e, 0x79, 0x35, 0x09, 0xff, 0x88, \
-        0x1b, 0xb4, 0x3e, 0x4c, 0xe1, 0x27, 0x2e, 0x75, 0x80, 0x58, 0x11, 0x03, \
-        0x21, 0x23, 0x96, 0x9a, 0xb5, 0x02, 0x81, 0x80, 0x05, 0x12, 0x64, 0x71, \
-        0x83, 0x00, 0x1c, 0xfe, 0xef, 0x83, 0xea, 0xdd, 0x2c, 0xc8, 0x2c, 0x00, \
-        0x62, 0x1e, 0x8f, 0x3a, 0xdb, 0x1c, 0xab, 0xd6, 0x34, 0x8b, 0xd1, 0xb2, \
-        0x5a, 0x4f, 0x3d, 0x37, 0x38, 0x02, 0xe0, 0xd7, 0x70, 0xc1, 0xb0, 0x47, \
-        0xe0, 0x08, 0x1a, 0x84, 0xec, 0x48, 0xc5, 0x7c, 0x76, 0x83, 0x12, 0x67, \
-        0xab, 0x7c, 0x9f, 0x90, 0x97, 0xc8, 0x8f, 0x07, 0xf4, 0xb3, 0x60, 0xf2, \
-        0x3f, 0x49, 0x18, 0xdb, 0x2e, 0x94, 0x6b, 0x53, 0x9e, 0xa2, 0x63, 0xde, \
-        0x63, 0xd9, 0xab, 0x21, 0x2e, 0x2d, 0x0a, 0xe0, 0xd0, 0xe8, 0xba, 0xc4, \
-        0x4c, 0x1e, 0xa5, 0xf5, 0x51, 0xa8, 0xc4, 0x92, 0xf8, 0x7f, 0x21, 0xe7, \
-        0x65, 0xbf, 0x0b, 0xe6, 0x01, 0xaf, 0x9c, 0x1d, 0x5b, 0x6c, 0x3f, 0x1c, \
-        0x2f, 0xa6, 0x0f, 0x68, 0x38, 0x8e, 0x85, 0xc4, 0x6c, 0x78, 0x2f, 0x6f, \
-        0x06, 0x21, 0x2e, 0x56                                                  \
-}
-/* END FILE */
-
-/* This is taken from cli2.crt. */
-/* BEGIN FILE string macro TEST_CLI_CRT_EC_PEM cli2.crt */
-#define TEST_CLI_CRT_EC_PEM                                                    \
-    "-----BEGIN CERTIFICATE-----\r\n"                                          \
-    "MIIB3zCCAWOgAwIBAgIBDTAMBggqhkjOPQQDAgUAMD4xCzAJBgNVBAYTAk5MMREw\r\n"     \
-    "DwYDVQQKDAhQb2xhclNTTDEcMBoGA1UEAwwTUG9sYXJTU0wgVGVzdCBFQyBDQTAe\r\n"     \
-    "Fw0xOTAyMTAxNDQ0MDBaFw0yOTAyMTAxNDQ0MDBaMEExCzAJBgNVBAYTAk5MMREw\r\n"     \
-    "DwYDVQQKDAhQb2xhclNTTDEfMB0GA1UEAwwWUG9sYXJTU0wgVGVzdCBDbGllbnQg\r\n"     \
-    "MjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABFflrrFz39Osu5O4gf8Sru7mU6zO\r\n"     \
-    "VVP2NA7MLuNjJQvfmOLzXGA2lsDVGBRw5X+f1UtFGOWwbNVc+JaPh3Cj5MejTTBL\r\n"     \
-    "MAkGA1UdEwQCMAAwHQYDVR0OBBYEFHoAX4Zk/OBd5REQO7LmO8QmP8/iMB8GA1Ud\r\n"     \
-    "IwQYMBaAFJ1tICRJAT8ry3i1Gbx+JMnb+zZ8MAwGCCqGSM49BAMCBQADaAAwZQIx\r\n"     \
-    "AMqme4DKMldUlplDET9Q6Eptre7uUWKhsLOF+zPkKDlfzpIkJYEFgcloDHGYw80u\r\n"     \
-    "IgIwNftyPXsabTqMM7iEHgVpX/GRozKklY9yQI/5eoA6gGW7Y+imuGR/oao5ySOb\r\n"     \
-    "a9Vk\r\n"                                                                 \
-    "-----END CERTIFICATE-----\r\n"
-/* END FILE */
-
-/* This is generated from cli2.crt.der. */
-/* BEGIN FILE binary macro TEST_CLI_CRT_EC_DER cli2.crt.der */
-#define TEST_CLI_CRT_EC_DER {                                                   \
-        0x30, 0x82, 0x01, 0xdf, 0x30, 0x82, 0x01, 0x63, 0xa0, 0x03, 0x02, 0x01, \
-        0x02, 0x02, 0x01, 0x0d, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, \
-        0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, \
-        0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \
-        0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \
-        0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, \
-        0x03, 0x0c, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, \
-        0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, \
-        0x17, 0x0d, 0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, \
-        0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, \
-        0x34, 0x34, 0x34, 0x30, 0x30, 0x5a, 0x30, 0x41, 0x31, 0x0b, 0x30, 0x09, \
-        0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, \
-        0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, \
-        0x72, 0x53, 0x53, 0x4c, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, \
-        0x03, 0x0c, 0x16, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, \
-        0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, \
-        0x32, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, \
-        0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, \
-        0x03, 0x42, 0x00, 0x04, 0x57, 0xe5, 0xae, 0xb1, 0x73, 0xdf, 0xd3, 0xac, \
-        0xbb, 0x93, 0xb8, 0x81, 0xff, 0x12, 0xae, 0xee, 0xe6, 0x53, 0xac, 0xce, \
-        0x55, 0x53, 0xf6, 0x34, 0x0e, 0xcc, 0x2e, 0xe3, 0x63, 0x25, 0x0b, 0xdf, \
-        0x98, 0xe2, 0xf3, 0x5c, 0x60, 0x36, 0x96, 0xc0, 0xd5, 0x18, 0x14, 0x70, \
-        0xe5, 0x7f, 0x9f, 0xd5, 0x4b, 0x45, 0x18, 0xe5, 0xb0, 0x6c, 0xd5, 0x5c, \
-        0xf8, 0x96, 0x8f, 0x87, 0x70, 0xa3, 0xe4, 0xc7, 0xa3, 0x4d, 0x30, 0x4b, \
-        0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, \
-        0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x7a, 0x00, \
-        0x5f, 0x86, 0x64, 0xfc, 0xe0, 0x5d, 0xe5, 0x11, 0x10, 0x3b, 0xb2, 0xe6, \
-        0x3b, 0xc4, 0x26, 0x3f, 0xcf, 0xe2, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, \
-        0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, \
-        0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, \
-        0xfb, 0x36, 0x7c, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \
-        0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x31, \
-        0x00, 0xca, 0xa6, 0x7b, 0x80, 0xca, 0x32, 0x57, 0x54, 0x96, 0x99, 0x43, \
-        0x11, 0x3f, 0x50, 0xe8, 0x4a, 0x6d, 0xad, 0xee, 0xee, 0x51, 0x62, 0xa1, \
-        0xb0, 0xb3, 0x85, 0xfb, 0x33, 0xe4, 0x28, 0x39, 0x5f, 0xce, 0x92, 0x24, \
-        0x25, 0x81, 0x05, 0x81, 0xc9, 0x68, 0x0c, 0x71, 0x98, 0xc3, 0xcd, 0x2e, \
-        0x22, 0x02, 0x30, 0x35, 0xfb, 0x72, 0x3d, 0x7b, 0x1a, 0x6d, 0x3a, 0x8c, \
-        0x33, 0xb8, 0x84, 0x1e, 0x05, 0x69, 0x5f, 0xf1, 0x91, 0xa3, 0x32, 0xa4, \
-        0x95, 0x8f, 0x72, 0x40, 0x8f, 0xf9, 0x7a, 0x80, 0x3a, 0x80, 0x65, 0xbb, \
-        0x63, 0xe8, 0xa6, 0xb8, 0x64, 0x7f, 0xa1, 0xaa, 0x39, 0xc9, 0x23, 0x9b, \
-        0x6b, 0xd5, 0x64                                                        \
-}
-/* END FILE */
-
-/* This is taken from cli2.key. */
-/* BEGIN FILE string macro TEST_CLI_KEY_EC_PEM cli2.key */
-#define TEST_CLI_KEY_EC_PEM                                                    \
-    "-----BEGIN EC PRIVATE KEY-----\r\n"                                       \
-    "MHcCAQEEIPb3hmTxZ3/mZI3vyk7p3U3wBf+WIop6hDhkFzJhmLcqoAoGCCqGSM49\r\n"     \
-    "AwEHoUQDQgAEV+WusXPf06y7k7iB/xKu7uZTrM5VU/Y0Dswu42MlC9+Y4vNcYDaW\r\n"     \
-    "wNUYFHDlf5/VS0UY5bBs1Vz4lo+HcKPkxw==\r\n"                                 \
-    "-----END EC PRIVATE KEY-----\r\n"
-/* END FILE */
-
-/* This is generated from cli2.key.der. */
-/* BEGIN FILE binary macro TEST_CLI_KEY_EC_DER cli2.key.der */
-#define TEST_CLI_KEY_EC_DER {                                                   \
-        0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xf6, 0xf7, 0x86, 0x64, 0xf1, \
-        0x67, 0x7f, 0xe6, 0x64, 0x8d, 0xef, 0xca, 0x4e, 0xe9, 0xdd, 0x4d, 0xf0, \
-        0x05, 0xff, 0x96, 0x22, 0x8a, 0x7a, 0x84, 0x38, 0x64, 0x17, 0x32, 0x61, \
-        0x98, 0xb7, 0x2a, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, \
-        0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x57, 0xe5, 0xae, \
-        0xb1, 0x73, 0xdf, 0xd3, 0xac, 0xbb, 0x93, 0xb8, 0x81, 0xff, 0x12, 0xae, \
-        0xee, 0xe6, 0x53, 0xac, 0xce, 0x55, 0x53, 0xf6, 0x34, 0x0e, 0xcc, 0x2e, \
-        0xe3, 0x63, 0x25, 0x0b, 0xdf, 0x98, 0xe2, 0xf3, 0x5c, 0x60, 0x36, 0x96, \
-        0xc0, 0xd5, 0x18, 0x14, 0x70, 0xe5, 0x7f, 0x9f, 0xd5, 0x4b, 0x45, 0x18, \
-        0xe5, 0xb0, 0x6c, 0xd5, 0x5c, 0xf8, 0x96, 0x8f, 0x87, 0x70, 0xa3, 0xe4, \
-        0xc7                                                                    \
-}
-/* END FILE */
-
-/* This is taken from cli-rsa-sha256.crt. */
-/* BEGIN FILE string macro TEST_CLI_CRT_RSA_PEM cli-rsa-sha256.crt */
-#define TEST_CLI_CRT_RSA_PEM                                                   \
-    "-----BEGIN CERTIFICATE-----\r\n"                                          \
-    "MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n"     \
-    "MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"     \
-    "MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n"     \
-    "A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n"     \
-    "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n"     \
-    "M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n"     \
-    "1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n"     \
-    "MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n"     \
-    "4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n"     \
-    "/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n"     \
-    "o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITAf\r\n"     \
-    "BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQsFAAOC\r\n"     \
-    "AQEAXidv1d4pLlBiKWED95rMycBdgDcgyNqJxakFkRfRyA2y1mlyTn7uBXRkNLY5\r\n"     \
-    "ZFzK82GCjk2Q2OD4RZSCPAJJqLpHHU34t71ciffvy2KK81YvrxczRhMAE64i+qna\r\n"     \
-    "yP3Td2XuWJR05PVPoSemsNELs9gWttdnYy3ce+EY2Y0n7Rsi7982EeLIAA7H6ca4\r\n"     \
-    "2Es/NUH//JZJT32OP0doMxeDRA+vplkKqTLLWf7dX26LIriBkBaRCgR5Yv9LBPFc\r\n"     \
-    "NOtpzu/LbrY7QFXKJMI+JXDudCsOn8KCmiA4d6Emisqfh3V3485l7HEQNcvLTxlD\r\n"     \
-    "6zDQyi0/ykYUYZkwQTK1N2Nvlw==\r\n"                                         \
-    "-----END CERTIFICATE-----\r\n"
-/* END FILE */
-
-/* This is generated from cli-rsa-sha256.crt.der. */
-/* BEGIN FILE binary macro TEST_CLI_CRT_RSA_DER cli-rsa-sha256.crt.der */
-#define TEST_CLI_CRT_RSA_DER {                                                  \
-        0x30, 0x82, 0x03, 0x3f, 0x30, 0x82, 0x02, 0x27, 0xa0, 0x03, 0x02, 0x01, \
-        0x02, 0x02, 0x01, 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, \
-        0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3b, 0x31, 0x0b, 0x30, \
-        0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, \
-        0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, \
-        0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, \
-        0x04, 0x03, 0x0c, 0x10, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, \
-        0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, \
-        0x31, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, 0x34, 0x30, 0x36, \
-        0x5a, 0x17, 0x0d, 0x32, 0x39, 0x30, 0x32, 0x31, 0x30, 0x31, 0x34, 0x34, \
-        0x34, 0x30, 0x36, 0x5a, 0x30, 0x3c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, \
-        0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, \
-        0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, \
-        0x53, 0x4c, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, \
-        0x11, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x20, 0x43, 0x6c, \
-        0x69, 0x65, 0x6e, 0x74, 0x20, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, \
-        0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, \
-        0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, \
-        0x01, 0x01, 0x00, 0xc8, 0x74, 0xc4, 0xcc, 0xb9, 0xf9, 0xb5, 0x79, 0xe9, \
-        0x45, 0xd9, 0x14, 0x60, 0xb0, 0x7d, 0xbb, 0x93, 0xf2, 0x6b, 0x1e, 0x9f, \
-        0x33, 0xad, 0x0d, 0x8f, 0x8a, 0x3c, 0x56, 0x65, 0xe5, 0xdc, 0x44, 0xd9, \
-        0xcc, 0x66, 0x85, 0x07, 0xd5, 0xf8, 0x27, 0xb0, 0x4a, 0x35, 0xd0, 0x63, \
-        0x9e, 0x0a, 0x6e, 0x1b, 0xb7, 0xda, 0xf0, 0x7e, 0xab, 0xee, 0x0c, 0x10, \
-        0x93, 0x86, 0x49, 0x18, 0x34, 0xf3, 0xa8, 0x2a, 0xd2, 0x57, 0xf5, 0x2e, \
-        0xd4, 0x2f, 0x77, 0x29, 0x84, 0x61, 0x4d, 0x82, 0x50, 0x8f, 0xa7, 0x95, \
-        0x48, 0x70, 0xf5, 0x6e, 0x4d, 0xb2, 0xd5, 0x13, 0xc3, 0xd2, 0x1a, 0xed, \
-        0xe6, 0x43, 0xea, 0x42, 0x14, 0xeb, 0x74, 0xea, 0xc0, 0xed, 0x1f, 0xd4, \
-        0x57, 0x4e, 0xa9, 0xf3, 0xa8, 0xed, 0xd2, 0xe0, 0xc1, 0x30, 0x71, 0x30, \
-        0x32, 0x30, 0xd5, 0xd3, 0xf6, 0x08, 0xd0, 0x56, 0x4f, 0x46, 0x8e, 0xf2, \
-        0x5f, 0xf9, 0x3d, 0x67, 0x91, 0x88, 0x30, 0x2e, 0x42, 0xb2, 0xdf, 0x7d, \
-        0xfb, 0xe5, 0x0c, 0x77, 0xff, 0xec, 0x31, 0xc0, 0x78, 0x8f, 0xbf, 0xc2, \
-        0x7f, 0xca, 0xad, 0x6c, 0x21, 0xd6, 0x8d, 0xd9, 0x8b, 0x6a, 0x8e, 0x6f, \
-        0xe0, 0x9b, 0xf8, 0x10, 0x56, 0xcc, 0xb3, 0x8e, 0x13, 0x15, 0xe6, 0x34, \
-        0x04, 0x66, 0xc7, 0xee, 0xf9, 0x36, 0x0e, 0x6a, 0x95, 0xf6, 0x09, 0x9a, \
-        0x06, 0x67, 0xf4, 0x65, 0x71, 0xf8, 0xca, 0xa4, 0xb1, 0x25, 0xe0, 0xfe, \
-        0x3c, 0x8b, 0x35, 0x04, 0x67, 0xba, 0xe0, 0x4f, 0x76, 0x85, 0xfc, 0x7f, \
-        0xfc, 0x36, 0x6b, 0xb5, 0xe9, 0xcd, 0x2d, 0x03, 0x62, 0x4e, 0xb3, 0x3d, \
-        0x00, 0xcf, 0xaf, 0x76, 0xa0, 0x69, 0x56, 0x83, 0x6a, 0xd2, 0xa8, 0xd4, \
-        0xe7, 0x50, 0x71, 0xe6, 0xb5, 0x36, 0x05, 0x77, 0x05, 0x6d, 0x7b, 0xc8, \
-        0xe4, 0xc4, 0xfd, 0x4c, 0xd5, 0x21, 0x5f, 0x02, 0x03, 0x01, 0x00, 0x01, \
-        0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, \
-        0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, \
-        0x04, 0x14, 0x71, 0xa1, 0x00, 0x73, 0x72, 0x40, 0x2f, 0x54, 0x76, 0x5e, \
-        0x33, 0xfc, 0x52, 0x8f, 0xbc, 0xf1, 0xdd, 0x6b, 0x46, 0x21, 0x30, 0x1f, \
-        0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xb4, \
-        0x5a, 0xe4, 0xa5, 0xb3, 0xde, 0xd2, 0x52, 0xf6, 0xb9, 0xd5, 0xa6, 0x95, \
-        0x0f, 0xeb, 0x3e, 0xbc, 0xc7, 0xfd, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, \
-        0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, \
-        0x01, 0x01, 0x00, 0x5e, 0x27, 0x6f, 0xd5, 0xde, 0x29, 0x2e, 0x50, 0x62, \
-        0x29, 0x61, 0x03, 0xf7, 0x9a, 0xcc, 0xc9, 0xc0, 0x5d, 0x80, 0x37, 0x20, \
-        0xc8, 0xda, 0x89, 0xc5, 0xa9, 0x05, 0x91, 0x17, 0xd1, 0xc8, 0x0d, 0xb2, \
-        0xd6, 0x69, 0x72, 0x4e, 0x7e, 0xee, 0x05, 0x74, 0x64, 0x34, 0xb6, 0x39, \
-        0x64, 0x5c, 0xca, 0xf3, 0x61, 0x82, 0x8e, 0x4d, 0x90, 0xd8, 0xe0, 0xf8, \
-        0x45, 0x94, 0x82, 0x3c, 0x02, 0x49, 0xa8, 0xba, 0x47, 0x1d, 0x4d, 0xf8, \
-        0xb7, 0xbd, 0x5c, 0x89, 0xf7, 0xef, 0xcb, 0x62, 0x8a, 0xf3, 0x56, 0x2f, \
-        0xaf, 0x17, 0x33, 0x46, 0x13, 0x00, 0x13, 0xae, 0x22, 0xfa, 0xa9, 0xda, \
-        0xc8, 0xfd, 0xd3, 0x77, 0x65, 0xee, 0x58, 0x94, 0x74, 0xe4, 0xf5, 0x4f, \
-        0xa1, 0x27, 0xa6, 0xb0, 0xd1, 0x0b, 0xb3, 0xd8, 0x16, 0xb6, 0xd7, 0x67, \
-        0x63, 0x2d, 0xdc, 0x7b, 0xe1, 0x18, 0xd9, 0x8d, 0x27, 0xed, 0x1b, 0x22, \
-        0xef, 0xdf, 0x36, 0x11, 0xe2, 0xc8, 0x00, 0x0e, 0xc7, 0xe9, 0xc6, 0xb8, \
-        0xd8, 0x4b, 0x3f, 0x35, 0x41, 0xff, 0xfc, 0x96, 0x49, 0x4f, 0x7d, 0x8e, \
-        0x3f, 0x47, 0x68, 0x33, 0x17, 0x83, 0x44, 0x0f, 0xaf, 0xa6, 0x59, 0x0a, \
-        0xa9, 0x32, 0xcb, 0x59, 0xfe, 0xdd, 0x5f, 0x6e, 0x8b, 0x22, 0xb8, 0x81, \
-        0x90, 0x16, 0x91, 0x0a, 0x04, 0x79, 0x62, 0xff, 0x4b, 0x04, 0xf1, 0x5c, \
-        0x34, 0xeb, 0x69, 0xce, 0xef, 0xcb, 0x6e, 0xb6, 0x3b, 0x40, 0x55, 0xca, \
-        0x24, 0xc2, 0x3e, 0x25, 0x70, 0xee, 0x74, 0x2b, 0x0e, 0x9f, 0xc2, 0x82, \
-        0x9a, 0x20, 0x38, 0x77, 0xa1, 0x26, 0x8a, 0xca, 0x9f, 0x87, 0x75, 0x77, \
-        0xe3, 0xce, 0x65, 0xec, 0x71, 0x10, 0x35, 0xcb, 0xcb, 0x4f, 0x19, 0x43, \
-        0xeb, 0x30, 0xd0, 0xca, 0x2d, 0x3f, 0xca, 0x46, 0x14, 0x61, 0x99, 0x30, \
-        0x41, 0x32, 0xb5, 0x37, 0x63, 0x6f, 0x97                                \
-}
-/* END FILE */
-
-/* This is taken from cli-rsa.key. */
-/* BEGIN FILE string macro TEST_CLI_KEY_RSA_PEM cli-rsa.key */
-#define TEST_CLI_KEY_RSA_PEM                                                   \
-    "-----BEGIN RSA PRIVATE KEY-----\r\n"                                      \
-    "MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n"     \
-    "B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n"     \
-    "bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n"     \
-    "Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n"     \
-    "7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n"     \
-    "dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n"     \
-    "yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n"     \
-    "4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n"     \
-    "ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n"     \
-    "zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n"     \
-    "l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n"     \
-    "DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n"     \
-    "VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n"     \
-    "Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n"     \
-    "wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n"     \
-    "c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n"     \
-    "33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n"     \
-    "ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n"     \
-    "BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n"     \
-    "KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n"     \
-    "UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n"     \
-    "7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n"     \
-    "gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n"     \
-    "bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n"     \
-    "8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n"             \
-    "-----END RSA PRIVATE KEY-----\r\n"
-/* END FILE */
-
-/* This is generated from cli-rsa.key.der. */
-/* BEGIN FILE binary macro TEST_CLI_KEY_RSA_DER cli-rsa.key.der */
-#define TEST_CLI_KEY_RSA_DER {                                                  \
-        0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, \
-        0xc8, 0x74, 0xc4, 0xcc, 0xb9, 0xf9, 0xb5, 0x79, 0xe9, 0x45, 0xd9, 0x14, \
-        0x60, 0xb0, 0x7d, 0xbb, 0x93, 0xf2, 0x6b, 0x1e, 0x9f, 0x33, 0xad, 0x0d, \
-        0x8f, 0x8a, 0x3c, 0x56, 0x65, 0xe5, 0xdc, 0x44, 0xd9, 0xcc, 0x66, 0x85, \
-        0x07, 0xd5, 0xf8, 0x27, 0xb0, 0x4a, 0x35, 0xd0, 0x63, 0x9e, 0x0a, 0x6e, \
-        0x1b, 0xb7, 0xda, 0xf0, 0x7e, 0xab, 0xee, 0x0c, 0x10, 0x93, 0x86, 0x49, \
-        0x18, 0x34, 0xf3, 0xa8, 0x2a, 0xd2, 0x57, 0xf5, 0x2e, 0xd4, 0x2f, 0x77, \
-        0x29, 0x84, 0x61, 0x4d, 0x82, 0x50, 0x8f, 0xa7, 0x95, 0x48, 0x70, 0xf5, \
-        0x6e, 0x4d, 0xb2, 0xd5, 0x13, 0xc3, 0xd2, 0x1a, 0xed, 0xe6, 0x43, 0xea, \
-        0x42, 0x14, 0xeb, 0x74, 0xea, 0xc0, 0xed, 0x1f, 0xd4, 0x57, 0x4e, 0xa9, \
-        0xf3, 0xa8, 0xed, 0xd2, 0xe0, 0xc1, 0x30, 0x71, 0x30, 0x32, 0x30, 0xd5, \
-        0xd3, 0xf6, 0x08, 0xd0, 0x56, 0x4f, 0x46, 0x8e, 0xf2, 0x5f, 0xf9, 0x3d, \
-        0x67, 0x91, 0x88, 0x30, 0x2e, 0x42, 0xb2, 0xdf, 0x7d, 0xfb, 0xe5, 0x0c, \
-        0x77, 0xff, 0xec, 0x31, 0xc0, 0x78, 0x8f, 0xbf, 0xc2, 0x7f, 0xca, 0xad, \
-        0x6c, 0x21, 0xd6, 0x8d, 0xd9, 0x8b, 0x6a, 0x8e, 0x6f, 0xe0, 0x9b, 0xf8, \
-        0x10, 0x56, 0xcc, 0xb3, 0x8e, 0x13, 0x15, 0xe6, 0x34, 0x04, 0x66, 0xc7, \
-        0xee, 0xf9, 0x36, 0x0e, 0x6a, 0x95, 0xf6, 0x09, 0x9a, 0x06, 0x67, 0xf4, \
-        0x65, 0x71, 0xf8, 0xca, 0xa4, 0xb1, 0x25, 0xe0, 0xfe, 0x3c, 0x8b, 0x35, \
-        0x04, 0x67, 0xba, 0xe0, 0x4f, 0x76, 0x85, 0xfc, 0x7f, 0xfc, 0x36, 0x6b, \
-        0xb5, 0xe9, 0xcd, 0x2d, 0x03, 0x62, 0x4e, 0xb3, 0x3d, 0x00, 0xcf, 0xaf, \
-        0x76, 0xa0, 0x69, 0x56, 0x83, 0x6a, 0xd2, 0xa8, 0xd4, 0xe7, 0x50, 0x71, \
-        0xe6, 0xb5, 0x36, 0x05, 0x77, 0x05, 0x6d, 0x7b, 0xc8, 0xe4, 0xc4, 0xfd, \
-        0x4c, 0xd5, 0x21, 0x5f, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, \
-        0x00, 0x67, 0x4d, 0xb5, 0xf6, 0x03, 0x89, 0xaa, 0x7a, 0x6f, 0x3b, 0x2d, \
-        0xca, 0x10, 0xa2, 0x23, 0xc9, 0xbd, 0x4e, 0xda, 0xe1, 0x67, 0x0e, 0x0c, \
-        0x8a, 0xc6, 0x84, 0x68, 0xdf, 0xe5, 0x97, 0x75, 0xd2, 0x8d, 0xa3, 0x86, \
-        0xd9, 0xdb, 0xd5, 0xeb, 0x13, 0x19, 0x08, 0xc5, 0x7e, 0xe5, 0x37, 0x97, \
-        0x0c, 0x73, 0x80, 0x66, 0x76, 0x35, 0xf1, 0x88, 0xb5, 0xf2, 0xfc, 0xf3, \
-        0xe1, 0x4b, 0x76, 0x4e, 0x73, 0x45, 0xce, 0x2c, 0xc2, 0x10, 0x26, 0x0d, \
-        0x68, 0x0d, 0x9f, 0x49, 0x3d, 0xd6, 0x80, 0x89, 0xe7, 0xc5, 0x49, 0x15, \
-        0xdd, 0x85, 0xc0, 0xc8, 0xfe, 0x82, 0x37, 0x12, 0x5a, 0x0a, 0x6b, 0xf6, \
-        0x68, 0x0d, 0x32, 0x16, 0xbd, 0xa4, 0x15, 0x54, 0x9e, 0x68, 0xa1, 0xad, \
-        0xca, 0x6b, 0xe5, 0x8c, 0xda, 0x76, 0x35, 0x59, 0x2f, 0x9b, 0xb4, 0xe1, \
-        0xf1, 0xf0, 0x50, 0x04, 0xee, 0xc8, 0xec, 0x05, 0xe1, 0xcf, 0x8d, 0xe4, \
-        0xd2, 0x64, 0x7b, 0x5e, 0x63, 0xe0, 0x7b, 0x07, 0xbc, 0x02, 0x96, 0x4e, \
-        0x1b, 0x78, 0x6c, 0xb6, 0x43, 0x9a, 0x32, 0xf6, 0xd6, 0x02, 0xf5, 0x80, \
-        0xcc, 0x26, 0x6e, 0xa5, 0xd0, 0xe3, 0x65, 0x88, 0xce, 0x26, 0xa9, 0x40, \
-        0xe1, 0xe1, 0x00, 0xe0, 0x7f, 0x3f, 0xc3, 0xb1, 0x7c, 0xde, 0xbe, 0x42, \
-        0xba, 0x07, 0x81, 0x13, 0xc2, 0xe0, 0x11, 0x11, 0x23, 0x2c, 0xf8, 0xb2, \
-        0x7a, 0x3a, 0xd4, 0xe4, 0x7d, 0x5f, 0xb9, 0xb1, 0x18, 0xfa, 0x1d, 0x1d, \
-        0x97, 0x91, 0xd9, 0x04, 0x9e, 0xbc, 0xc9, 0xb4, 0xd7, 0x7d, 0x0e, 0x54, \
-        0xf6, 0x8f, 0xd0, 0x28, 0x0d, 0xdd, 0x77, 0x4b, 0x68, 0x04, 0x48, 0x61, \
-        0x75, 0x15, 0x03, 0x1b, 0x35, 0xad, 0x8e, 0xfc, 0x24, 0x11, 0x07, 0xea, \
-        0x17, 0x5a, 0xde, 0x19, 0x68, 0xff, 0xb6, 0x87, 0x7f, 0x80, 0x2a, 0x5f, \
-        0x0c, 0x58, 0xba, 0x5f, 0x41, 0x02, 0x81, 0x81, 0x00, 0xe3, 0x03, 0xaf, \
-        0xfe, 0x98, 0xd2, 0x0b, 0x7b, 0x72, 0xe9, 0x3b, 0x8e, 0xbc, 0xa5, 0xf6, \
-        0xac, 0xe5, 0x22, 0x06, 0xb2, 0xd7, 0x5e, 0xfd, 0x89, 0x4b, 0x16, 0x67, \
-        0x32, 0x83, 0x22, 0x58, 0x8e, 0x62, 0xa4, 0xb4, 0x2d, 0xf9, 0x16, 0x13, \
-        0x54, 0xf6, 0x9f, 0x2f, 0xf9, 0xbb, 0x0e, 0x7e, 0x8c, 0x6f, 0x08, 0xda, \
-        0xc8, 0xe9, 0x1c, 0x66, 0x10, 0x70, 0x93, 0x90, 0x8d, 0xcf, 0x90, 0x3a, \
-        0x43, 0x89, 0x49, 0xeb, 0x83, 0x2a, 0xfe, 0x5a, 0x87, 0xce, 0x74, 0x42, \
-        0x41, 0x0d, 0x8c, 0x73, 0x51, 0xbc, 0x7b, 0x20, 0xc5, 0xfd, 0xf6, 0x0b, \
-        0x65, 0xed, 0xa9, 0x2e, 0xfc, 0x0f, 0xf5, 0x50, 0xf9, 0x8d, 0x37, 0x36, \
-        0x9a, 0x20, 0xdf, 0xc3, 0xe3, 0x27, 0xbc, 0x98, 0x72, 0xc1, 0x14, 0x4b, \
-        0x71, 0xe9, 0x83, 0x14, 0xff, 0x24, 0xe2, 0x14, 0x15, 0xb6, 0x6f, 0x0f, \
-        0x32, 0x9d, 0xd9, 0x98, 0xd1, 0x02, 0x81, 0x81, 0x00, 0xe2, 0x0c, 0xfb, \
-        0xc3, 0x33, 0x9b, 0x47, 0x88, 0x27, 0xf2, 0x26, 0xde, 0xeb, 0x5e, 0xee, \
-        0x40, 0xf6, 0x63, 0x5b, 0x35, 0x23, 0xf5, 0xd5, 0x07, 0x61, 0xdf, 0xa2, \
-        0x9f, 0x58, 0x30, 0x04, 0x22, 0x2b, 0xb4, 0xd9, 0xda, 0x46, 0x7f, 0x48, \
-        0xf5, 0x4f, 0xd0, 0xea, 0xd7, 0xa0, 0x45, 0x8a, 0x62, 0x8b, 0x8c, 0xac, \
-        0x73, 0x5e, 0xfa, 0x36, 0x65, 0x3e, 0xba, 0x6c, 0xba, 0x5e, 0x6b, 0x92, \
-        0x29, 0x5e, 0x6a, 0x0f, 0xd6, 0xd2, 0xa5, 0x95, 0x86, 0xda, 0x72, 0xc5, \
-        0x9e, 0xc9, 0x6b, 0x37, 0x5e, 0x4b, 0x9b, 0x77, 0xe1, 0x67, 0x1a, 0x1e, \
-        0x30, 0xd8, 0x41, 0x68, 0x40, 0xd3, 0x9c, 0xb4, 0xf6, 0xeb, 0x2a, 0x22, \
-        0xdf, 0x78, 0x29, 0xd2, 0x64, 0x92, 0x5b, 0x2f, 0x78, 0x64, 0x4a, 0xa2, \
-        0xa6, 0x6b, 0x3e, 0x50, 0xb1, 0x7a, 0xb1, 0x8d, 0x59, 0xb4, 0x55, 0xba, \
-        0xb6, 0x91, 0x85, 0xa3, 0x2f, 0x02, 0x81, 0x80, 0x10, 0x1e, 0x19, 0xe7, \
-        0xbc, 0x97, 0xe5, 0x22, 0xcd, 0xa4, 0xcb, 0x8a, 0xb5, 0xd0, 0x1e, 0xb4, \
-        0x65, 0xcc, 0x45, 0xa7, 0x7a, 0xed, 0x0e, 0x99, 0x29, 0xd0, 0x9c, 0x61, \
-        0x14, 0xb8, 0x62, 0x8b, 0x31, 0x6b, 0xba, 0x33, 0x2d, 0x65, 0x28, 0xd8, \
-        0x36, 0x6e, 0x54, 0xec, 0xa9, 0x20, 0x3d, 0x51, 0xe1, 0x2c, 0x42, 0xc4, \
-        0x52, 0xf0, 0xa6, 0x3a, 0x72, 0x93, 0xb7, 0x86, 0xa9, 0xfe, 0xf6, 0x74, \
-        0x07, 0x12, 0x4d, 0x7b, 0x51, 0x99, 0x1f, 0x7a, 0x56, 0xe9, 0x20, 0x2f, \
-        0x18, 0x34, 0x29, 0x97, 0xdb, 0x06, 0xee, 0xeb, 0xbf, 0xbd, 0x31, 0x4f, \
-        0xfa, 0x50, 0xb1, 0xba, 0x49, 0xb3, 0xc4, 0x1d, 0x03, 0xae, 0xb0, 0xdc, \
-        0xbe, 0x8a, 0xc4, 0x90, 0xa3, 0x28, 0x9b, 0xb6, 0x42, 0x09, 0x1b, 0xd6, \
-        0x29, 0x9b, 0x19, 0xe9, 0x87, 0x87, 0xd9, 0x9f, 0x35, 0x05, 0xab, 0x91, \
-        0x8f, 0x6d, 0x7c, 0x91, 0x02, 0x81, 0x81, 0x00, 0x94, 0x57, 0xf0, 0xe0, \
-        0x28, 0xfd, 0xbd, 0xf3, 0x9c, 0x43, 0x4d, 0x3e, 0xfd, 0x37, 0x4f, 0x23, \
-        0x52, 0x8d, 0xe1, 0x4c, 0xfe, 0x4c, 0x55, 0x80, 0x82, 0xba, 0x3f, 0xfe, \
-        0x51, 0xe1, 0x30, 0xd5, 0x3b, 0xd9, 0x73, 0x1d, 0xcb, 0x25, 0xbc, 0xbb, \
-        0x3f, 0xa5, 0xda, 0x77, 0xa6, 0xb5, 0xfc, 0x1a, 0xaf, 0x79, 0xa1, 0xb2, \
-        0x14, 0xa2, 0x1f, 0x10, 0x52, 0x1a, 0x05, 0x40, 0x48, 0xb6, 0x4f, 0x34, \
-        0xd6, 0xc0, 0xc3, 0xa4, 0x36, 0x98, 0x73, 0x88, 0x0b, 0xd3, 0x45, 0xdc, \
-        0xee, 0x51, 0x6e, 0x04, 0x73, 0x99, 0x93, 0x12, 0x58, 0x96, 0xcb, 0x39, \
-        0x42, 0xb1, 0xa9, 0xb8, 0xe1, 0x25, 0xf5, 0x9c, 0x14, 0xb7, 0x92, 0x2b, \
-        0x14, 0xb0, 0x5d, 0x61, 0xa2, 0xaa, 0x34, 0x7c, 0xcd, 0x54, 0x2d, 0x69, \
-        0x08, 0xf7, 0xdb, 0xfc, 0x9c, 0x87, 0xe8, 0x3a, 0xf6, 0x1d, 0x4c, 0x6a, \
-        0x83, 0x15, 0x30, 0x01, 0x02, 0x81, 0x81, 0x00, 0x9c, 0x53, 0xa1, 0xb6, \
-        0x2f, 0xc0, 0x06, 0xf5, 0xdf, 0x5c, 0xd1, 0x4a, 0x4e, 0xc8, 0xbd, 0x6d, \
-        0x32, 0xf1, 0x5e, 0xe5, 0x3b, 0x70, 0xd0, 0xa8, 0xe5, 0x41, 0x57, 0x6c, \
-        0x87, 0x53, 0x0f, 0xeb, 0x28, 0xa0, 0x62, 0x8f, 0x43, 0x62, 0xec, 0x2e, \
-        0x6c, 0x71, 0x55, 0x5b, 0x6a, 0xf4, 0x74, 0x14, 0xea, 0x7a, 0x03, 0xf6, \
-        0xfc, 0xa4, 0xce, 0xc4, 0xac, 0xda, 0x1d, 0xf0, 0xb5, 0xa9, 0xfd, 0x11, \
-        0x18, 0x3b, 0x14, 0xa0, 0x90, 0x8d, 0x26, 0xb7, 0x75, 0x73, 0x0a, 0x02, \
-        0x2c, 0x6f, 0x0f, 0xd8, 0x41, 0x78, 0xc3, 0x73, 0x81, 0xac, 0xaa, 0xaf, \
-        0xf2, 0xee, 0x32, 0xb5, 0x8d, 0x05, 0xf9, 0x59, 0x5a, 0x9e, 0x3e, 0x65, \
-        0x9b, 0x74, 0xda, 0xa0, 0x74, 0x95, 0x17, 0x5f, 0x8d, 0x58, 0xfc, 0x8e, \
-        0x4e, 0x2c, 0x1e, 0xbc, 0x81, 0x02, 0x18, 0xac, 0x12, 0xc6, 0xf9, 0x64, \
-        0x8b, 0x87, 0xc3, 0x00                                                  \
-}
-/* END FILE */
-
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 3549a7b..f4c7f6d 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -70,6 +70,32 @@
 
 # alternative versions of OpenSSL and GnuTLS (no default path)
 
+# If $OPENSSL is at least 1.1.1, use it as OPENSSL_NEXT as well.
+if [ -z "${OPENSSL_NEXT:-}" ]; then
+    case $($OPENSSL version) in
+        OpenSSL\ 1.1.[1-9]*) OPENSSL_NEXT=$OPENSSL;;
+        OpenSSL\ [3-9]*) OPENSSL_NEXT=$OPENSSL;;
+    esac
+fi
+
+# If $GNUTLS_CLI is at least 3.7, use it as GNUTLS_NEXT_CLI as well.
+if [ -z "${GNUTLS_NEXT_CLI:-}" ]; then
+    case $($GNUTLS_CLI --version) in
+        gnutls-cli\ 3.[1-9][0-9]*) GNUTLS_NEXT_CLI=$GNUTLS_CLI;;
+        gnutls-cli\ 3.[7-9].*) GNUTLS_NEXT_CLI=$GNUTLS_CLI;;
+        gnutls-cli\ [4-9]*) GNUTLS_NEXT_CLI=$GNUTLS_CLI;;
+    esac
+fi
+
+# If $GNUTLS_SERV is at least 3.7, use it as GNUTLS_NEXT_SERV as well.
+if [ -z "${GNUTLS_NEXT_SERV:-}" ]; then
+    case $($GNUTLS_SERV --version) in
+        gnutls-cli\ 3.[1-9][0-9]*) GNUTLS_NEXT_SERV=$GNUTLS_SERV;;
+        gnutls-cli\ 3.[7-9].*) GNUTLS_NEXT_SERV=$GNUTLS_SERV;;
+        gnutls-cli\ [4-9]*) GNUTLS_NEXT_SERV=$GNUTLS_SERV;;
+    esac
+fi
+
 if [ -n "${OPENSSL_NEXT:-}" ]; then
     O_NEXT_SRV="$OPENSSL_NEXT s_server -www -cert data_files/server5.crt -key data_files/server5.key"
     O_NEXT_SRV_EARLY_DATA="$OPENSSL_NEXT s_server -early_data -cert data_files/server5.crt -key data_files/server5.key"
@@ -443,9 +469,9 @@
     esac
 
     case "$CMD_LINE" in
-        *server5*|\
-        *server7*|\
-        *dir-maxpath*)
+        */server5*|\
+        */server7*|\
+        */dir-maxpath*)
             if [ "$TLS_VERSION" = "TLS13" ]; then
                 # In case of TLS13 the support for ECDSA is enough
                 requires_pk_alg "ECDSA"
@@ -477,9 +503,15 @@
     esac
 
     case "$CMD_LINE" in
-        *server2*|\
-        *server7*)
-            # server2 and server7 certificates use RSA encryption
+        */server1*|\
+        */server2*|\
+        */server7*)
+            # Certificates with an RSA key. The algorithm requirement is
+            # some subset of {PKCS#1v1.5 encryption, PKCS#1v1.5 signature,
+            # PSS signature}. We can't easily tell which subset works, and
+            # we aren't currently running ssl-opt.sh in configurations
+            # where partial RSA support is a problem, so generically, we
+            # just require RSA and it works out for our tests so far.
             requires_config_enabled "MBEDTLS_RSA_C"
     esac
 
@@ -494,9 +526,10 @@
 
 adapt_cmd_for_psk () {
     case "$2" in
-        *openssl*) s='-psk abc123 -nocert';;
-        *gnutls-*) s='--pskkey=abc123';;
-        *) s='psk=abc123';;
+        *openssl*s_server*) s='-psk 73776f726466697368 -nocert';;
+        *openssl*) s='-psk 73776f726466697368';;
+        *gnutls-*) s='--pskusername=Client_identity --pskkey=73776f726466697368';;
+        *) s='psk=73776f726466697368';;
     esac
     eval $1='"$2 $s"'
     unset s
@@ -2449,9 +2482,9 @@
 requires_hash_alg SHA_256
 run_test    "Opaque key for server authentication: RSA-PSK" \
             "$P_SRV debug_level=1 key_opaque=1 key_opaque_algs=rsa-decrypt,none \
-             psk=abc123 psk_identity=foo" \
+             psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI force_version=tls12 force_ciphersuite=TLS-RSA-PSK-WITH-AES-128-CBC-SHA256 \
-             psk=abc123 psk_identity=foo" \
+             psk=73776f726466697368 psk_identity=foo" \
             0 \
             -c "Verifying peer X.509 certificate... ok" \
             -c "Ciphersuite is TLS-RSA-PSK-" \
@@ -2698,12 +2731,14 @@
             -C "error"
 
 # Tests for SHA-1 support
+requires_hash_alg SHA_1
 run_test    "SHA-1 forbidden by default in server certificate" \
             "$P_SRV key_file=data_files/server2.key crt_file=data_files/server2.crt" \
             "$P_CLI debug_level=2 force_version=tls12 allow_sha1=0" \
             1 \
             -c "The certificate is signed with an unacceptable hash"
 
+requires_hash_alg SHA_1
 run_test    "SHA-1 explicitly allowed in server certificate" \
             "$P_SRV key_file=data_files/server2.key crt_file=data_files/server2.crt" \
             "$P_CLI force_version=tls12 allow_sha1=1" \
@@ -2714,17 +2749,23 @@
             "$P_CLI force_version=tls12 allow_sha1=0" \
             0
 
+requires_hash_alg SHA_1
+requires_config_enabled MBEDTLS_RSA_C
 run_test    "SHA-1 forbidden by default in client certificate" \
             "$P_SRV force_version=tls12 auth_mode=required allow_sha1=0" \
             "$P_CLI key_file=data_files/cli-rsa.key crt_file=data_files/cli-rsa-sha1.crt" \
             1 \
             -s "The certificate is signed with an unacceptable hash"
 
+requires_hash_alg SHA_1
+requires_config_enabled MBEDTLS_RSA_C
 run_test    "SHA-1 explicitly allowed in client certificate" \
             "$P_SRV force_version=tls12 auth_mode=required allow_sha1=1" \
             "$P_CLI key_file=data_files/cli-rsa.key crt_file=data_files/cli-rsa-sha1.crt" \
             0
 
+requires_config_enabled MBEDTLS_RSA_C
+requires_hash_alg SHA_256
 run_test    "SHA-256 allowed by default in client certificate" \
             "$P_SRV force_version=tls12 auth_mode=required allow_sha1=0" \
             "$P_CLI key_file=data_files/cli-rsa.key crt_file=data_files/cli-rsa-sha256.crt" \
@@ -3820,7 +3861,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: openssl client" \
-            "$P_SRV debug_level=3 tickets=1" \
+            "$P_SRV force_version=tls12 debug_level=3 tickets=1" \
             "( $O_CLI -sess_out $SESSION; \
                $O_CLI -sess_in $SESSION; \
                rm -f $SESSION )" \
@@ -5626,6 +5667,7 @@
 # Test for the "secure renegotiation" extension only (no actual renegotiation)
 
 requires_gnutls
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Renego ext: gnutls server strict, client default" \
             "$G_NEXT_SRV --priority=NORMAL:-VERS-ALL:+VERS-TLS1.2:%SAFE_RENEGOTIATION" \
@@ -5636,6 +5678,7 @@
             -c "HTTP/1.0 200 [Oo][Kk]"
 
 requires_gnutls
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Renego ext: gnutls server unsafe, client default" \
             "$G_NEXT_SRV --priority=NORMAL:-VERS-ALL:+VERS-TLS1.2:%DISABLE_SAFE_RENEGOTIATION" \
@@ -5646,6 +5689,7 @@
             -c "HTTP/1.0 200 [Oo][Kk]"
 
 requires_gnutls
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Renego ext: gnutls server unsafe, client break legacy" \
             "$G_NEXT_SRV --priority=NORMAL:-VERS-ALL:+VERS-TLS1.2:%DISABLE_SAFE_RENEGOTIATION" \
@@ -5656,28 +5700,31 @@
             -C "HTTP/1.0 200 [Oo][Kk]"
 
 requires_gnutls
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Renego ext: gnutls client strict, server default" \
             "$P_SRV debug_level=3" \
-            "$G_CLI --priority=NORMAL:%SAFE_RENEGOTIATION localhost" \
+            "$G_CLI --priority=NORMAL:-VERS-ALL:+VERS-TLS1.2:%SAFE_RENEGOTIATION localhost" \
             0 \
             -s "received TLS_EMPTY_RENEGOTIATION_INFO\|found renegotiation extension" \
             -s "server hello, secure renegotiation extension"
 
 requires_gnutls
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Renego ext: gnutls client unsafe, server default" \
             "$P_SRV debug_level=3" \
-            "$G_CLI --priority=NORMAL:%DISABLE_SAFE_RENEGOTIATION localhost" \
+            "$G_CLI --priority=NORMAL:-VERS-ALL:+VERS-TLS1.2:%DISABLE_SAFE_RENEGOTIATION localhost" \
             0 \
             -S "received TLS_EMPTY_RENEGOTIATION_INFO\|found renegotiation extension" \
             -S "server hello, secure renegotiation extension"
 
 requires_gnutls
+requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Renego ext: gnutls client unsafe, server break legacy" \
             "$P_SRV debug_level=3 allow_legacy=-1" \
-            "$G_CLI --priority=NORMAL:%DISABLE_SAFE_RENEGOTIATION localhost" \
+            "$G_CLI --priority=NORMAL:-VERS-ALL:+VERS-TLS1.2:%DISABLE_SAFE_RENEGOTIATION localhost" \
             1 \
             -S "received TLS_EMPTY_RENEGOTIATION_INFO\|found renegotiation extension" \
             -S "server hello, secure renegotiation extension"
@@ -7789,7 +7836,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "keyUsage cli-auth: RSA, DigitalSignature: OK" \
             "$P_SRV debug_level=1 auth_mode=optional" \
-            "$O_CLI -key data_files/server2.key \
+            "$O_CLI -tls1_2 -key data_files/server2.key \
              -cert data_files/server2.ku-ds.crt" \
             0 \
             -s "Verifying peer X.509 certificate... ok" \
@@ -7799,7 +7846,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "keyUsage cli-auth: RSA, KeyEncipherment: fail (soft)" \
             "$P_SRV debug_level=1 auth_mode=optional" \
-            "$O_CLI -key data_files/server2.key \
+            "$O_CLI -tls1_2 -key data_files/server2.key \
              -cert data_files/server2.ku-ke.crt" \
             0 \
             -s "bad certificate (usage extensions)" \
@@ -7807,8 +7854,8 @@
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "keyUsage cli-auth: RSA, KeyEncipherment: fail (hard)" \
-            "$P_SRV debug_level=1 auth_mode=required" \
-            "$O_CLI -key data_files/server2.key \
+            "$P_SRV debug_level=1 force_version=tls12 auth_mode=required" \
+            "$O_CLI -tls1_2 -key data_files/server2.key \
              -cert data_files/server2.ku-ke.crt" \
             1 \
             -s "bad certificate (usage extensions)" \
@@ -7817,7 +7864,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "keyUsage cli-auth: ECDSA, DigitalSignature: OK" \
             "$P_SRV debug_level=1 auth_mode=optional" \
-            "$O_CLI -key data_files/server5.key \
+            "$O_CLI -tls1_2 -key data_files/server5.key \
              -cert data_files/server5.ku-ds.crt" \
             0 \
             -s "Verifying peer X.509 certificate... ok" \
@@ -7827,7 +7874,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "keyUsage cli-auth: ECDSA, KeyAgreement: fail (soft)" \
             "$P_SRV debug_level=1 auth_mode=optional" \
-            "$O_CLI -key data_files/server5.key \
+            "$O_CLI -tls1_2 -key data_files/server5.key \
              -cert data_files/server5.ku-ka.crt" \
             0 \
             -s "bad certificate (usage extensions)" \
@@ -8004,7 +8051,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "extKeyUsage cli-auth: clientAuth -> OK" \
             "$P_SRV debug_level=1 auth_mode=optional" \
-            "$O_CLI -key data_files/server5.key \
+            "$O_CLI -tls1_2 -key data_files/server5.key \
              -cert data_files/server5.eku-cli.crt" \
             0 \
             -S "bad certificate (usage extensions)" \
@@ -8013,7 +8060,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "extKeyUsage cli-auth: serverAuth,clientAuth -> OK" \
             "$P_SRV debug_level=1 auth_mode=optional" \
-            "$O_CLI -key data_files/server5.key \
+            "$O_CLI -tls1_2 -key data_files/server5.key \
              -cert data_files/server5.eku-srv_cli.crt" \
             0 \
             -S "bad certificate (usage extensions)" \
@@ -8022,7 +8069,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "extKeyUsage cli-auth: codeSign,anyEKU -> OK" \
             "$P_SRV debug_level=1 auth_mode=optional" \
-            "$O_CLI -key data_files/server5.key \
+            "$O_CLI -tls1_2 -key data_files/server5.key \
              -cert data_files/server5.eku-cs_any.crt" \
             0 \
             -S "bad certificate (usage extensions)" \
@@ -8031,7 +8078,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "extKeyUsage cli-auth: codeSign -> fail (soft)" \
             "$P_SRV debug_level=1 auth_mode=optional" \
-            "$O_CLI -key data_files/server5.key \
+            "$O_CLI -tls1_2 -key data_files/server5.key \
              -cert data_files/server5.eku-cs.crt" \
             0 \
             -s "bad certificate (usage extensions)" \
@@ -8040,7 +8087,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "extKeyUsage cli-auth: codeSign -> fail (hard)" \
             "$P_SRV debug_level=1 auth_mode=required" \
-            "$O_CLI -key data_files/server5.key \
+            "$O_CLI -tls1_2 -key data_files/server5.key \
              -cert data_files/server5.eku-cs.crt" \
             1 \
             -s "bad certificate (usage extensions)" \
@@ -8183,9 +8230,9 @@
 # Tests for PSK callback
 
 run_test    "PSK callback: psk, no callback" \
-            "$P_SRV psk=abc123 psk_identity=foo" \
+            "$P_SRV psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
-            psk_identity=foo psk=abc123" \
+            psk_identity=foo psk=73776f726466697368" \
             0 \
             -S "SSL - The handshake negotiation failed" \
             -S "SSL - Unknown identity received" \
@@ -8193,9 +8240,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque psk on client, no callback" \
-            "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo" \
+            "$P_SRV extended_ms=0 debug_level=1 psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI extended_ms=0 debug_level=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
-            psk_identity=foo psk=abc123 psk_opaque=1" \
+            psk_identity=foo psk=73776f726466697368 psk_opaque=1" \
             0 \
             -C "session hash for extended master secret"\
             -S "session hash for extended master secret"\
@@ -8205,9 +8252,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque psk on client, no callback, SHA-384" \
-            "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo" \
+            "$P_SRV extended_ms=0 debug_level=1 psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI extended_ms=0 debug_level=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \
-            psk_identity=foo psk=abc123 psk_opaque=1" \
+            psk_identity=foo psk=73776f726466697368 psk_opaque=1" \
             0 \
             -C "session hash for extended master secret"\
             -S "session hash for extended master secret"\
@@ -8217,9 +8264,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque psk on client, no callback, EMS" \
-            "$P_SRV extended_ms=1 debug_level=3 psk=abc123 psk_identity=foo" \
+            "$P_SRV extended_ms=1 debug_level=3 psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI extended_ms=1 debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
-            psk_identity=foo psk=abc123 psk_opaque=1" \
+            psk_identity=foo psk=73776f726466697368 psk_opaque=1" \
             0 \
             -c "session hash for extended master secret"\
             -s "session hash for extended master secret"\
@@ -8229,9 +8276,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque psk on client, no callback, SHA-384, EMS" \
-            "$P_SRV extended_ms=1 debug_level=3 psk=abc123 psk_identity=foo" \
+            "$P_SRV extended_ms=1 debug_level=3 psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI extended_ms=1 debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \
-            psk_identity=foo psk=abc123 psk_opaque=1" \
+            psk_identity=foo psk=73776f726466697368 psk_opaque=1" \
             0 \
             -c "session hash for extended master secret"\
             -s "session hash for extended master secret"\
@@ -8241,9 +8288,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque rsa-psk on client, no callback" \
-            "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo" \
+            "$P_SRV extended_ms=0 debug_level=1 psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI extended_ms=0 debug_level=1 min_version=tls12 force_ciphersuite=TLS-RSA-PSK-WITH-AES-128-CBC-SHA256 \
-            psk_identity=foo psk=abc123 psk_opaque=1" \
+            psk_identity=foo psk=73776f726466697368 psk_opaque=1" \
             0 \
             -C "session hash for extended master secret"\
             -S "session hash for extended master secret"\
@@ -8253,9 +8300,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque rsa-psk on client, no callback, SHA-384" \
-            "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo" \
+            "$P_SRV extended_ms=0 debug_level=1 psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI extended_ms=0 debug_level=1 min_version=tls12 force_ciphersuite=TLS-RSA-PSK-WITH-AES-256-CBC-SHA384 \
-            psk_identity=foo psk=abc123 psk_opaque=1" \
+            psk_identity=foo psk=73776f726466697368 psk_opaque=1" \
             0 \
             -C "session hash for extended master secret"\
             -S "session hash for extended master secret"\
@@ -8265,9 +8312,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque rsa-psk on client, no callback, EMS" \
-            "$P_SRV extended_ms=1 debug_level=3 psk=abc123 psk_identity=foo" \
+            "$P_SRV extended_ms=1 debug_level=3 psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI extended_ms=1 debug_level=3 min_version=tls12 force_ciphersuite=TLS-RSA-PSK-WITH-AES-128-CBC-SHA \
-            psk_identity=foo psk=abc123 psk_opaque=1" \
+            psk_identity=foo psk=73776f726466697368 psk_opaque=1" \
             0 \
             -c "session hash for extended master secret"\
             -s "session hash for extended master secret"\
@@ -8277,9 +8324,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque rsa-psk on client, no callback, SHA-384, EMS" \
-            "$P_SRV extended_ms=1 debug_level=3 psk=abc123 psk_identity=foo" \
+            "$P_SRV extended_ms=1 debug_level=3 psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI extended_ms=1 debug_level=3 min_version=tls12 force_ciphersuite=TLS-RSA-PSK-WITH-AES-256-CBC-SHA384 \
-            psk_identity=foo psk=abc123 psk_opaque=1" \
+            psk_identity=foo psk=73776f726466697368 psk_opaque=1" \
             0 \
             -c "session hash for extended master secret"\
             -s "session hash for extended master secret"\
@@ -8289,9 +8336,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque ecdhe-psk on client, no callback" \
-            "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo" \
+            "$P_SRV extended_ms=0 debug_level=1 psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI extended_ms=0 debug_level=1 min_version=tls12 force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256 \
-            psk_identity=foo psk=abc123 psk_opaque=1" \
+            psk_identity=foo psk=73776f726466697368 psk_opaque=1" \
             0 \
             -C "session hash for extended master secret"\
             -S "session hash for extended master secret"\
@@ -8301,9 +8348,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque ecdhe-psk on client, no callback, SHA-384" \
-            "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo" \
+            "$P_SRV extended_ms=0 debug_level=1 psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI extended_ms=0 debug_level=1 min_version=tls12 force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384 \
-            psk_identity=foo psk=abc123 psk_opaque=1" \
+            psk_identity=foo psk=73776f726466697368 psk_opaque=1" \
             0 \
             -C "session hash for extended master secret"\
             -S "session hash for extended master secret"\
@@ -8313,9 +8360,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque ecdhe-psk on client, no callback, EMS" \
-            "$P_SRV extended_ms=1 debug_level=3 psk=abc123 psk_identity=foo" \
+            "$P_SRV extended_ms=1 debug_level=3 psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI extended_ms=1 debug_level=3 min_version=tls12 force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA \
-            psk_identity=foo psk=abc123 psk_opaque=1" \
+            psk_identity=foo psk=73776f726466697368 psk_opaque=1" \
             0 \
             -c "session hash for extended master secret"\
             -s "session hash for extended master secret"\
@@ -8325,9 +8372,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque ecdhe-psk on client, no callback, SHA-384, EMS" \
-            "$P_SRV extended_ms=1 debug_level=3 psk=abc123 psk_identity=foo" \
+            "$P_SRV extended_ms=1 debug_level=3 psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI extended_ms=1 debug_level=3 min_version=tls12 force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384 \
-            psk_identity=foo psk=abc123 psk_opaque=1" \
+            psk_identity=foo psk=73776f726466697368 psk_opaque=1" \
             0 \
             -c "session hash for extended master secret"\
             -s "session hash for extended master secret"\
@@ -8337,9 +8384,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque dhe-psk on client, no callback" \
-            "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo" \
+            "$P_SRV extended_ms=0 debug_level=1 psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI extended_ms=0 debug_level=1 min_version=tls12 force_ciphersuite=TLS-DHE-PSK-WITH-AES-128-CBC-SHA256 \
-            psk_identity=foo psk=abc123 psk_opaque=1" \
+            psk_identity=foo psk=73776f726466697368 psk_opaque=1" \
             0 \
             -C "session hash for extended master secret"\
             -S "session hash for extended master secret"\
@@ -8349,9 +8396,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque dhe-psk on client, no callback, SHA-384" \
-            "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo" \
+            "$P_SRV extended_ms=0 debug_level=1 psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI extended_ms=0 debug_level=1 min_version=tls12 force_ciphersuite=TLS-DHE-PSK-WITH-AES-256-CBC-SHA384 \
-            psk_identity=foo psk=abc123 psk_opaque=1" \
+            psk_identity=foo psk=73776f726466697368 psk_opaque=1" \
             0 \
             -C "session hash for extended master secret"\
             -S "session hash for extended master secret"\
@@ -8361,9 +8408,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque dhe-psk on client, no callback, EMS" \
-            "$P_SRV extended_ms=1 debug_level=3 psk=abc123 psk_identity=foo" \
+            "$P_SRV extended_ms=1 debug_level=3 psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI extended_ms=1 debug_level=3 min_version=tls12 force_ciphersuite=TLS-DHE-PSK-WITH-AES-128-CBC-SHA \
-            psk_identity=foo psk=abc123 psk_opaque=1" \
+            psk_identity=foo psk=73776f726466697368 psk_opaque=1" \
             0 \
             -c "session hash for extended master secret"\
             -s "session hash for extended master secret"\
@@ -8373,9 +8420,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: opaque dhe-psk on client, no callback, SHA-384, EMS" \
-            "$P_SRV extended_ms=1 debug_level=3 psk=abc123 psk_identity=foo" \
+            "$P_SRV extended_ms=1 debug_level=3 psk=73776f726466697368 psk_identity=foo" \
             "$P_CLI extended_ms=1 debug_level=3 min_version=tls12 force_ciphersuite=TLS-DHE-PSK-WITH-AES-256-CBC-SHA384 \
-            psk_identity=foo psk=abc123 psk_opaque=1" \
+            psk_identity=foo psk=73776f726466697368 psk_opaque=1" \
             0 \
             -c "session hash for extended master secret"\
             -s "session hash for extended master secret"\
@@ -8385,9 +8432,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, static opaque on server, no callback" \
-            "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
+            "$P_SRV extended_ms=0 debug_level=1 psk=73776f726466697368 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
             "$P_CLI extended_ms=0 debug_level=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
-            psk_identity=foo psk=abc123" \
+            psk_identity=foo psk=73776f726466697368" \
             0 \
             -C "session hash for extended master secret"\
             -S "session hash for extended master secret"\
@@ -8397,9 +8444,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, static opaque on server, no callback, SHA-384" \
-            "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384" \
+            "$P_SRV extended_ms=0 debug_level=1 psk=73776f726466697368 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384" \
             "$P_CLI extended_ms=0 debug_level=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \
-            psk_identity=foo psk=abc123" \
+            psk_identity=foo psk=73776f726466697368" \
             0 \
             -C "session hash for extended master secret"\
             -S "session hash for extended master secret"\
@@ -8409,10 +8456,10 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, static opaque on server, no callback, EMS" \
-            "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 \
+            "$P_SRV debug_level=3 psk=73776f726466697368 psk_identity=foo psk_opaque=1 min_version=tls12 \
             force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA extended_ms=1" \
             "$P_CLI debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
-            psk_identity=foo psk=abc123 extended_ms=1" \
+            psk_identity=foo psk=73776f726466697368 extended_ms=1" \
             0 \
             -c "session hash for extended master secret"\
             -s "session hash for extended master secret"\
@@ -8422,10 +8469,10 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, static opaque on server, no callback, EMS, SHA384" \
-            "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 \
+            "$P_SRV debug_level=3 psk=73776f726466697368 psk_identity=foo psk_opaque=1 min_version=tls12 \
             force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 extended_ms=1" \
             "$P_CLI debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \
-            psk_identity=foo psk=abc123 extended_ms=1" \
+            psk_identity=foo psk=73776f726466697368 extended_ms=1" \
             0 \
             -c "session hash for extended master secret"\
             -s "session hash for extended master secret"\
@@ -8435,9 +8482,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw rsa-psk on client, static opaque on server, no callback" \
-            "$P_SRV extended_ms=0 debug_level=5 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-RSA-PSK-WITH-AES-128-CBC-SHA" \
+            "$P_SRV extended_ms=0 debug_level=5 psk=73776f726466697368 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-RSA-PSK-WITH-AES-128-CBC-SHA" \
             "$P_CLI extended_ms=0 debug_level=5 min_version=tls12 force_ciphersuite=TLS-RSA-PSK-WITH-AES-128-CBC-SHA \
-            psk_identity=foo psk=abc123" \
+            psk_identity=foo psk=73776f726466697368" \
             0 \
             -C "session hash for extended master secret"\
             -S "session hash for extended master secret"\
@@ -8447,9 +8494,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw rsa-psk on client, static opaque on server, no callback, SHA-384" \
-            "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-RSA-PSK-WITH-AES-256-CBC-SHA384" \
+            "$P_SRV extended_ms=0 debug_level=1 psk=73776f726466697368 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-RSA-PSK-WITH-AES-256-CBC-SHA384" \
             "$P_CLI extended_ms=0 debug_level=1 min_version=tls12 force_ciphersuite=TLS-RSA-PSK-WITH-AES-256-CBC-SHA384 \
-            psk_identity=foo psk=abc123" \
+            psk_identity=foo psk=73776f726466697368" \
             0 \
             -C "session hash for extended master secret"\
             -S "session hash for extended master secret"\
@@ -8459,10 +8506,10 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw rsa-psk on client, static opaque on server, no callback, EMS" \
-            "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 \
+            "$P_SRV debug_level=3 psk=73776f726466697368 psk_identity=foo psk_opaque=1 min_version=tls12 \
             force_ciphersuite=TLS-RSA-PSK-WITH-AES-128-CBC-SHA extended_ms=1" \
             "$P_CLI debug_level=3 min_version=tls12 force_ciphersuite=TLS-RSA-PSK-WITH-AES-128-CBC-SHA \
-            psk_identity=foo psk=abc123 extended_ms=1" \
+            psk_identity=foo psk=73776f726466697368 extended_ms=1" \
             0 \
             -c "session hash for extended master secret"\
             -s "session hash for extended master secret"\
@@ -8472,10 +8519,10 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw rsa-psk on client, static opaque on server, no callback, EMS, SHA384" \
-            "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 \
+            "$P_SRV debug_level=3 psk=73776f726466697368 psk_identity=foo psk_opaque=1 min_version=tls12 \
             force_ciphersuite=TLS-RSA-PSK-WITH-AES-256-CBC-SHA384 extended_ms=1" \
             "$P_CLI debug_level=3 min_version=tls12 force_ciphersuite=TLS-RSA-PSK-WITH-AES-256-CBC-SHA384 \
-            psk_identity=foo psk=abc123 extended_ms=1" \
+            psk_identity=foo psk=73776f726466697368 extended_ms=1" \
             0 \
             -c "session hash for extended master secret"\
             -s "session hash for extended master secret"\
@@ -8485,9 +8532,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw ecdhe-psk on client, static opaque on server, no callback" \
-            "$P_SRV extended_ms=0 debug_level=5 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA" \
+            "$P_SRV extended_ms=0 debug_level=5 psk=73776f726466697368 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA" \
             "$P_CLI extended_ms=0 debug_level=5 min_version=tls12 force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA \
-            psk_identity=foo psk=abc123" \
+            psk_identity=foo psk=73776f726466697368" \
             0 \
             -C "session hash for extended master secret"\
             -S "session hash for extended master secret"\
@@ -8497,9 +8544,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw ecdhe-psk on client, static opaque on server, no callback, SHA-384" \
-            "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384" \
+            "$P_SRV extended_ms=0 debug_level=1 psk=73776f726466697368 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384" \
             "$P_CLI extended_ms=0 debug_level=1 min_version=tls12 force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384 \
-            psk_identity=foo psk=abc123" \
+            psk_identity=foo psk=73776f726466697368" \
             0 \
             -C "session hash for extended master secret"\
             -S "session hash for extended master secret"\
@@ -8509,10 +8556,10 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw ecdhe-psk on client, static opaque on server, no callback, EMS" \
-            "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 \
+            "$P_SRV debug_level=3 psk=73776f726466697368 psk_identity=foo psk_opaque=1 min_version=tls12 \
             force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA extended_ms=1" \
             "$P_CLI debug_level=3 min_version=tls12 force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA \
-            psk_identity=foo psk=abc123 extended_ms=1" \
+            psk_identity=foo psk=73776f726466697368 extended_ms=1" \
             0 \
             -c "session hash for extended master secret"\
             -s "session hash for extended master secret"\
@@ -8522,10 +8569,10 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw ecdhe-psk on client, static opaque on server, no callback, EMS, SHA384" \
-            "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 \
+            "$P_SRV debug_level=3 psk=73776f726466697368 psk_identity=foo psk_opaque=1 min_version=tls12 \
             force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384 extended_ms=1" \
             "$P_CLI debug_level=3 min_version=tls12 force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384 \
-            psk_identity=foo psk=abc123 extended_ms=1" \
+            psk_identity=foo psk=73776f726466697368 extended_ms=1" \
             0 \
             -c "session hash for extended master secret"\
             -s "session hash for extended master secret"\
@@ -8535,9 +8582,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw dhe-psk on client, static opaque on server, no callback" \
-            "$P_SRV extended_ms=0 debug_level=5 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-DHE-PSK-WITH-AES-128-CBC-SHA" \
+            "$P_SRV extended_ms=0 debug_level=5 psk=73776f726466697368 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-DHE-PSK-WITH-AES-128-CBC-SHA" \
             "$P_CLI extended_ms=0 debug_level=5 min_version=tls12 force_ciphersuite=TLS-DHE-PSK-WITH-AES-128-CBC-SHA \
-            psk_identity=foo psk=abc123" \
+            psk_identity=foo psk=73776f726466697368" \
             0 \
             -C "session hash for extended master secret"\
             -S "session hash for extended master secret"\
@@ -8547,9 +8594,9 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw dhe-psk on client, static opaque on server, no callback, SHA-384" \
-            "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-DHE-PSK-WITH-AES-256-CBC-SHA384" \
+            "$P_SRV extended_ms=0 debug_level=1 psk=73776f726466697368 psk_identity=foo psk_opaque=1 min_version=tls12 force_ciphersuite=TLS-DHE-PSK-WITH-AES-256-CBC-SHA384" \
             "$P_CLI extended_ms=0 debug_level=1 min_version=tls12 force_ciphersuite=TLS-DHE-PSK-WITH-AES-256-CBC-SHA384 \
-            psk_identity=foo psk=abc123" \
+            psk_identity=foo psk=73776f726466697368" \
             0 \
             -C "session hash for extended master secret"\
             -S "session hash for extended master secret"\
@@ -8559,10 +8606,10 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw dhe-psk on client, static opaque on server, no callback, EMS" \
-            "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 \
+            "$P_SRV debug_level=3 psk=73776f726466697368 psk_identity=foo psk_opaque=1 min_version=tls12 \
             force_ciphersuite=TLS-DHE-PSK-WITH-AES-128-CBC-SHA extended_ms=1" \
             "$P_CLI debug_level=3 min_version=tls12 force_ciphersuite=TLS-DHE-PSK-WITH-AES-128-CBC-SHA \
-            psk_identity=foo psk=abc123 extended_ms=1" \
+            psk_identity=foo psk=73776f726466697368 extended_ms=1" \
             0 \
             -c "session hash for extended master secret"\
             -s "session hash for extended master secret"\
@@ -8572,10 +8619,10 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw dhe-psk on client, static opaque on server, no callback, EMS, SHA384" \
-            "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls12 \
+            "$P_SRV debug_level=3 psk=73776f726466697368 psk_identity=foo psk_opaque=1 min_version=tls12 \
             force_ciphersuite=TLS-DHE-PSK-WITH-AES-256-CBC-SHA384 extended_ms=1" \
             "$P_CLI debug_level=3 min_version=tls12 force_ciphersuite=TLS-DHE-PSK-WITH-AES-256-CBC-SHA384 \
-            psk_identity=foo psk=abc123 extended_ms=1" \
+            psk_identity=foo psk=73776f726466697368 extended_ms=1" \
             0 \
             -c "session hash for extended master secret"\
             -s "session hash for extended master secret"\
@@ -8785,7 +8832,7 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, mismatching static raw PSK on server, opaque PSK from callback" \
-            "$P_SRV extended_ms=0 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
+            "$P_SRV extended_ms=0 psk_identity=foo psk=73776f726466697368 debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
             "$P_CLI extended_ms=0 debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
             psk_identity=def psk=beef" \
             0 \
@@ -8797,7 +8844,7 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, mismatching static opaque PSK on server, opaque PSK from callback" \
-            "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
+            "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=foo psk=73776f726466697368 debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
             "$P_CLI extended_ms=0 debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
             psk_identity=def psk=beef" \
             0 \
@@ -8809,7 +8856,7 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, mismatching static opaque PSK on server, raw PSK from callback" \
-            "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
+            "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=foo psk=73776f726466697368 debug_level=3 psk_list=abc,dead,def,beef min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
             "$P_CLI extended_ms=0 debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
             psk_identity=def psk=beef" \
             0 \
@@ -8821,7 +8868,7 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, id-matching but wrong raw PSK on server, opaque PSK from callback" \
-            "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=def psk=abc123 debug_level=3 psk_list=abc,dead,def,beef min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
+            "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=def psk=73776f726466697368 debug_level=3 psk_list=abc,dead,def,beef min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
             "$P_CLI extended_ms=0 debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
             psk_identity=def psk=beef" \
             0 \
@@ -8833,7 +8880,7 @@
 
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "PSK callback: raw psk on client, matching opaque PSK on server, wrong opaque PSK from callback" \
-            "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=def psk=beef debug_level=3 psk_list=abc,dead,def,abc123 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
+            "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=def psk=beef debug_level=3 psk_list=abc,dead,def,73776f726466697368 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \
             "$P_CLI extended_ms=0 debug_level=3 min_version=tls12 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
             psk_identity=def psk=beef" \
             1 \
@@ -8842,16 +8889,16 @@
 run_test    "PSK callback: no psk, no callback" \
             "$P_SRV" \
             "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
-            psk_identity=foo psk=abc123" \
+            psk_identity=foo psk=73776f726466697368" \
             1 \
             -s "SSL - The handshake negotiation failed" \
             -S "SSL - Unknown identity received" \
             -S "SSL - Verification of the message MAC failed"
 
 run_test    "PSK callback: callback overrides other settings" \
-            "$P_SRV psk=abc123 psk_identity=foo psk_list=abc,dead,def,beef" \
+            "$P_SRV psk=73776f726466697368 psk_identity=foo psk_list=abc,dead,def,beef" \
             "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \
-            psk_identity=foo psk=abc123" \
+            psk_identity=foo psk=73776f726466697368" \
             1 \
             -S "SSL - The handshake negotiation failed" \
             -s "SSL - Unknown identity received" \
@@ -9069,11 +9116,25 @@
 
 # Test for ClientHello without extensions
 
+# Without extensions, ECC is impossible (no curve negotiation).
+requires_config_enabled MBEDTLS_RSA_C
 requires_gnutls
-run_test    "ClientHello without extensions" \
+run_test    "ClientHello without extensions: RSA" \
             "$P_SRV force_version=tls12 debug_level=3" \
             "$G_CLI --priority=NORMAL:%NO_EXTENSIONS:%DISABLE_SAFE_RENEGOTIATION localhost" \
             0 \
+            -s "Ciphersuite is .*-RSA-WITH-.*" \
+            -S "Ciphersuite is .*-EC.*" \
+            -s "dumping 'client hello extensions' (0 bytes)"
+
+requires_config_enabled MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+requires_gnutls
+run_test    "ClientHello without extensions: PSK" \
+            "$P_SRV force_version=tls12 debug_level=3 psk=73776f726466697368" \
+            "$G_CLI --priority=NORMAL:+PSK:-RSA:-DHE-RSA:%NO_EXTENSIONS:%DISABLE_SAFE_RENEGOTIATION --pskusername=Client_identity --pskkey=73776f726466697368 localhost" \
+            0 \
+            -s "Ciphersuite is .*-PSK-.*" \
+            -S "Ciphersuite is .*-EC.*" \
             -s "dumping 'client hello extensions' (0 bytes)"
 
 # Tests for mbedtls_ssl_get_bytes_avail()
@@ -9683,9 +9744,9 @@
 
 requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
 run_test    "SSL async private: decrypt RSA-PSK, delay=0" \
-            "$P_SRV psk=abc123 \
+            "$P_SRV psk=73776f726466697368 \
              async_operations=d async_private_delay1=0 async_private_delay2=0" \
-            "$P_CLI psk=abc123 \
+            "$P_CLI psk=73776f726466697368 \
              force_ciphersuite=TLS-RSA-PSK-WITH-AES-128-CBC-SHA256" \
             0 \
             -s "Async decrypt callback: using key slot " \
@@ -9693,9 +9754,9 @@
 
 requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
 run_test    "SSL async private: decrypt RSA-PSK, delay=1" \
-            "$P_SRV psk=abc123 \
+            "$P_SRV psk=73776f726466697368 \
              async_operations=d async_private_delay1=1 async_private_delay2=1" \
-            "$P_CLI psk=abc123 \
+            "$P_CLI psk=73776f726466697368 \
              force_ciphersuite=TLS-RSA-PSK-WITH-AES-128-CBC-SHA256" \
             0 \
             -s "Async decrypt callback: using key slot " \
@@ -10145,8 +10206,8 @@
             -s "! Certificate verification was skipped"
 
 run_test    "DTLS wrong PSK: badmac alert" \
-            "$P_SRV dtls=1 psk=abc123 force_ciphersuite=TLS-PSK-WITH-AES-128-GCM-SHA256" \
-            "$P_CLI dtls=1 psk=abc124" \
+            "$P_SRV dtls=1 psk=73776f726466697368 force_ciphersuite=TLS-PSK-WITH-AES-128-GCM-SHA256" \
+            "$P_CLI dtls=1 psk=73776f726466697374" \
             1 \
             -s "SSL - Verification of the message MAC failed" \
             -c "SSL - A fatal alert message was received from our peer"
@@ -11914,8 +11975,8 @@
 requires_config_value_at_most "MBEDTLS_SSL_DTLS_MAX_BUFFERING" 230
 run_test    "DTLS reordering: Buffer encrypted Finished message, drop for fragmented NewSessionTicket" \
             -p "$P_PXY delay_srv=NewSessionTicket delay_srv=NewSessionTicket delay_ccs=1" \
-            "$P_SRV mtu=140 response_size=90 dgram_packing=0 psk=abc123 psk_identity=foo cookies=0 dtls=1 debug_level=2" \
-            "$P_CLI dgram_packing=0 dtls=1 debug_level=2 force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8 psk=abc123 psk_identity=foo" \
+            "$P_SRV mtu=140 response_size=90 dgram_packing=0 psk=73776f726466697368 psk_identity=foo cookies=0 dtls=1 debug_level=2" \
+            "$P_CLI dgram_packing=0 dtls=1 debug_level=2 force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8 psk=73776f726466697368 psk_identity=foo" \
             0 \
             -s "Buffer record from epoch 1" \
             -s "Found buffered record from current epoch - load" \
@@ -11929,8 +11990,8 @@
 run_test    "DTLS proxy: 3d (drop, delay, duplicate), \"short\" PSK handshake" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
             "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
-             psk=abc123" \
-            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=abc123 \
+             psk=73776f726466697368" \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=73776f726466697368 \
              force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \
             0 \
             -s "Extra-header:" \
@@ -12005,8 +12066,8 @@
 run_test    "DTLS proxy: 3d, min handshake, resumption" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
             "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
-             psk=abc123 debug_level=3" \
-            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=abc123 \
+             psk=73776f726466697368 debug_level=3" \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=73776f726466697368 \
              debug_level=3 reconnect=1 skip_close_notify=1 read_timeout=1000 max_resend=10 \
              force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \
             0 \
@@ -12020,8 +12081,8 @@
 run_test    "DTLS proxy: 3d, min handshake, resumption, nbio" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
             "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
-             psk=abc123 debug_level=3 nbio=2" \
-            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=abc123 \
+             psk=73776f726466697368 debug_level=3 nbio=2" \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=73776f726466697368 \
              debug_level=3 reconnect=1 skip_close_notify=1 read_timeout=1000 max_resend=10 \
              force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8 nbio=2" \
             0 \
@@ -12035,8 +12096,8 @@
 run_test    "DTLS proxy: 3d, min handshake, client-initiated renego" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
             "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
-             psk=abc123 renegotiation=1 debug_level=2" \
-            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=abc123 \
+             psk=73776f726466697368 renegotiation=1 debug_level=2" \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=73776f726466697368 \
              renegotiate=1 debug_level=2 \
              force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \
             0 \
@@ -12050,8 +12111,8 @@
 run_test    "DTLS proxy: 3d, min handshake, client-initiated renego, nbio" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
             "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
-             psk=abc123 renegotiation=1 debug_level=2" \
-            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=abc123 \
+             psk=73776f726466697368 renegotiation=1 debug_level=2" \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=73776f726466697368 \
              renegotiate=1 debug_level=2 \
              force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \
             0 \
@@ -12065,9 +12126,9 @@
 run_test    "DTLS proxy: 3d, min handshake, server-initiated renego" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
             "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
-             psk=abc123 renegotiate=1 renegotiation=1 exchanges=4 \
+             psk=73776f726466697368 renegotiate=1 renegotiation=1 exchanges=4 \
              debug_level=2" \
-            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=abc123 \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=73776f726466697368 \
              renegotiation=1 exchanges=4 debug_level=2 \
              force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \
             0 \
@@ -12081,9 +12142,9 @@
 run_test    "DTLS proxy: 3d, min handshake, server-initiated renego, nbio" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
             "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 auth_mode=none \
-             psk=abc123 renegotiate=1 renegotiation=1 exchanges=4 \
+             psk=73776f726466697368 renegotiate=1 renegotiation=1 exchanges=4 \
              debug_level=2 nbio=2" \
-            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=abc123 \
+            "$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=0 psk=73776f726466697368 \
              renegotiation=1 exchanges=4 debug_level=2 nbio=2 \
              force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8" \
             0 \
@@ -14062,8 +14123,8 @@
 requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
 requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
 run_test    "TLS 1.3: no HRR in case of PSK key exchange mode" \
-            "$P_SRV nbio=2 psk=010203 psk_identity=0a0b0c tls13_kex_modes=psk groups=none" \
-            "$P_CLI nbio=2 debug_level=3 psk=010203 psk_identity=0a0b0c tls13_kex_modes=all" \
+            "$P_SRV nbio=2 psk=73776f726466697368 psk_identity=0a0b0c tls13_kex_modes=psk groups=none" \
+            "$P_CLI nbio=2 debug_level=3 psk=73776f726466697368 psk_identity=0a0b0c tls13_kex_modes=all" \
             0 \
             -C "received HelloRetryRequest message" \
             -c "Selected key exchange mode: psk$" \
diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data
index a929c82..2bc3848 100644
--- a/tests/suites/test_suite_pk.data
+++ b/tests/suites/test_suite_pk.data
@@ -8,23 +8,23 @@
 depends_on:MBEDTLS_RSA_C
 valid_parameters_pkwrite:"308204a20201000282010100a9021f3d406ad555538bfd36ee82652e15615e89bfb8e84590dbee881652d3f143504796125964876bfd2be046f973beddcf92e1915bed66a06f8929794580d0836ad54143775f397c09044782b0573970eda3ec15191ea8330847c10542a9fd4cc3b4dfdd061f4d1051406773130f40f86d81255f0ab153c6307e1539acf95aee7f929ea6055be7139785b52392d9d42406d50925897507dda61a8f3f0919bead652c64eb959bdcfe415e17a6da6c5b69cc02ba142c16249c4adccdd0f7526773f12da023fd7ef431ca2d70ca890b04db2ea64f706e9ecebd5889e253599e6e5a9265e2883f0c9419a3dde5e89d9513ed29dbab7012dc5aca6b17ab528254b10203010001028201001689f5e89142ae18a6ffb0513715a4b0b4a13b9e5b3729a2bd62d738c6e15cea7bf3a4d85ab2193a0628c9452bb1f0c1af8b132789df1c95e72778bf5330f5b0d915d242d5e0818e85001ed5fa93d1ce13455deb0a15438562e8e3c8d60ec1e4c9ebff9f2b36b9cde9332cc79f0d17a7ae79cc1353cd75409ad9b4b6d7ee3d82af6f3207656cf2ac98947c15c398db0cebf8dc3eef5398269480cdd09411b960273ae3f364da09af849f24aa87346c58618ea91d9d6cd1d3932c80dbfc1f0a4166a9036911999ca27761079f0ce02db02c1c909ff9b4278578d7bb1b54b2b7082fc9e864b6b394e331c0d11a9a68255565b6dd477f4119c5809839520700711102818100d7db987ad86de6a9b0749fb5da80bacde3bebd72dcc83f60a27db74f927ac3661386577bfce5b4a00ad024682401d6aad29713c8e223b53415305ca07559821099b187fdd1bad3dc4dec9da96f5fa6128331e8f7d89f1e1a788698d1a27256dc7cd392f04e531a9e38e7265bf4fd7eec01e7835e9b1a0dd8923e440381be1c2702818100c87025fff7a493c623404966fbc8b32ed164ca620ad1a0ad11ef42fd12118456017856a8b42e5d4ad36104e9dc9f8a2f3003c3957ffddb20e2f4e3fc3cf2cdddae01f57a56de4fd24b91ab6d3e5cc0e8af0473659594a6bbfdaacf958f19c8d508eac12d8977616af6877106288093d37904a139220c1bc278ea56edc086976702818043e708685c7cf5fa9b4f948e1856366d5e1f3a694f9a8e954f884c89f3823ac5798ee12657bfcaba2dac9c47464c6dc2fecc17a531be19da706fee336bb6e47b645dbc71d3eff9856bddeb1ac9b644ffbdd58d7ba9e1240f1faaf797ba8a4d58becbaf85789e1bd979fcfccc209d3db7f0416bc9eef09b3a6d86b8ce8199d4310281804f4b86ccffe49d0d8ace98fb63ea9f708b284ba483d130b6a75cb76cb4e4372d6b41774f20912319420ca4cbfc1b25a8cb5f01d6381f6ebc50ed3ef08010327f5ba2acc1ac7220b3fa6f7399314db2879b0db0b5647abd87abb01295815a5b086491b2c0d81c616ed67ef8a8ce0727f446711d7323d4147b5828a52143c43b4b028180540756beba83c20a0bda11d6dec706a71744ff28090cec079dffb507d82828038fe657f61496a20317f779cb683ce8196c29a6fe28839a282eef4de57773be56808b0c3e2ac7747e2b200b2fbf20b55258cd24622a1ce0099de098ab0855106ae087f08b0c8c346d81619400c1b4838e33ed9ff90f05db8fccf8fb7ab881ca12"
 
-PK utils: RSA Minimum key
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_utils:MBEDTLS_PK_RSA:MBEDTLS_RSA_GEN_KEY_MIN_BITS:MBEDTLS_RSA_GEN_KEY_MIN_BITS:(MBEDTLS_RSA_GEN_KEY_MIN_BITS + 7) / 8:"RSA"
+PK utils: RSA 1024-bit
+depends_on:MBEDTLS_RSA_C
+pk_utils:MBEDTLS_PK_RSA:1024:1024:(1024 + 7) / 8:"RSA"
 
-# mbedtls_rsa_gen_key() only supports even sizes, so we don't test min+1,
-# min+3, etc.
-PK utils: RSA Minimum key + 2 bits
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_utils:MBEDTLS_PK_RSA:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 2:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 2:(MBEDTLS_RSA_GEN_KEY_MIN_BITS + 2 + 7) / 8:"RSA"
+# In the following 3 test cases we test a few different sizes that are not a
+# multiple of 8 and for which we have test data.
+PK utils: RSA 1026-bits
+depends_on:MBEDTLS_RSA_C
+pk_utils:MBEDTLS_PK_RSA:1026:1026:(1026 + 7) / 8:"RSA"
 
-PK utils: RSA Minimum key + 4 bits
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_utils:MBEDTLS_PK_RSA:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 4:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 4:(MBEDTLS_RSA_GEN_KEY_MIN_BITS + 4 + 7) / 8:"RSA"
+PK utils: RSA 1028-bits
+depends_on:MBEDTLS_RSA_C
+pk_utils:MBEDTLS_PK_RSA:1028:1028:(1028 + 7) / 8:"RSA"
 
-PK utils: RSA Minimum key + 6 bits
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_utils:MBEDTLS_PK_RSA:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 6:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 6:(MBEDTLS_RSA_GEN_KEY_MIN_BITS + 6 + 7) / 8:"RSA"
+PK utils: RSA 1030-bits
+depends_on:MBEDTLS_RSA_C
+pk_utils:MBEDTLS_PK_RSA:1030:1030:(1030 + 7) / 8:"RSA"
 
 PK utils: ECKEY SECP192R1
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_ECP_HAVE_SECP192R1
@@ -63,7 +63,7 @@
 pk_psa_utils:0
 
 PK PSA utilities: RSA setup/free, info functions, unsupported operations
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_psa_utils:1
 
 PK can do ext: ECDSA(ANY)/NONE, invalid check STREAM_CIPHER
@@ -159,147 +159,147 @@
 pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_DERIVE|PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):256:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_DERIVE:1
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, check not allowed COPY usage
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_COPY:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, invalid check STREAM_CIPHER
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_STREAM_CIPHER:PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, invalid check ECDSA(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, invalid check ECDH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_ECDH:PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, invalid check RSA_PKCS1V15_CRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, invalid check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, check non-present usage
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_DERIVE:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(SHA256)/NONE, check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: NONE, RSA_PKCS1V15_SIGN(ANY), check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: NONE, RSA_PKCS1V15_SIGN(SHA256), check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: RSA_PKCS1V15_SIGN(SHA256)/NONE, invalid check RSA_PKCS1V15_SIGN(ANY)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(SHA1)/NONE, invalid check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_1):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PSS(ANY)/NONE, invalid check STREAM_CIPHER
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_STREAM_CIPHER:PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PSS(ANY)/NONE, invalid check ECDSA(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PSS(ANY)/NONE, invalid check RSA_PKCS1V15_CRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PSS(ANY)/NONE, invalid check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PSS(ANY)/NONE, check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: RSA_PSS(SHA256)/NONE, check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: NONE, RSA_PSS(ANY), check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: NONE, RSA_PSS(SHA256), check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: RSA_PSS(SHA256)/NONE, invalid check RSA_PSS(ANY)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PSS(SHA1)/NONE, invalid check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_SHA_1):PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PKCS1V15_SIGN_RAW/NONE, check RSA_PKCS1V15_SIGN_RAW
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: RSA_PKCS1V15_SIGN_RAW/NONE, invalid check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PKCS1V15_CRYPT/NONE, invalid check STREAM_CIPHER
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_STREAM_CIPHER:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:0
 
 PK can do ext: RSA_PKCS1V15_CRYPT/NONE, invalid check ECDSA(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:0
 
 PK can do ext: RSA_PKCS1V15_CRYPT/NONE, invalid check ECDH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_ECDH:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:0
 
 PK can do ext: RSA_PKCS1V15_CRYPT/NONE, invalid check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:0
 
 PK can do ext: RSA_PKCS1V15_CRYPT/NONE, invalid check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:0
 
 PK can do ext: RSA_PKCS1V15_CRYPT/NONE, check RSA_PKCS1V15_CRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:1
 
 PK can do ext: RSA_PKCS1V15_CRYPT/RSA_PSS(ANY), check RSA_PKCS1V15_CRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT|PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:1
 
 PK can do ext: RSA_PKCS1V15_CRYPT/RSA_PSS(ANY), check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT|PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_DECRYPT:1
 
 PK can do ext: RSA_PKCS1V15_CRYPT/RSA_PSS(ANY), check non allowed ENCRYPT usage
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT|PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_ENCRYPT:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/RSA_PSS(ANY), check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/RSA_PSS(ANY), check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: MBEDTLS_PK_ECKEY, check ECDSA(SHA256)
@@ -311,19 +311,19 @@
 pk_can_do_ext:0:MBEDTLS_PK_ECKEY:0:0:0:MBEDTLS_ECP_DP_SECP256R1:PSA_ALG_ECDH:PSA_KEY_USAGE_DERIVE:1
 
 PK can do ext: MBEDTLS_PK_RSA, check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:0:MBEDTLS_PK_RSA:0:0:0:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: MBEDTLS_PK_RSA, check PSA_ALG_RSA_PKCS1V15_CRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:0:MBEDTLS_PK_RSA:0:0:0:1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:1
 
 PK can do ext: MBEDTLS_PK_RSA, check invalid PSA_KEY_USAGE_ENCRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:0:MBEDTLS_PK_RSA:0:0:0:1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_ENCRYPT:0
 
 PK can do ext: MBEDTLS_PK_RSA, check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:0:MBEDTLS_PK_RSA:0:0:0:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 RSA verify test vector: PKCS1v1.5 (explicit), SHA1, good
@@ -435,20 +435,20 @@
 pk_sign_verify:MBEDTLS_PK_ECKEY_DH:MBEDTLS_ECP_DP_SECP192R1:0:0:MBEDTLS_ERR_PK_TYPE_MISMATCH:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 RSA sign-verify, PKCS1v1.5, SHA1
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_GENPRIME:MBEDTLS_RSA_GEN_KEY_MIN_BITS >= 512:MBEDTLS_MD_CAN_SHA1
-pk_sign_verify:MBEDTLS_PK_RSA:MBEDTLS_RSA_GEN_KEY_MIN_BITS:MBEDTLS_RSA_PKCS_V15:MBEDTLS_MD_SHA1:0:0
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA1
+pk_sign_verify:MBEDTLS_PK_RSA:RSA_KEY_SIZE:MBEDTLS_RSA_PKCS_V15:MBEDTLS_MD_SHA1:0:0
 
 RSA sign-verify, PKCS1v2.1, SHA1
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_GENPRIME:MBEDTLS_RSA_GEN_KEY_MIN_BITS >= 512:MBEDTLS_MD_CAN_SHA1
-pk_sign_verify:MBEDTLS_PK_RSA:MBEDTLS_RSA_GEN_KEY_MIN_BITS:MBEDTLS_RSA_PKCS_V21:MBEDTLS_MD_SHA1:0:0
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA1
+pk_sign_verify:MBEDTLS_PK_RSA:RSA_KEY_SIZE:MBEDTLS_RSA_PKCS_V21:MBEDTLS_MD_SHA1:0:0
 
 RSA sign-verify, PKCS1v1.5, SHA256
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_GENPRIME:MBEDTLS_RSA_GEN_KEY_MIN_BITS >= 512:MBEDTLS_MD_CAN_SHA256
-pk_sign_verify:MBEDTLS_PK_RSA:MBEDTLS_RSA_GEN_KEY_MIN_BITS:MBEDTLS_RSA_PKCS_V15:MBEDTLS_MD_SHA256:0:0
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA256
+pk_sign_verify:MBEDTLS_PK_RSA:RSA_KEY_SIZE:MBEDTLS_RSA_PKCS_V15:MBEDTLS_MD_SHA256:0:0
 
 RSA sign-verify, PKCS1v2.1, SHA256
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_GENPRIME:MBEDTLS_RSA_GEN_KEY_MIN_BITS >= 512:MBEDTLS_MD_CAN_SHA256
-pk_sign_verify:MBEDTLS_PK_RSA:MBEDTLS_RSA_GEN_KEY_MIN_BITS:MBEDTLS_RSA_PKCS_V21:MBEDTLS_MD_SHA256:0:0
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256
+pk_sign_verify:MBEDTLS_PK_RSA:RSA_KEY_SIZE:MBEDTLS_RSA_PKCS_V21:MBEDTLS_MD_SHA256:0:0
 
 RSA encrypt-decrypt test PKCS1 v1.5
 depends_on:MBEDTLS_PKCS1_V15
@@ -507,7 +507,7 @@
 pk_ec_nocrypt:MBEDTLS_PK_ECDSA
 
 RSA_ALT consistency
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_GENPRIME:MBEDTLS_RSA_GEN_KEY_MIN_BITS >= 512
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_rsa_alt:
 
 Verify ext RSA #1 (PKCS1 v2.1, salt_len = ANY, OK)
@@ -688,35 +688,35 @@
 pk_psa_sign:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):512:0
 
 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
 pk_psa_sign:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:MBEDTLS_RSA_PKCS_V15
 
 PSA wrapped sign: RSA PKCS1 v2.1
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21
 pk_psa_sign:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:MBEDTLS_RSA_PKCS_V21
 
 PK sign ext: RSA2048, PK_RSA, MD_SHA256
-depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C:MBEDTLS_RSA_GEN_KEY_MIN_BITS <= 2048
+depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C
 pk_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSA:MBEDTLS_MD_SHA256
 
 PK sign ext: RSA2048, PK_RSASSA_PSS, MD_SHA256
-depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C:MBEDTLS_RSA_GEN_KEY_MIN_BITS <= 2048
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C
 pk_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA256
 
 PK sign ext: RSA2048, PK_RSA, MD_SHA384
-depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA384:MBEDTLS_RSA_C:MBEDTLS_RSA_GEN_KEY_MIN_BITS <= 2048
+depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA384:MBEDTLS_RSA_C
 pk_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSA:MBEDTLS_MD_SHA384
 
 PK sign ext: RSA2048, PK_RSASSA_PSS, MD_SHA384
-depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA384:MBEDTLS_RSA_C:MBEDTLS_RSA_GEN_KEY_MIN_BITS <= 2048
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA384:MBEDTLS_RSA_C
 pk_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA384
 
 PK sign ext: RSA2048, PK_RSA, MD_SHA512
-depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA512:MBEDTLS_RSA_C:MBEDTLS_RSA_GEN_KEY_MIN_BITS <= 2048
+depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA512:MBEDTLS_RSA_C
 pk_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSA:MBEDTLS_MD_SHA512
 
 PK sign ext: RSA2048, PK_RSASSA_PSS, MD_SHA512
-depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512:MBEDTLS_RSA_C:MBEDTLS_RSA_GEN_KEY_MIN_BITS <= 2048
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512:MBEDTLS_RSA_C
 pk_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA512
 
 PK sign ext: SECP256R1, PK_ECDSA, MD_SHA256
@@ -762,136 +762,136 @@
 
 # Bad usage due to not specifying sign/crypt/derive.
 PSA attributes for pk: RSA usage=0 (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PAIR:0:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 # Bad usage due to not specifying sign/crypt/derive.
 PSA attributes for pk: RSA usage=EXPORT (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_EXPORT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 # This usage could make sense, but is not currently supported.
 PSA attributes for pk: RSA usage=DECRYPT|EXPORT (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 # Bad usage due to specifying more than one of sign/crypt/derive.
 PSA attributes for pk: RSA usage=DECRYPT|SIGN_MESSAGE (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 # This usage could make sense, but is not currently supported.
 PSA attributes for pk: RSA usage=SIGN_MESSAGE|SIGN_HASH (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 # This usage could make sense, but is not currently supported.
 PSA attributes for pk: RSA usage=SIGN_MESSAGE|VERIFY_MESSAGE (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: RSA v15 pair DECRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_DECRYPT:1:PSA_ALG_RSA_PKCS1V15_CRYPT
 
 PSA attributes for pk: RSA v21 SHA-256 pair DECRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA256:FROM_PAIR:PSA_KEY_USAGE_DECRYPT:1:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256)
 
 PSA attributes for pk: RSA v21 SHA-512 pair DECRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA512:FROM_PAIR:PSA_KEY_USAGE_DECRYPT:1:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_512)
 
 PSA attributes for pk: RSA v15 pair->public ENCRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_PKCS1V15_CRYPT
 
 PSA attributes for pk: RSA v21 SHA-256 pair->public ENCRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA256:FROM_PAIR:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256)
 
 PSA attributes for pk: RSA v21 SHA-512 pair->public ENCRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA512:FROM_PAIR:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_512)
 
 PSA attributes for pk: RSA v15 public ENCRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_PKCS1V15_CRYPT
 
 PSA attributes for pk: RSA v21 SHA-256 public ENCRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA256:FROM_PUBLIC:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256)
 
 PSA attributes for pk: RSA v21 SHA-512 public ENCRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA512:FROM_PUBLIC:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_512)
 
 PSA attributes for pk: RSA v15 public DECRYPT (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: RSA v15 pair SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_SIGN_MESSAGE:1:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v21 SHA-256 pair SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:FROM_PAIR:PSA_KEY_USAGE_SIGN_MESSAGE:1:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v15 pair SIGN_HASH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_SIGN_HASH:1:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v21 SHA-256 pair SIGN_HASH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:FROM_PAIR:PSA_KEY_USAGE_SIGN_HASH:1:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v15 pair->public VERIFY_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v21 SHA-256 pair->public VERIFY_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:FROM_PAIR:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v15 pair->public VERIFY_HASH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v21 SHA-256 pair->public VERIFY_HASH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:FROM_PAIR:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v15 public VERIFY_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v21 SHA-256 public VERIFY_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:FROM_PUBLIC:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v15 public VERIFY_HASH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v21 SHA-256 public VERIFY_HASH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:FROM_PUBLIC:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v15 public SIGN_MESSAGE (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: RSA v15 public SIGN_HASH (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: RSA v15 pair DERIVE (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: RSA v15 public DERIVE (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY pair DECRYPT (bad)
@@ -1063,164 +1063,164 @@
 pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:FROM_PUBLIC:PSA_KEY_USAGE_VERIFY_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: opaque RSA pair, 0 & SIGN_MESSAGE (bad policy)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:0:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:0:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
 
 PSA attributes for pk: opaque RSA pair, SIGN_MESSAGE & SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE
 
 PSA attributes for pk: opaque RSA pair, SIGN|VERIFY & SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA attributes for pk: opaque RSA pair, SIGN|DECRYPT & SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_DECRYPT
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_DECRYPT
 
 # For a PK_OPAQUE key with a key pair type output,
 # mbedtls_pk_import_into_psa() requires the key to be copyable or exportable.
 # Try all combinations of COPY/not, EXPORT/not.
 PSA attributes for pk: opaque RSA pair, SIGN|... & SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
 
 PSA attributes for pk: opaque RSA pair, SIGN|EXPORT|... & SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
 
 PSA attributes for pk: opaque RSA pair, SIGN|COPY|... & SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
 
 PSA attributes for pk: opaque RSA pair, SIGN|COPY|EXPORT... & SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
 
 PSA attributes for pk: opaque RSA pair, SIGN_MESSAGE & SIGN_HASH (bad policy)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
 
 # For a PK_OPAQUE key, mbedtls_pk_get_psa_attributes() ignores the input
 # key's algorithm policy. Just this time, test with a few different algorithms.
 PSA attributes for pk: opaque RSA pair, SIGN_HASH & SIGN_HASH [0]
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
 
 PSA attributes for pk: opaque RSA pair, SIGN_HASH & SIGN_HASH [raw]
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
 
 PSA attributes for pk: opaque RSA pair, SIGN_HASH & SIGN_HASH [v15]
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
 
 PSA attributes for pk: opaque RSA pair, SIGN_HASH & SIGN_HASH [PSS]
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
 
 PSA attributes for pk: opaque RSA pair, 0 & DECRYPT (bad policy)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:0:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:0:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
 
 PSA attributes for pk: opaque RSA pair, DECRYPT & DECRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:0:1:PSA_KEY_USAGE_DECRYPT
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:0:1:PSA_KEY_USAGE_DECRYPT
 
 PSA attributes for pk: opaque RSA pair, DECRYPT|... & DECRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
 
 PSA attributes for pk: opaque RSA pair, ... & DERIVE (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
 
 PSA attributes for pk: opaque RSA pair, ... & EXPORT (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_EXPORT:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_EXPORT:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
 
 PSA attributes for pk: opaque RSA pair->public, VERIFY_MESSAGE & VERIFY_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_VERIFY_MESSAGE:0:0:PSA_KEY_USAGE_VERIFY_MESSAGE
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_VERIFY_MESSAGE:0:0:PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA attributes for pk: opaque RSA pair->public, VERIFY_HASH & VERIFY_HASH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_VERIFY_HASH:0:0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_VERIFY_HASH:0:0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA attributes for pk: opaque RSA pair->public, ENCRYPT & ENCRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_ENCRYPT:0:0:PSA_KEY_USAGE_ENCRYPT
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_ENCRYPT:0:0:PSA_KEY_USAGE_ENCRYPT
 
 PSA attributes for pk: opaque ECC pair, 0 & SIGN_MESSAGE (bad policy)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:0:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
 
 PSA attributes for pk: opaque ECC pair, SIGN_MESSAGE & SIGN_MESSAGE
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE
 
 PSA attributes for pk: opaque ECC pair, SIGN|VERIFY & SIGN_MESSAGE
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA attributes for pk: opaque ECC pair, SIGN|DECRYPT & SIGN_MESSAGE
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_DECRYPT:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_DECRYPT
 
 PSA attributes for pk: opaque ECC pair, SIGN|... & SIGN_MESSAGE
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
 
 PSA attributes for pk: opaque ECC pair, SIGN_HASH & SIGN_HASH
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
 
 PSA attributes for pk: opaque ECC pair, ... & DERIVE
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_KEY_USAGE_DERIVE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DERIVE
 
 PSA attributes for pk: opaque ECC pair, ... & DECRYPT (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
 
 PSA attributes for pk: opaque ECC pair, ... & EXPORT (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_ECDH:PSA_KEY_USAGE_EXPORT:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
 
 PSA attributes for pk: opaque ECC pair->public, VERIFY_MESSAGE & VERIFY_MESSAGE
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_VERIFY_MESSAGE:0:0:PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA attributes for pk: opaque ECC pair->public, VERIFY_HASH & VERIFY_HASH
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_VERIFY_HASH:0:0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA attributes for pk: opaque ECC pair->public, ENCRYPT & ENCRYPT (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_ENCRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH:0:0
 
 PSA import into PSA: RSA pair to ECC (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_import_into_psa_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):0:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA import into PSA: RSA public to RSA pair (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_import_into_psa_fail:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_TYPE_RSA_KEY_PAIR:0:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
 
 # MBEDTLS_ERR_PK_INVALID_ALG is the error that results from our translation
 # of PSA errors. In this case MBEDTLS_ERR_PK_TYPE_MISMATCH would probably
 # be more appropriate. (Applies to all the RSA "different bits" test cases.)
 PSA import into PSA: RSA pair to different bits (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_import_into_psa_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 8:MBEDTLS_ERR_PK_INVALID_ALG
+depends_on:MBEDTLS_RSA_C
+pk_import_into_psa_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE + 8:MBEDTLS_ERR_PK_INVALID_ALG
 
 PSA import into PSA: RSA public to different bits (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_import_into_psa_fail:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 8:MBEDTLS_ERR_PK_INVALID_ALG
+depends_on:MBEDTLS_RSA_C
+pk_import_into_psa_fail:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_TYPE_RSA_PUBLIC_KEY:RSA_KEY_SIZE + 8:MBEDTLS_ERR_PK_INVALID_ALG
 
 PSA import into PSA: RSA private to public, different bits (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_import_into_psa_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 8:MBEDTLS_ERR_PK_INVALID_ALG
+depends_on:MBEDTLS_RSA_C
+pk_import_into_psa_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_TYPE_RSA_PUBLIC_KEY:RSA_KEY_SIZE + 8:MBEDTLS_ERR_PK_INVALID_ALG
 
 PSA import into PSA: ECKEY pair to RSA (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
@@ -1395,149 +1395,149 @@
 pk_import_into_psa_lifetime:1:1:0:1:1
 
 PSA import into PSA: opaque RSA, COPY (ok)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
 
 PSA import into PSA: opaque RSA, EXPORT (ok)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
 
 PSA import into PSA: opaque RSA, no COPY/EXPORT (bad)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:MBEDTLS_ERR_PK_TYPE_MISMATCH
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 # Detail that isn't precisely documented: since this copies the key,
 # the new key has the intersection of the usage flags.
 PSA import into PSA: opaque RSA, COPY|EXPORT, different usage (restricted)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
 
 # Detail that isn't precisely documented: since this copies the key,
 # the new key has the intersection of the usage flags.
 PSA import into PSA: opaque RSA, COPY, different usage (restricted)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
 
 # Detail that isn't precisely documented: since this exports the key,
 # the new key has all the requested usage flags.
 PSA import into PSA: opaque RSA, EXPORT, different usage (ok)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
 
 PSA import into PSA: opaque RSA, COPY|EXPORT, different algorithm (ok)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
 
 PSA import into PSA: opaque RSA, COPY, different algorithm (bad)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):MBEDTLS_ERR_PK_TYPE_MISMATCH
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA import into PSA: opaque RSA, EXPORT, different algorithm (ok)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
 
 PSA import into PSA: opaque RSA, implicit bits (ok)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
 
 PSA import into PSA: opaque RSA, different bits (bad)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 8:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:MBEDTLS_ERR_PK_TYPE_MISMATCH
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE + 8:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA import into PSA: opaque RSA, different type (bad)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:PSA_KEY_TYPE_HMAC:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:PSA_KEY_TYPE_HMAC:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA import into PSA: opaque RSA to public (ok)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_PUBLIC_KEY:RSA_KEY_SIZE:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
 
 PSA import into PSA: opaque RSA to public, implicit bits (ok)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_PUBLIC_KEY:0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_PUBLIC_KEY:0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
 
 # MBEDTLS_ERR_PK_INVALID_ALG is the error that results from our translation
 # of PSA errors. In this case MBEDTLS_ERR_PK_TYPE_MISMATCH would probably
 # be more appropriate.
 PSA import into PSA: opaque RSA to public, different bits (bad)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 8:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:MBEDTLS_ERR_PK_INVALID_ALG
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_PUBLIC_KEY:RSA_KEY_SIZE + 8:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:MBEDTLS_ERR_PK_INVALID_ALG
 
 PSA import into PSA: opaque ECC, COPY (ok)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0
 
 PSA import into PSA: opaque ECC, EXPORT (ok)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0
 
 PSA import into PSA: opaque ECC, no COPY/EXPORT (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 # Detail that isn't precisely documented: since this copies the key,
 # the new key has the intersection of the usage flags.
 PSA import into PSA: opaque ECC, COPY|EXPORT, different usage (restricted)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0
 
 # Detail that isn't precisely documented: since this copies the key,
 # the new key has the intersection of the usage flags.
 PSA import into PSA: opaque ECC, COPY, different usage (restricted)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0
 
 # Detail that isn't precisely documented: since this exports the key,
 # the new key has all the requested usage flags.
 PSA import into PSA: opaque ECC, EXPORT, different usage (ok)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0
 
 PSA import into PSA: opaque ECC, COPY|EXPORT, different algorithm (ok)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0
 
 PSA import into PSA: opaque ECC, COPY, different algorithm (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA import into PSA: opaque ECC, EXPORT, different algorithm (ok)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0
 
 PSA import into PSA: opaque ECC, implicit bits (ok)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0
 
 PSA import into PSA: opaque ECC, different bits (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS + 8:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA import into PSA: opaque ECC, different type (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:PSA_KEY_TYPE_HMAC:MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA import into PSA: opaque ECC, different family (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ANOTHER_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA import into PSA: opaque ECC to public (ok)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0
 
 PSA import into PSA: opaque ECC to public, implicit bits (ok)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0
 
 # MBEDTLS_ERR_PK_INVALID_ALG is the error that results from our translation
 # of PSA errors. In this case MBEDTLS_ERR_PK_TYPE_MISMATCH would probably
 # be more appropriate.
 PSA import into PSA: opaque ECC to public, different bits (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS + 8:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):MBEDTLS_ERR_PK_INVALID_ALG
 
 PSA import into PSA: opaque ECC to public, different family (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ANOTHER_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 Copy from PSA: use wrong parameters
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index 442a362..23f5cda 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -21,17 +21,13 @@
 #include "psa/crypto.h"
 #include "mbedtls/psa_util.h"
 
+#include "pkwrite.h"
+
 #include <test/psa_exercise_key.h>
 
 /* Needed for the definition of MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE. */
 #include "pkwrite.h"
 
-/* Used for properly sizing the key buffer in pk_genkey_ec() */
-#include "psa_util_internal.h"
-
-#define RSA_KEY_SIZE   MBEDTLS_RSA_GEN_KEY_MIN_BITS
-#define RSA_KEY_LEN   (MBEDTLS_RSA_GEN_KEY_MIN_BITS/8)
-
 #if defined(MBEDTLS_RSA_C) ||                                           \
     defined(MBEDTLS_PK_RSA_ALT_SUPPORT) ||                              \
     defined(MBEDTLS_ECDSA_C) ||                                         \
@@ -44,8 +40,7 @@
  * - The build has built-in ECC and ECDSA signature.
  */
 #if (defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_PK_WRITE_C) && \
-    ((defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME)) || \
-    defined(MBEDTLS_PK_CAN_ECDSA_SIGN))) || \
+    (defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_CAN_ECDSA_SIGN))) || \
     (defined(MBEDTLS_ECP_C) && defined(MBEDTLS_PK_CAN_ECDSA_SIGN))
 #define MBEDTLS_TEST_PK_PSA_SIGN
 #endif
@@ -185,123 +180,190 @@
 #define MBEDTLS_MD_ALG_FOR_TEST         MBEDTLS_MD_SHA512
 #endif
 
-#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
-static int pk_genkey_ec(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id)
+#include <../src/test_keys.h>
+
+/* Define an RSA key size we know it's present in predefined_key[] array. */
+#define RSA_KEY_SIZE   1024
+#define RSA_KEY_LEN   (RSA_KEY_SIZE/8)
+
+static int get_predefined_key_data(int is_ec, int group_id_or_keybits,
+                                   const unsigned char **key, size_t *key_len,
+                                   const unsigned char **pub_key, size_t *pub_key_len)
 {
-    psa_status_t status;
-    psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
-    size_t curve_bits;
-    psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(grp_id, &curve_bits);
-    int ret;
+    size_t i;
+    struct predefined_key_element *predefined_key = NULL;
 
-    if (curve == 0) {
-        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-    }
-
-    psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
-    psa_set_key_bits(&key_attr, curve_bits);
-    psa_key_usage_t usage = PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY;
-    psa_algorithm_t sign_alg = 0;
-    psa_algorithm_t derive_alg = 0;
-    if (mbedtls_pk_get_type(pk) != MBEDTLS_PK_ECDSA) {
-        usage |= PSA_KEY_USAGE_DERIVE;
-        derive_alg = PSA_ALG_ECDH;
-    }
-    if (mbedtls_pk_get_type(pk) != MBEDTLS_PK_ECKEY_DH &&
-        curve != PSA_ECC_FAMILY_MONTGOMERY) {
-        usage |= PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE;
-#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
-        sign_alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH);
-#else
-        sign_alg = PSA_ALG_ECDSA(PSA_ALG_ANY_HASH);
-#endif
-    }
-    if (derive_alg != 0) {
-        psa_set_key_algorithm(&key_attr, derive_alg);
-        if (sign_alg != 0) {
-            psa_set_key_enrollment_algorithm(&key_attr, sign_alg);
+    for (i = 0; i < ARRAY_LENGTH(predefined_keys); i++) {
+        if (is_ec) {
+            if (group_id_or_keybits == predefined_keys[i].group_id) {
+                predefined_key = &predefined_keys[i];
+            }
+        } else if (group_id_or_keybits == predefined_keys[i].keybits) {
+            predefined_key = &predefined_keys[i];
         }
-    } else {
-        psa_set_key_algorithm(&key_attr, sign_alg);
-    }
-    psa_set_key_usage_flags(&key_attr, usage);
-
-    status = psa_generate_key(&key_attr, &pk->priv_id);
-    if (status != PSA_SUCCESS) {
-        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
     }
 
-    status = psa_export_public_key(pk->priv_id, pk->pub_raw, sizeof(pk->pub_raw),
-                                   &pk->pub_raw_len);
-    if (status != PSA_SUCCESS) {
-        ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
-        goto exit;
-    }
-
-    pk->ec_family = curve;
-    pk->ec_bits = curve_bits;
-
-    return 0;
-
-exit:
-    status = psa_destroy_key(pk->priv_id);
-    return (ret != 0) ? ret : psa_pk_status_to_mbedtls(status);
-}
-#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
-
-/** Generate a key of the desired type.
- *
- * \param pk               The PK object to fill. It must have been initialized
- *                         with mbedtls_pk_setup().
- * \param curve_or_keybits - For RSA keys, the key size in bits.
- *                         - For EC keys, the curve (\c MBEDTLS_ECP_DP_xxx).
- *
- * \return                 The status from the underlying type-specific key
- *                         generation function.
- * \return                 -1 if the key type is not recognized.
- */
-static int pk_genkey(mbedtls_pk_context *pk, int curve_or_keybits)
-{
-    (void) pk;
-    (void) curve_or_keybits;
-
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME)
-    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA) {
-        return mbedtls_rsa_gen_key(mbedtls_pk_rsa(*pk),
-                                   mbedtls_test_rnd_std_rand, NULL,
-                                   curve_or_keybits, 3);
-    }
-#endif
-#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
-    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECKEY ||
-        mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECKEY_DH ||
-        mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECDSA) {
-        int ret;
-
-#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
-        ret = pk_genkey_ec(pk, curve_or_keybits);
-        if (ret != 0) {
-            return ret;
+    if (predefined_key != NULL) {
+        *key = predefined_key->priv_key;
+        *key_len = predefined_key->priv_key_len;
+        if (pub_key != NULL) {
+            *pub_key = predefined_key->pub_key;
+            *pub_key_len = predefined_key->pub_key_len;
         }
-
         return 0;
-#else
-        ret = mbedtls_ecp_group_load(&mbedtls_pk_ec_rw(*pk)->grp, curve_or_keybits);
-        if (ret != 0) {
-            return ret;
-        }
-        return mbedtls_ecp_gen_keypair(&mbedtls_pk_ec_rw(*pk)->grp,
-                                       &mbedtls_pk_ec_rw(*pk)->d,
-                                       &mbedtls_pk_ec_rw(*pk)->Q,
-                                       mbedtls_test_rnd_std_rand, NULL);
-#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
-
     }
-#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
-    return -1;
+
+    TEST_FAIL("Unsupported key");
+    /* "exit" label is to make the compiler happy. */
+exit:
+    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
 }
 
 #if defined(MBEDTLS_PSA_CRYPTO_C)
+psa_status_t pk_psa_import_key(const unsigned char *key_data, size_t key_len,
+                               psa_key_type_t type, psa_key_usage_t usage,
+                               psa_algorithm_t alg, mbedtls_svc_key_id_t *key)
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status;
+
+    *key = MBEDTLS_SVC_KEY_ID_INIT;
+
+    /* Note: psa_import_key() automatically determines the key's bit length
+     * from the provided key data. That's why psa_set_key_bits() is not used below. */
+    psa_set_key_usage_flags(&attributes, usage);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_type(&attributes, type);
+    status = psa_import_key(&attributes, key_data, key_len, key);
+
+    return status;
+}
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
+/** Setup the provided PK context.
+ *
+ * Predefined keys used for the setup are taken from "test/src/test_keys.h"
+ * which is automatically generated using "framework/scripts/generate_test_keys.py".
+ *
+ * \param pk               The PK object to fill. It must  have been initialized
+ *                         (mbedtls_pk_init()), but not setup (mbedtls_pk_setup()).
+ * \param pk_type          mbedtls_pk_type_t to use in the PK context.
+ * \param curve_or_keybits - For RSA keys, the key size in bits.
+ *                         - For EC keys, the curve (\c MBEDTLS_ECP_DP_xxx).
+ *
+ * \return                 0 on success or a negative value otherwise.
+ */
+static int pk_setup(mbedtls_pk_context *pk, mbedtls_pk_type_t pk_type, int curve_or_keybits)
+{
+    const unsigned char *key_data = NULL;
+    const unsigned char *pub_key_data = NULL;
+    size_t key_data_len = 0;
+    size_t pub_key_data_len = 0;
+    int ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+
+    TEST_EQUAL(mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(pk_type)), 0);
+
+    if (pk_type == MBEDTLS_PK_RSA) {
+#if defined(MBEDTLS_RSA_C)
+        TEST_EQUAL(get_predefined_key_data(0, curve_or_keybits, &key_data, &key_data_len,
+                                           NULL, 0), 0);
+        TEST_EQUAL(mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), key_data, key_data_len), 0);
+#else /* MBEDTLS_RSA_C */
+        TEST_FAIL("RSA keys not supported.");
+#endif /* MBEDTLS_RSA_C */
+    } else {
+        TEST_EQUAL(get_predefined_key_data(1, curve_or_keybits, &key_data, &key_data_len,
+                                           &pub_key_data, &pub_key_data_len), 0);
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+        pk->ec_family = mbedtls_ecc_group_to_psa(curve_or_keybits, &pk->ec_bits);
+        TEST_EQUAL(pk_psa_import_key(key_data, key_data_len,
+                                     PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family),
+                                     PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH |
+                                     PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE |
+                                     PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_COPY |
+                                     PSA_KEY_USAGE_EXPORT,
+                                     MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(PSA_ALG_ANY_HASH),
+                                     &pk->priv_id), 0);
+        memcpy(pk->pub_raw, pub_key_data, pub_key_data_len);
+        pk->pub_raw_len = pub_key_data_len;
+#elif defined(MBEDTLS_ECP_C)
+        TEST_EQUAL(mbedtls_ecp_read_key(curve_or_keybits, mbedtls_pk_ec_rw(*pk),
+                                        key_data, key_data_len), 0);
+        TEST_EQUAL(mbedtls_ecp_point_read_binary(&(mbedtls_pk_ec_rw(*pk)->grp),
+                                                 &(mbedtls_pk_ec_rw(*pk)->Q),
+                                                 pub_key_data, pub_key_data_len), 0);
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_ECP_C */
+        TEST_FAIL("EC keys not supported.");
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_ECP_C */
+    }
+    /* Override pk_info. */
+    pk->pk_info = mbedtls_pk_info_from_type(pk_type);
+    ret = 0;
+
+exit:
+    return ret;
+}
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+/** Create a PSA key of the desired type and properties.
+ *
+ * - For RSA and EC keys predefined key data is used (as in the pk_setup() above).
+ * - Other key types (ex: DH) are generated at runtime.
+ *
+ * \param type                  PSA key type.
+ * \param bits                  PSA key bit size.
+ * \param usage                 PSA key usage flags.
+ * \param alg                   PSA key primary algorithm.
+ * \param enrollment_alg        PSA key enrollment algorithm.
+ * \param persistent_key_id     PSA key ID for persistent keys. Set to PSA_KEY_ID_NULL
+ *                              for volatile keys.
+ * \param[out] key              Identifier of the "generated" (actually imported) PSA key.
+ */
+psa_status_t pk_psa_setup(psa_key_type_t type, size_t bits,
+                          psa_key_usage_t usage, psa_algorithm_t alg,
+                          psa_algorithm_t enrollment_alg,
+                          mbedtls_svc_key_id_t persistent_key_id,
+                          mbedtls_svc_key_id_t *key)
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    const unsigned char *key_data = NULL;
+    size_t key_data_size = 0;
+
+    *key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_set_key_usage_flags(&attributes, usage);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_enrollment_algorithm(&attributes, enrollment_alg);
+    psa_set_key_type(&attributes, type);
+    psa_set_key_bits(&attributes, bits);
+    if (!mbedtls_svc_key_id_is_null(persistent_key_id)) {
+        psa_set_key_id(&attributes, persistent_key_id);
+    }
+
+    /* For EC and RSA keys we use predefined keys in order to:
+     * - speed up testing and
+     * - ease requirements/dependencies on test cases.
+     * For other keys (ex: DH) psa_generate_key() is used instead. */
+    if (PSA_KEY_TYPE_IS_RSA(type)) {
+        TEST_EQUAL(get_predefined_key_data(0, bits, &key_data, &key_data_size, NULL, 0), 0);
+    } else if (PSA_KEY_TYPE_IS_ECC(type)) {
+#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
+        mbedtls_ecp_group_id grp_id;
+        grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(type), bits);
+        TEST_EQUAL(get_predefined_key_data(1, grp_id, &key_data, &key_data_size, NULL, 0), 0);
+#else /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
+        TEST_FAIL("EC keys are not supported");
+#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
+    } else {
+        return psa_generate_key(&attributes, key);
+    }
+
+    status = psa_import_key(&attributes, key_data, key_data_size, key);
+
+exit:
+    return status;
+}
+
 static psa_key_usage_t pk_get_psa_attributes_implied_usage(
     psa_key_usage_t expected_usage)
 {
@@ -443,32 +505,18 @@
     if (pk_type == MBEDTLS_PK_NONE) {
         return 0;
     }
-    TEST_EQUAL(mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(pk_type)), 0);
 
     switch (pk_type) {
 #if defined(MBEDTLS_RSA_C)
         case MBEDTLS_PK_RSA:
         {
             *psa_type = PSA_KEY_TYPE_RSA_KEY_PAIR;
-            mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
-            if (want_pair) {
-#if defined(MBEDTLS_GENPRIME)
-                TEST_EQUAL(mbedtls_rsa_gen_key(
-                               rsa,
-                               mbedtls_test_rnd_std_rand, NULL,
-                               MBEDTLS_RSA_GEN_KEY_MIN_BITS, 65537), 0);
-#else
-                TEST_FAIL("I don't know how to create an RSA key pair in this configuration.");
-#endif
-            } else {
-                unsigned char N[PSA_BITS_TO_BYTES(MBEDTLS_RSA_GEN_KEY_MIN_BITS)] = { 0xff };
-                N[sizeof(N) - 1] = 0x03;
-                const unsigned char E[1] = { 0x03 };
-                TEST_EQUAL(mbedtls_rsa_import_raw(rsa,
-                                                  N, sizeof(N),
-                                                  NULL, 0, NULL, 0, NULL, 0,
-                                                  E, sizeof(E)), 0);
-                TEST_EQUAL(mbedtls_rsa_complete(rsa), 0);
+            TEST_EQUAL(pk_setup(pk, pk_type, RSA_KEY_SIZE), 0);
+            if (!want_pair) {
+                mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
+                mbedtls_mpi_free(&rsa->D);
+                mbedtls_mpi_free(&rsa->P);
+                mbedtls_mpi_free(&rsa->Q);
             }
             break;
         }
@@ -482,7 +530,7 @@
             mbedtls_ecp_group_id grp_id = MBEDTLS_TEST_ECP_DP_ONE_CURVE;
             size_t bits;
             *psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR(mbedtls_ecc_group_to_psa(grp_id, &bits));
-            TEST_EQUAL(pk_genkey(pk, grp_id), 0);
+            TEST_EQUAL(pk_setup(pk, pk_type, grp_id), 0);
             if (!want_pair) {
 #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
                 psa_key_attributes_t pub_attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -518,7 +566,7 @@
 exit:
     return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
 }
-#endif
+#endif /* MBEDTLS_PSA_CRYPTO_C */
 
 #if defined(MBEDTLS_PSA_CRYPTO_C)
 /* Create a new PSA key which will contain only the public part of the private
@@ -587,73 +635,6 @@
     psa_reset_key_attributes(&new_attr);
     return new_key_id;
 }
-
-psa_status_t pk_psa_import_key(unsigned char *key_data, size_t key_len,
-                               psa_key_type_t type, psa_key_usage_t usage,
-                               psa_algorithm_t alg, mbedtls_svc_key_id_t *key)
-{
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_status_t status;
-
-    *key = MBEDTLS_SVC_KEY_ID_INIT;
-
-    /* Note: psa_import_key() automatically determines the key's bit length
-     * from the provided key data. That's why psa_set_key_bits() is not used below. */
-    psa_set_key_usage_flags(&attributes, usage);
-    psa_set_key_algorithm(&attributes, alg);
-    psa_set_key_type(&attributes, type);
-    status = psa_import_key(&attributes, key_data, key_len, key);
-
-    return status;
-}
-
-psa_status_t pk_psa_genkey_generic(psa_key_type_t type, size_t bits,
-                                   psa_key_usage_t usage, psa_algorithm_t alg,
-                                   mbedtls_svc_key_id_t *key)
-{
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_status_t status;
-
-    *key = MBEDTLS_SVC_KEY_ID_INIT;
-
-    psa_set_key_usage_flags(&attributes, usage);
-    psa_set_key_algorithm(&attributes, alg);
-    psa_set_key_type(&attributes, type);
-    psa_set_key_bits(&attributes, bits);
-    status = psa_generate_key(&attributes, key);
-
-    return status;
-}
-
-/*
- * Generate an ECC key using PSA and return the key identifier of that key,
- * or 0 if the key generation failed.
- * The key uses NIST P-256 and is usable for signing with SHA-256.
- */
-mbedtls_svc_key_id_t pk_psa_genkey_ecc(void)
-{
-    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
-
-    pk_psa_genkey_generic(PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1), 256,
-                          PSA_KEY_USAGE_SIGN_HASH, PSA_ALG_ECDSA(PSA_ALG_SHA_256),
-                          &key);
-
-    return key;
-}
-
-/*
- * Generate an RSA key using PSA and return the key identifier of that key,
- * or 0 if the key generation failed.
- */
-mbedtls_svc_key_id_t pk_psa_genkey_rsa(void)
-{
-    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
-
-    pk_psa_genkey_generic(PSA_KEY_TYPE_RSA_KEY_PAIR, 1024, PSA_KEY_USAGE_SIGN_HASH,
-                          PSA_ALG_RSA_PKCS1V15_SIGN_RAW, &key);
-
-    return key;
-}
 #endif /* MBEDTLS_PSA_CRYPTO_C */
 /* END_HEADER */
 
@@ -688,11 +669,15 @@
     mbedtls_pk_init(&pk);
 
     if (key_is_rsa) {
-        bitlen = 1024; /* hardcoded in genkey() */
-        key = pk_psa_genkey_rsa();
+        bitlen = 1024;
+        PSA_ASSERT(pk_psa_setup(PSA_KEY_TYPE_RSA_KEY_PAIR, 1024, PSA_KEY_USAGE_SIGN_HASH,
+                                PSA_ALG_RSA_PKCS1V15_SIGN_RAW, PSA_ALG_NONE,
+                                MBEDTLS_SVC_KEY_ID_INIT, &key));
     } else {
-        bitlen = 256; /* hardcoded in genkey() */
-        key = pk_psa_genkey_ecc();
+        bitlen = 256;
+        PSA_ASSERT(pk_psa_setup(PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1), 256,
+                                PSA_KEY_USAGE_SIGN_HASH, PSA_ALG_ECDSA(PSA_ALG_SHA_256),
+                                PSA_ALG_NONE, MBEDTLS_SVC_KEY_ID_INIT, &key));
     }
     if (mbedtls_svc_key_id_is_null(key)) {
         goto exit;
@@ -777,16 +762,8 @@
     USE_PSA_INIT();
 
     if (opaque_key == 1) {
-        psa_set_key_usage_flags(&attributes, key_usage);
-        psa_set_key_algorithm(&attributes, key_alg);
-        if (key_alg2 != 0) {
-            psa_set_key_enrollment_algorithm(&attributes, key_alg2);
-        }
-        psa_set_key_type(&attributes, key_type);
-        psa_set_key_bits(&attributes, curve_or_keybits);
-
-        PSA_ASSERT(psa_generate_key(&attributes, &key));
-
+        PSA_ASSERT(pk_psa_setup(key_type, curve_or_keybits, key_usage,
+                                key_alg, key_alg2, MBEDTLS_SVC_KEY_ID_INIT, &key));
         if (mbedtls_svc_key_id_is_null(key)) {
             goto exit;
         }
@@ -795,9 +772,7 @@
 
         TEST_EQUAL(mbedtls_pk_get_type(&pk), MBEDTLS_PK_OPAQUE);
     } else {
-        TEST_EQUAL(mbedtls_pk_setup(&pk,
-                                    mbedtls_pk_info_from_type(key_type)), 0);
-        TEST_EQUAL(pk_genkey(&pk, curve_or_keybits), 0);
+        TEST_EQUAL(pk_setup(&pk, key_type, curve_or_keybits), 0);
         TEST_EQUAL(mbedtls_pk_get_type(&pk), key_type);
     }
 
@@ -999,8 +974,7 @@
     mbedtls_pk_init(&pk);
     USE_PSA_INIT();
 
-    TEST_ASSERT(mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(type)) == 0);
-    TEST_ASSERT(pk_genkey(&pk, curve_or_keybits) == 0);
+    TEST_ASSERT(pk_setup(&pk, type, curve_or_keybits) == 0);
 
     TEST_ASSERT((int) mbedtls_pk_get_type(&pk) == type);
     TEST_ASSERT(mbedtls_pk_can_do(&pk, type));
@@ -1368,8 +1342,7 @@
     memset(hash, 0x2a, sizeof(hash));
     memset(sig, 0, sizeof(sig));
 
-    TEST_ASSERT(mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(type)) == 0);
-    TEST_ASSERT(pk_genkey(&pk, curve_or_keybits) == 0);
+    TEST_ASSERT(pk_setup(&pk, type, curve_or_keybits) == 0);
 
 #if defined(MBEDTLS_RSA_C)
     if (type == MBEDTLS_PK_RSA) {
@@ -1762,9 +1735,7 @@
     memset(test, 0, sizeof(test));
 
     /* Initialize PK RSA context with random key */
-    TEST_ASSERT(mbedtls_pk_setup(&rsa,
-                                 mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == 0);
-    TEST_ASSERT(pk_genkey(&rsa, RSA_KEY_SIZE) == 0);
+    TEST_ASSERT(pk_setup(&rsa, MBEDTLS_PK_RSA, RSA_KEY_SIZE) == 0);
 
     /* Extract key to the raw rsa context */
     TEST_ASSERT(mbedtls_rsa_copy(&raw, mbedtls_pk_rsa(rsa)) == 0);
@@ -1832,7 +1803,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_MD_CAN_SHA256:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_TEST_PK_PSA_SIGN */
+/* BEGIN_CASE depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_CAN_SHA256:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_TEST_PK_PSA_SIGN */
 void pk_psa_sign(int psa_type, int bits, int rsa_padding)
 {
     mbedtls_pk_context pk;
@@ -1847,7 +1818,7 @@
     int ret;
 #endif /* MBEDTLS_RSA_C || MBEDTLS_PK_WRITE_C */
 #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
-    mbedtls_ecp_group_id ecp_grp_id;
+    mbedtls_ecp_group_id ecp_grp_id = MBEDTLS_ECP_DP_NONE;
 #endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
 
     /*
@@ -1863,21 +1834,18 @@
     USE_PSA_INIT();
 
     /* Create the legacy EC/RSA PK context. */
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME)
+#if defined(MBEDTLS_RSA_C)
     if (PSA_KEY_TYPE_IS_RSA(psa_type)) {
-        TEST_ASSERT(mbedtls_pk_setup(&pk,
-                                     mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == 0);
-        TEST_EQUAL(pk_genkey(&pk, bits), 0);
+        TEST_EQUAL(pk_setup(&pk, MBEDTLS_PK_RSA, bits), 0);
         TEST_EQUAL(mbedtls_rsa_set_padding(mbedtls_pk_rsa(pk), rsa_padding, MBEDTLS_MD_NONE), 0);
     }
-#else /* MBEDTLS_RSA_C && MBEDTLS_GENPRIME */
+#else /* MBEDTLS_RSA_C */
     (void) rsa_padding;
-#endif /* MBEDTLS_RSA_C && MBEDTLS_GENPRIME */
+#endif /* MBEDTLS_RSA_C */
 #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
     if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(psa_type)) {
         ecp_grp_id = mbedtls_ecc_group_from_psa(psa_type, bits);
-        TEST_ASSERT(mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)) == 0);
-        TEST_ASSERT(pk_genkey(&pk, ecp_grp_id) == 0);
+        TEST_ASSERT(pk_setup(&pk, MBEDTLS_PK_ECKEY, ecp_grp_id) == 0);
     }
 #endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
 
@@ -1999,7 +1967,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_GENPRIME */
+/* BEGIN_CASE */
 void pk_sign_ext(int pk_type, int curve_or_keybits, int key_pk_type, int md_alg)
 {
     mbedtls_pk_context pk;
@@ -2015,9 +1983,7 @@
     mbedtls_pk_init(&pk);
     MD_OR_USE_PSA_INIT();
 
-    TEST_EQUAL(mbedtls_pk_setup(&pk,
-                                mbedtls_pk_info_from_type(pk_type)), 0);
-    TEST_EQUAL(pk_genkey(&pk, curve_or_keybits), 0);
+    TEST_EQUAL(pk_setup(&pk, pk_type, curve_or_keybits), 0);
 
     TEST_EQUAL(mbedtls_pk_sign_ext(key_pk_type, &pk, md_alg, hash, hash_len,
                                    sig, sizeof(sig), &sig_len,
@@ -2037,7 +2003,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_USE_PSA_CRYPTO */
+/* BEGIN_CASE depends_on:MBEDTLS_RSA_C:MBEDTLS_USE_PSA_CRYPTO */
 void pk_psa_wrap_sign_ext(int pk_type, int key_bits, int key_pk_type, int md_alg)
 {
     mbedtls_pk_context pk;
@@ -2059,11 +2025,7 @@
 
     /* Create legacy RSA public/private key in PK context. */
     mbedtls_pk_init(&pk);
-    TEST_EQUAL(mbedtls_pk_setup(&pk,
-                                mbedtls_pk_info_from_type(pk_type)), 0);
-    TEST_EQUAL(mbedtls_rsa_gen_key(mbedtls_pk_rsa(pk),
-                                   mbedtls_test_rnd_std_rand, NULL,
-                                   key_bits, 3), 0);
+    TEST_EQUAL(pk_setup(&pk, pk_type, key_bits), 0);
 
     if (key_pk_type == MBEDTLS_PK_RSASSA_PSS) {
         mbedtls_rsa_set_padding(mbedtls_pk_rsa(pk), MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_NONE);
@@ -2207,7 +2169,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_GENPRIME */
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21 */
 void pk_rsa_v21_get_psa_attributes(int md_type, int from_pair,
                                    int usage_arg,
                                    int to_pair, int expected_alg)
@@ -2281,7 +2243,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PSA_CRYPTO_STORAGE_C */
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PSA_CRYPTO_STORAGE_C */
 void pk_import_into_psa_lifetime(int from_opaque,
                                  int from_persistent, /* when from opaque */
                                  int from_exportable, /* when from opaque */
@@ -2302,17 +2264,18 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
         psa_key_type_t from_psa_type =
             PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY);
-        psa_set_key_type(&attributes, from_psa_type);
-        psa_set_key_bits(&attributes, MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS);
-        psa_set_key_usage_flags(
-            &attributes,
+        psa_key_usage_t psa_key_usage =
             (from_exportable ? PSA_KEY_USAGE_EXPORT : PSA_KEY_USAGE_COPY) |
-            PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
-        psa_set_key_algorithm(&attributes, PSA_ALG_ECDH);
+            PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH;
+        mbedtls_svc_key_id_t persistent_key_id = MBEDTLS_SVC_KEY_ID_INIT;
+
         if (from_persistent) {
-            psa_set_key_id(&attributes, mbedtls_svc_key_id_make(0, 1));
+            persistent_key_id = mbedtls_svc_key_id_make(0, 1);
         }
-        PSA_ASSERT(psa_generate_key(&attributes, &old_key_id));
+
+        PSA_ASSERT(pk_psa_setup(from_psa_type, MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS,
+                                psa_key_usage, PSA_ALG_ECDH, PSA_ALG_NONE,
+                                persistent_key_id, &old_key_id));
         TEST_EQUAL(mbedtls_pk_setup_opaque(&pk, old_key_id), 0);
         psa_reset_key_attributes(&attributes);
 #else
@@ -2388,12 +2351,8 @@
 
     PSA_INIT();
 
-    psa_set_key_type(&attributes, from_type);
-    psa_set_key_bits(&attributes, bits);
-    psa_set_key_usage_flags(&attributes, from_usage);
-    psa_set_key_algorithm(&attributes, alg);
-    psa_set_key_enrollment_algorithm(&attributes, 42);
-    PSA_ASSERT(psa_generate_key(&attributes, &old_key_id));
+    PSA_ASSERT(pk_psa_setup(from_type, bits, from_usage, alg, 42,
+                            MBEDTLS_SVC_KEY_ID_INIT, &old_key_id));
     TEST_EQUAL(mbedtls_pk_setup_opaque(&pk, old_key_id), 0);
 
     psa_key_type_t expected_psa_type =
@@ -2485,11 +2444,8 @@
 
     PSA_INIT();
 
-    psa_set_key_type(&from_attributes, from_type);
-    psa_set_key_bits(&from_attributes, from_bits);
-    psa_set_key_usage_flags(&from_attributes, from_usage);
-    psa_set_key_algorithm(&from_attributes, from_alg);
-    PSA_ASSERT(psa_generate_key(&from_attributes, &from_key_id));
+    PSA_ASSERT(pk_psa_setup(from_type, from_bits, from_usage, from_alg, PSA_ALG_NONE,
+                            MBEDTLS_SVC_KEY_ID_INIT, &from_key_id));
     TEST_EQUAL(mbedtls_pk_setup_opaque(&pk, from_key_id), 0);
 
     psa_set_key_type(&to_attributes, to_type);
@@ -2555,23 +2511,21 @@
                MBEDTLS_ERR_PK_BAD_INPUT_DATA);
 
 #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)
-    /* Generate a key type that is not handled by the PK module. */
-    PSA_ASSERT(pk_psa_genkey_generic(PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919), 2048,
-                                     PSA_KEY_USAGE_EXPORT, PSA_ALG_NONE, &key_id));
+    pk_psa_setup(PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919), 2048,
+                 PSA_KEY_USAGE_EXPORT, PSA_ALG_NONE, PSA_ALG_NONE,
+                 MBEDTLS_SVC_KEY_ID_INIT, &key_id);
     TEST_EQUAL(mbedtls_pk_copy_from_psa(key_id, &pk_ctx), MBEDTLS_ERR_PK_BAD_INPUT_DATA);
     TEST_EQUAL(mbedtls_pk_copy_public_from_psa(key_id, &pk_ctx), MBEDTLS_ERR_PK_BAD_INPUT_DATA);
     psa_destroy_key(key_id);
 #endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE */
 
-#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) && defined(PSA_WANT_ECC_SECP_R1_256) && \
-    defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) && defined(PSA_WANT_ECC_SECP_R1_256)
     /* Generate an EC key which cannot be exported. */
-    PSA_ASSERT(pk_psa_genkey_generic(PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1), 256,
-                                     0, PSA_ALG_NONE, &key_id));
+    PSA_ASSERT(pk_psa_setup(PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1), 256,
+                            0, PSA_ALG_NONE, PSA_ALG_NONE, MBEDTLS_SVC_KEY_ID_INIT, &key_id));
     TEST_EQUAL(mbedtls_pk_copy_from_psa(key_id, &pk_ctx), MBEDTLS_ERR_PK_TYPE_MISMATCH);
     psa_destroy_key(key_id);
-#endif /* MBEDTLS_PK_HAVE_ECC_KEYS && PSA_WANT_ECC_SECP_R1_256 &&
-          PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS && PSA_WANT_ECC_SECP_R1_256 */
 
 exit:
     mbedtls_pk_free(&pk_ctx);
@@ -2589,11 +2543,12 @@
     mbedtls_pk_init(&pk_ctx);
     PSA_INIT();
 
-    PSA_ASSERT(pk_psa_genkey_generic(PSA_KEY_TYPE_RSA_KEY_PAIR,
-                                     PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS,
-                                     PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT,
-                                     PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256),
-                                     &key_id));
+    PSA_ASSERT(pk_psa_setup(PSA_KEY_TYPE_RSA_KEY_PAIR,
+                            PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS,
+                            PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT,
+                            PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256),
+                            PSA_ALG_NONE,
+                            MBEDTLS_SVC_KEY_ID_INIT, &key_id));
     TEST_EQUAL(mbedtls_pk_copy_from_psa(key_id, &pk_ctx), MBEDTLS_ERR_PK_BAD_INPUT_DATA);
 exit:
     mbedtls_pk_free(&pk_ctx);
diff --git a/tests/suites/test_suite_pkparse.data b/tests/suites/test_suite_pkparse.data
index 1650f51..d170e1e 100644
--- a/tests/suites/test_suite_pkparse.data
+++ b/tests/suites/test_suite_pkparse.data
@@ -914,21 +914,23 @@
 depends_on:MBEDTLS_AES_C:MBEDTLS_MD_CAN_SHA384:MBEDTLS_PKCS5_C:MBEDTLS_CIPHER_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH
 pk_parse_keyfile_rsa:"data_files/rsa_pkcs8_pbes2_pbkdf2_2048_aes256cbc_sha384.der":"PolarSSLTest":0
 
-Parse RSA Key #100.1 (512-bit)
-depends_on:MBEDTLS_PEM_C
-pk_parse_keyfile_rsa:"data_files/rsa512.key":"":0
+# Test keys with non-word-aligned sizes.
+# We use sizes that are large enough to exercise PKCS#1 v1.5 signature with
+# the largest supported hashes (SHA-512 and SHA3-512.)
+Parse RSA Key #100 (768-bit)
+pk_parse_keyfile_rsa:"data_files/rsa_pkcs1_768_clear.der":"":0
 
-Parse RSA Key #100.1 (521-bit)
-depends_on:MBEDTLS_PEM_C
-pk_parse_keyfile_rsa:"data_files/rsa521.key":"":0
+Parse RSA Key #100 (769-bit)
+pk_parse_keyfile_rsa:"data_files/rsa_pkcs1_769_clear.der":"":0
 
-Parse RSA Key #100.1 (522-bit)
-depends_on:MBEDTLS_PEM_C
-pk_parse_keyfile_rsa:"data_files/rsa522.key":"":0
+Parse RSA Key #100 (770-bit)
+pk_parse_keyfile_rsa:"data_files/rsa_pkcs1_770_clear.der":"":0
 
-Parse RSA Key #100.1 (528-bit)
-depends_on:MBEDTLS_PEM_C
-pk_parse_keyfile_rsa:"data_files/rsa528.key":"":0
+Parse RSA Key #100 (776-bit)
+pk_parse_keyfile_rsa:"data_files/rsa_pkcs1_776_clear.der":"":0
+
+Parse RSA Key #100 (784-bit)
+pk_parse_keyfile_rsa:"data_files/rsa_pkcs1_784_clear.der":"":0
 
 Parse Public RSA Key #1 (PKCS#8 wrapped)
 depends_on:MBEDTLS_PEM_PARSE_C
diff --git a/tests/suites/test_suite_pkparse.function b/tests/suites/test_suite_pkparse.function
index a06fc30..63ff092 100644
--- a/tests/suites/test_suite_pkparse.function
+++ b/tests/suites/test_suite_pkparse.function
@@ -47,7 +47,19 @@
     int ok = 0;
 
     TEST_EQUAL(mbedtls_pk_get_psa_attributes(ctx, usage_flag, &attributes), 0);
-    TEST_EQUAL(mbedtls_pk_import_into_psa(ctx, &attributes, &psa_key), 0);
+    int ret = mbedtls_pk_import_into_psa(ctx, &attributes, &psa_key);
+    if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_RSA &&
+        mbedtls_pk_get_bitlen(ctx) % 8 != 0 &&
+        ret == MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) {
+        /* There is a historical limitation with support for RSA keys in PSA:
+         * only byte-aligned sizes are supported.
+         * https://github.com/Mbed-TLS/mbedtls/issues/9048
+         * For now, for such keys, treat not-supported from PSA as a success.
+         */
+        ok = 1;
+        goto exit;
+    }
+    TEST_EQUAL(ret, 0);
     if (!mbedtls_test_key_consistency_psa_pk(psa_key, ctx)) {
         goto exit;
     }
diff --git a/tests/suites/test_suite_psa_crypto_pake.data b/tests/suites/test_suite_psa_crypto_pake.data
index 49e97a9..f81bb53 100644
--- a/tests/suites/test_suite_psa_crypto_pake.data
+++ b/tests/suites/test_suite_psa_crypto_pake.data
@@ -74,7 +74,7 @@
 depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
 ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:"client":"server":1:ERR_INJECT_EMPTY_IO_BUFFER:PSA_ERROR_INVALID_ARGUMENT
 
-PSA PAKE: unkown input step
+PSA PAKE: unknown input step
 depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
 ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:"client":"server":1:ERR_INJECT_UNKNOWN_STEP:PSA_ERROR_INVALID_ARGUMENT
 
@@ -94,7 +94,7 @@
 depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
 ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:"client":"server":0:ERR_INJECT_EMPTY_IO_BUFFER:PSA_ERROR_INVALID_ARGUMENT
 
-PSA PAKE: unkown output step
+PSA PAKE: unknown output step
 depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
 ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:"client":"server":0:ERR_INJECT_UNKNOWN_STEP:PSA_ERROR_INVALID_ARGUMENT
 
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 89d4578..500c676 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -239,71 +239,71 @@
 x509_parse_san:"data_files/server5-tricky-ip-san-malformed-len.crt.der":"":MBEDTLS_ERR_X509_BAD_INPUT_DATA
 
 X509 CRL information #1
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA1:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA1:MBEDTLS_RSA_C
 mbedtls_x509_crl_info:"data_files/parse_input/crl_expired.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-20 10\:24\:19\nnext update   \: 2011-02-20 11\:24\:19\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA1\n"
 
 X509 CRL Information MD5 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_MD5:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_MD5:MBEDTLS_RSA_C
 mbedtls_x509_crl_info:"data_files/parse_input/crl_md5.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with MD5\n"
 
 X509 CRL Information SHA1 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA1:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA1:MBEDTLS_RSA_C
 mbedtls_x509_crl_info:"data_files/parse_input/crl_sha1.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA1\n"
 
 X509 CRL Information SHA224 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA224:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA224:MBEDTLS_RSA_C
 mbedtls_x509_crl_info:"data_files/parse_input/crl_sha224.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA-224\n"
 
 X509 CRL Information SHA256 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C
 mbedtls_x509_crl_info:"data_files/parse_input/crl_sha256.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA-256\n"
 
 X509 CRL Information SHA384 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA384:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA384:MBEDTLS_RSA_C
 mbedtls_x509_crl_info:"data_files/parse_input/crl_sha384.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA-384\n"
 
 X509 CRL Information SHA512 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA512:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA512:MBEDTLS_RSA_C
 mbedtls_x509_crl_info:"data_files/parse_input/crl_sha512.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA-512\n"
 
 X509 CRL information RSA-PSS, SHA1 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA1:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA1
 mbedtls_x509_crl_info:"data_files/parse_input/crl-rsa-pss-sha1.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2014-01-20 13\:46\:35\nnext update   \: 2024-01-18 13\:46\:35\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nserial number\: 16 revocation date\: 2014-01-20 13\:43\:05\nsigned using  \: RSASSA-PSS (SHA1, MGF1-SHA1, 0xEA)\n"
 
 X509 CRL information RSA-PSS, SHA224 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA224:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA224
 mbedtls_x509_crl_info:"data_files/parse_input/crl-rsa-pss-sha224.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2014-01-20 13\:56\:06\nnext update   \: 2024-01-18 13\:56\:06\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nserial number\: 16 revocation date\: 2014-01-20 13\:43\:05\nsigned using  \: RSASSA-PSS (SHA224, MGF1-SHA224, 0xE2)\n"
 
 X509 CRL information RSA-PSS, SHA256 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA256:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA256
 mbedtls_x509_crl_info:"data_files/parse_input/crl-rsa-pss-sha256.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2014-01-20 13\:56\:16\nnext update   \: 2024-01-18 13\:56\:16\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nserial number\: 16 revocation date\: 2014-01-20 13\:43\:05\nsigned using  \: RSASSA-PSS (SHA256, MGF1-SHA256, 0xDE)\n"
 
 X509 CRL information RSA-PSS, SHA384 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA384:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA384
 mbedtls_x509_crl_info:"data_files/parse_input/crl-rsa-pss-sha384.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2014-01-20 13\:56\:28\nnext update   \: 2024-01-18 13\:56\:28\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nserial number\: 16 revocation date\: 2014-01-20 13\:43\:05\nsigned using  \: RSASSA-PSS (SHA384, MGF1-SHA384, 0xCE)\n"
 
 X509 CRL information RSA-PSS, SHA512 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA512:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA512
 mbedtls_x509_crl_info:"data_files/parse_input/crl-rsa-pss-sha512.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2014-01-20 13\:56\:38\nnext update   \: 2024-01-18 13\:56\:38\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nserial number\: 16 revocation date\: 2014-01-20 13\:43\:05\nsigned using  \: RSASSA-PSS (SHA512, MGF1-SHA512, 0xBE)\n"
 
 X509 CRL Information EC, SHA1 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA1:MBEDTLS_PK_CAN_ECDSA_SOME:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA1:MBEDTLS_PK_CAN_ECDSA_SOME
 mbedtls_x509_crl_info:"data_files/parse_input/crl-ec-sha1.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nthis update   \: 2013-09-24 16\:31\:08\nnext update   \: 2023-09-22 16\:31\:08\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nsigned using  \: ECDSA with SHA1\n"
 
 X509 CRL Information EC, SHA224 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA224:MBEDTLS_PK_CAN_ECDSA_SOME:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA224:MBEDTLS_PK_CAN_ECDSA_SOME
 mbedtls_x509_crl_info:"data_files/parse_input/crl-ec-sha224.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nthis update   \: 2013-09-24 16\:31\:08\nnext update   \: 2023-09-22 16\:31\:08\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nsigned using  \: ECDSA with SHA224\n"
 
 X509 CRL Information EC, SHA256 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA256:MBEDTLS_PK_CAN_ECDSA_SOME:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA256:MBEDTLS_PK_CAN_ECDSA_SOME
 mbedtls_x509_crl_info:"data_files/parse_input/crl-ec-sha256.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nthis update   \: 2013-09-24 16\:31\:08\nnext update   \: 2023-09-22 16\:31\:08\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nsigned using  \: ECDSA with SHA256\n"
 
 X509 CRL Information EC, SHA384 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA384:MBEDTLS_PK_CAN_ECDSA_SOME:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA384:MBEDTLS_PK_CAN_ECDSA_SOME
 mbedtls_x509_crl_info:"data_files/parse_input/crl-ec-sha384.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nthis update   \: 2013-09-24 16\:31\:08\nnext update   \: 2023-09-22 16\:31\:08\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nsigned using  \: ECDSA with SHA384\n"
 
 X509 CRL Information EC, SHA512 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA512:MBEDTLS_PK_CAN_ECDSA_SOME:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA512:MBEDTLS_PK_CAN_ECDSA_SOME
 mbedtls_x509_crl_info:"data_files/parse_input/crl-ec-sha512.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nthis update   \: 2013-09-24 16\:31\:08\nnext update   \: 2023-09-22 16\:31\:08\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nsigned using  \: ECDSA with SHA512\n"
 
 X509 CRL Malformed Input (trailing spaces at end of file)