Merge pull request #8845 from gilles-peskine-arm/ecp-write-doc-3.6

Document ECP write functions
diff --git a/ChangeLog.d/8799.txt b/ChangeLog.d/8799.txt
new file mode 100644
index 0000000..50e7c11
--- /dev/null
+++ b/ChangeLog.d/8799.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * mbedtls_pem_read_buffer() now performs a check on the padding data of
+     decrypted keys and it rejects invalid ones.
diff --git a/ChangeLog.d/8824.txt b/ChangeLog.d/8824.txt
new file mode 100644
index 0000000..abc305f
--- /dev/null
+++ b/ChangeLog.d/8824.txt
@@ -0,0 +1,7 @@
+Bugfix
+   * Fix mbedtls_pk_sign(), mbedtls_pk_verify(), mbedtls_pk_decrypt() and
+     mbedtls_pk_encrypt() on non-opaque RSA keys to honor the padding mode in
+     the RSA context. Before, if MBEDTLS_USE_PSA_CRYPTO was enabled, they always
+     used PKCS#1 v1.5 even when the RSA context was configured for PKCS#1 v2.1
+     (PSS/OAEP). Fixes #8824.
+
diff --git a/ChangeLog.d/benchmark-ecdh.txt b/ChangeLog.d/benchmark-ecdh.txt
new file mode 100644
index 0000000..ef243b8
--- /dev/null
+++ b/ChangeLog.d/benchmark-ecdh.txt
@@ -0,0 +1,3 @@
+Features
+   * The benchmark program now reports times for both ephemeral and static
+     ECDH in all ECDH configurations.
diff --git a/ChangeLog.d/domain_parameters.txt b/ChangeLog.d/domain_parameters.txt
new file mode 100644
index 0000000..d860cc4
--- /dev/null
+++ b/ChangeLog.d/domain_parameters.txt
@@ -0,0 +1,9 @@
+New deprecations
+   * In the PSA API, domain parameters are no longer used for anything.
+     They are deprecated and will be removed in a future version of the
+     library.
+
+Removals
+   * In the PSA API, the experimental way to encode the public exponent of
+     an RSA key as a domain parameter is no longer supported. Use
+     psa_generate_key_ext() instead.
diff --git a/ChangeLog.d/gcm-large-tables.txt b/ChangeLog.d/gcm-large-tables.txt
new file mode 100644
index 0000000..f9bba5b
--- /dev/null
+++ b/ChangeLog.d/gcm-large-tables.txt
@@ -0,0 +1,4 @@
+Features
+    * Add support for 8-bit GCM tables for Shoup's algorithm to speedup GCM
+      operations when hardware accelerated AES is not present. Improves
+      performance by around 30% on 64-bit Intel; 125% on Armv7-M.
diff --git a/ChangeLog.d/get_ticket_creation_time.txt b/ChangeLog.d/get_ticket_creation_time.txt
new file mode 100644
index 0000000..7b5166c
--- /dev/null
+++ b/ChangeLog.d/get_ticket_creation_time.txt
@@ -0,0 +1,3 @@
+Features
+   * Add getter (mbedtls_ssl_session_get_ticket_creation_time()) to access
+     `mbedtls_ssl_session.ticket_creation_time`.
diff --git a/ChangeLog.d/mbedtls_pk_import_into_psa.txt b/ChangeLog.d/mbedtls_pk_import_into_psa.txt
new file mode 100644
index 0000000..c294f44
--- /dev/null
+++ b/ChangeLog.d/mbedtls_pk_import_into_psa.txt
@@ -0,0 +1,4 @@
+Features
+   * The new functions mbedtls_pk_get_psa_attributes() and
+     mbedtls_pk_import_into_psa() provide a uniform way to create a PSA
+     key from a PK key.
diff --git a/ChangeLog.d/psa_generate_key_ext.txt b/ChangeLog.d/psa_generate_key_ext.txt
new file mode 100644
index 0000000..8340f01
--- /dev/null
+++ b/ChangeLog.d/psa_generate_key_ext.txt
@@ -0,0 +1,3 @@
+Features
+   * The new function psa_generate_key_ext() allows generating an RSA
+     key pair with a custom public exponent.
diff --git a/include/mbedtls/build_info.h b/include/mbedtls/build_info.h
index 2f336ba..99a449b 100644
--- a/include/mbedtls/build_info.h
+++ b/include/mbedtls/build_info.h
@@ -158,7 +158,8 @@
  *   (e.g. MBEDTLS_MD_LIGHT)
  */
 #if defined(MBEDTLS_PSA_CRYPTO_CONFIG) /* PSA_WANT_xxx influences MBEDTLS_xxx */ || \
-    defined(MBEDTLS_PSA_CRYPTO_C) /* MBEDTLS_xxx influences PSA_WANT_xxx */
+    defined(MBEDTLS_PSA_CRYPTO_C) /* MBEDTLS_xxx influences PSA_WANT_xxx */ || \
+    defined(MBEDTLS_PSA_CRYPTO_CLIENT) /* The same as the previous, but with separation only */
 #include "mbedtls/config_psa.h"
 #endif
 
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 576efea..b3c038d 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -85,7 +85,7 @@
 #endif /* some curve accelerated */
 
 #if defined(MBEDTLS_CTR_DRBG_C) && !(defined(MBEDTLS_AES_C) || \
-    (defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_KEY_TYPE_AES) && \
+    (defined(MBEDTLS_PSA_CRYPTO_CLIENT) && defined(PSA_WANT_KEY_TYPE_AES) && \
     defined(PSA_WANT_ALG_ECB_NO_PADDING)))
 #error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites"
 #endif
@@ -397,7 +397,7 @@
 #endif
 
 #if defined(MBEDTLS_LMS_C) &&                                          \
-    ! ( defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_256) )
+    ! ( defined(MBEDTLS_PSA_CRYPTO_CLIENT) && defined(PSA_WANT_ALG_SHA_256) )
 #error "MBEDTLS_LMS_C requires MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256"
 #endif
 
@@ -791,7 +791,7 @@
  * Note: for dependencies common with TLS 1.2 (running handshake hash),
  * see MBEDTLS_SSL_TLS_C. */
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
-    !(defined(MBEDTLS_PSA_CRYPTO_C) && \
+    !(defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \
       defined(PSA_WANT_ALG_HKDF_EXTRACT) && \
       defined(PSA_WANT_ALG_HKDF_EXPAND) && \
       (defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_384)))
@@ -987,7 +987,7 @@
 #endif
 #undef MBEDTLS_THREADING_IMPL // temporary macro defined above
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_C)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_CLIENT)
 #error "MBEDTLS_USE_PSA_CRYPTO defined, but not all prerequisites"
 #endif
 
diff --git a/include/mbedtls/config_adjust_ssl.h b/include/mbedtls/config_adjust_ssl.h
index 5dd331c..39c7b3b 100644
--- a/include/mbedtls/config_adjust_ssl.h
+++ b/include/mbedtls/config_adjust_ssl.h
@@ -34,6 +34,10 @@
 #undef MBEDTLS_SSL_PROTO_DTLS
 #endif
 
+#if !(defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SESSION_TICKETS))
+#undef MBEDTLS_SSL_TICKET_C
+#endif
+
 #if !defined(MBEDTLS_SSL_PROTO_DTLS)
 #undef MBEDTLS_SSL_DTLS_ANTI_REPLAY
 #undef MBEDTLS_SSL_DTLS_CONNECTION_ID
diff --git a/include/mbedtls/gcm.h b/include/mbedtls/gcm.h
index 631b392..98faa43 100644
--- a/include/mbedtls/gcm.h
+++ b/include/mbedtls/gcm.h
@@ -46,6 +46,12 @@
 
 #if !defined(MBEDTLS_GCM_ALT)
 
+#if defined(MBEDTLS_GCM_LARGE_TABLE)
+#define MBEDTLS_GCM_HTABLE_SIZE 256
+#else
+#define MBEDTLS_GCM_HTABLE_SIZE 16
+#endif
+
 /**
  * \brief          The GCM context structure.
  */
@@ -53,18 +59,18 @@
 #if defined(MBEDTLS_BLOCK_CIPHER_C)
     mbedtls_block_cipher_context_t MBEDTLS_PRIVATE(block_cipher_ctx);  /*!< The cipher context used. */
 #else
-    mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx);  /*!< The cipher context used. */
+    mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx);    /*!< The cipher context used. */
 #endif
-    uint64_t MBEDTLS_PRIVATE(HL)[16];                      /*!< Precalculated HTable low. */
-    uint64_t MBEDTLS_PRIVATE(HH)[16];                      /*!< Precalculated HTable high. */
-    uint64_t MBEDTLS_PRIVATE(len);                         /*!< The total length of the encrypted data. */
-    uint64_t MBEDTLS_PRIVATE(add_len);                     /*!< The total length of the additional data. */
-    unsigned char MBEDTLS_PRIVATE(base_ectr)[16];          /*!< The first ECTR for tag. */
-    unsigned char MBEDTLS_PRIVATE(y)[16];                  /*!< The Y working value. */
-    unsigned char MBEDTLS_PRIVATE(buf)[16];                /*!< The buf working value. */
-    int MBEDTLS_PRIVATE(mode);                             /*!< The operation to perform:
-                                                            #MBEDTLS_GCM_ENCRYPT or
-                                                            #MBEDTLS_GCM_DECRYPT. */
+    uint64_t MBEDTLS_PRIVATE(H)[MBEDTLS_GCM_HTABLE_SIZE][2]; /*!< Precalculated HTable. */
+    uint64_t MBEDTLS_PRIVATE(len);                           /*!< The total length of the encrypted data. */
+    uint64_t MBEDTLS_PRIVATE(add_len);                       /*!< The total length of the additional data. */
+    unsigned char MBEDTLS_PRIVATE(base_ectr)[16];            /*!< The first ECTR for tag. */
+    unsigned char MBEDTLS_PRIVATE(y)[16];                    /*!< The Y working value. */
+    unsigned char MBEDTLS_PRIVATE(buf)[16];                  /*!< The buf working value. */
+    unsigned char MBEDTLS_PRIVATE(mode);                     /*!< The operation to perform:
+                                                              #MBEDTLS_GCM_ENCRYPT or
+                                                              #MBEDTLS_GCM_DECRYPT. */
+    unsigned char MBEDTLS_PRIVATE(acceleration);             /*!< The acceleration to use. */
 }
 mbedtls_gcm_context;
 
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index 254e75a..7cf4153 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -2801,6 +2801,22 @@
 #define MBEDTLS_GCM_C
 
 /**
+ * \def MBEDTLS_GCM_LARGE_TABLE
+ *
+ * Enable large pre-computed tables for  Galois/Counter Mode (GCM).
+ * Can significantly increase throughput on systems without GCM hardware
+ * acceleration (e.g., AESNI, AESCE).
+ *
+ * The mbedtls_gcm_context size will increase by 3840 bytes.
+ * The code size will increase by roughly 344 bytes.
+ *
+ * Module:  library/gcm.c
+ *
+ * Requires: MBEDTLS_GCM_C
+ */
+//#define MBEDTLS_GCM_LARGE_TABLE
+
+/**
  * \def MBEDTLS_HKDF_C
  *
  * Enable the HKDF algorithm (RFC 5869).
diff --git a/include/mbedtls/pem.h b/include/mbedtls/pem.h
index cc617a9..3c6a28d 100644
--- a/include/mbedtls/pem.h
+++ b/include/mbedtls/pem.h
@@ -73,11 +73,11 @@
  * \param data      source data to look in (must be nul-terminated)
  * \param pwd       password for decryption (can be NULL)
  * \param pwdlen    length of password
- * \param use_len   destination for total length used (set after header is
- *                  correctly read, so unless you get
+ * \param use_len   destination for total length used from data buffer. It is
+ *                  set after header is correctly read, so unless you get
  *                  MBEDTLS_ERR_PEM_BAD_INPUT_DATA or
  *                  MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is
- *                  the length to skip)
+ *                  the length to skip.
  *
  * \note            Attempts to check password correctness by verifying if
  *                  the decrypted text starts with an ASN.1 sequence of
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index 919543c..534712b 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -592,6 +592,54 @@
 int mbedtls_pk_get_psa_attributes(const mbedtls_pk_context *pk,
                                   psa_key_usage_t usage,
                                   psa_key_attributes_t *attributes);
+
+/**
+ * \brief           Import a key into the PSA key store.
+ *
+ *                  This function is equivalent to calling psa_import_key()
+ *                  with the key material from \p pk.
+ *
+ *                  The typical way to use this function is:
+ *                  -# Call mbedtls_pk_get_psa_attributes() to obtain
+ *                     attributes for the given key.
+ *                  -# If desired, modify the attributes, for example:
+ *                      - To create a persistent key, call
+ *                        psa_set_key_identifier() and optionally
+ *                        psa_set_key_lifetime().
+ *                      - To import only the public part of a key pair:
+ *                        ```
+ *                        psa_set_key_type(&attributes,
+ *                                         PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(
+ *                                             psa_get_key_type(&attributes)));
+ *                        ```
+ *                      - Restrict the key usage if desired.
+ *                  -# Call mbedtls_pk_import_into_psa().
+ *
+ * \note            This function does not support RSA-alt contexts
+ *                  (set up with mbedtls_pk_setup_rsa_alt()).
+ *
+ * \param[in] pk    The PK context to use. It must have been set up.
+ *                  It can either contain a key pair or just a public key.
+ * \param[in] attributes
+ *                  The attributes to use for the new key. They must be
+ *                  compatible with \p pk. In particular, the key type
+ *                  must match the content of \p pk.
+ *                  If \p pk contains a key pair, the key type in
+ *                  attributes can be either the key pair type or the
+ *                  corresponding public key type (to import only the
+ *                  public part).
+ * \param[out] key_id
+ *                  On success, the identifier of the newly created key.
+ *                  On error, this is #MBEDTLS_SVC_KEY_ID_INIT.
+ *
+ * \return          0 on success.
+ *                  #MBEDTLS_ERR_PK_TYPE_MISMATCH if \p pk does not contain
+ *                  a key of the type identified in \p attributes.
+ *                  Another error code on other failures.
+ */
+int mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk,
+                               const psa_key_attributes_t *attributes,
+                               mbedtls_svc_key_id_t *key_id);
 #endif /* MBEDTLS_PSA_CRYPTO_C */
 
 /**
@@ -612,14 +660,17 @@
  * \param sig       Signature to verify
  * \param sig_len   Signature length
  *
+ * \note            For keys of type #MBEDTLS_PK_RSA, the signature algorithm is
+ *                  either PKCS#1 v1.5 or PSS (accepting any salt length),
+ *                  depending on the padding mode in the underlying RSA context.
+ *                  For a pk object constructed by parsing, this is PKCS#1 v1.5
+ *                  by default. Use mbedtls_pk_verify_ext() to explicitly select
+ *                  a different algorithm.
+ *
  * \return          0 on success (signature is valid),
  *                  #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid
  *                  signature in \p sig but its length is less than \p sig_len,
  *                  or a specific error code.
- *
- * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
- *                  Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... )
- *                  to verify RSASSA_PSS signatures.
  */
 int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
                       const unsigned char *hash, size_t hash_len,
@@ -706,11 +757,15 @@
  * \param f_rng     RNG function, must not be \c NULL.
  * \param p_rng     RNG parameter
  *
- * \return          0 on success, or a specific error code.
+ * \note            For keys of type #MBEDTLS_PK_RSA, the signature algorithm is
+ *                  either PKCS#1 v1.5 or PSS (using the largest possible salt
+ *                  length up to the hash length), depending on the padding mode
+ *                  in the underlying RSA context. For a pk object constructed
+ *                  by parsing, this is PKCS#1 v1.5 by default. Use
+ *                  mbedtls_pk_verify_ext() to explicitly select a different
+ *                  algorithm.
  *
- * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
- *                  There is no interface in the PK module to make RSASSA-PSS
- *                  signatures yet.
+ * \return          0 on success, or a specific error code.
  *
  * \note            For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0.
  *                  For ECDSA, md_alg may never be MBEDTLS_MD_NONE.
@@ -806,7 +861,10 @@
  * \param f_rng     RNG function, must not be \c NULL.
  * \param p_rng     RNG parameter
  *
- * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
+ * \note            For keys of type #MBEDTLS_PK_RSA, the signature algorithm is
+ *                  either PKCS#1 v1.5 or OAEP, depending on the padding mode in
+ *                  the underlying RSA context. For a pk object constructed by
+ *                  parsing, this is PKCS#1 v1.5 by default.
  *
  * \return          0 on success, or a specific error code.
  */
@@ -827,9 +885,12 @@
  * \param f_rng     RNG function, must not be \c NULL.
  * \param p_rng     RNG parameter
  *
- * \note            \p f_rng is used for padding generation.
+ * \note            For keys of type #MBEDTLS_PK_RSA, the signature algorithm is
+ *                  either PKCS#1 v1.5 or OAEP, depending on the padding mode in
+ *                  the underlying RSA context. For a pk object constructed by
+ *                  parsing, this is PKCS#1 v1.5 by default.
  *
- * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
+ * \note            \p f_rng is used for padding generation.
  *
  * \return          0 on success, or a specific error code.
  */
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 9583a15..08c628a 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -1224,6 +1224,7 @@
 #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
 
     unsigned char MBEDTLS_PRIVATE(exported);
+    uint8_t MBEDTLS_PRIVATE(endpoint);          /*!< 0: client, 1: server */
 
     /** TLS version negotiated in the session. Used if and when renegotiating
      *  or resuming a session instead of the configured minor TLS version.
@@ -1257,26 +1258,41 @@
     uint32_t MBEDTLS_PRIVATE(ticket_lifetime);   /*!< ticket lifetime hint    */
 #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
 
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) && \
+    defined(MBEDTLS_HAVE_TIME)
+    /*! When a ticket is created by a TLS server as part of an established TLS
+     *  session, the ticket creation time may need to be saved for the ticket
+     *  module to be able to check the ticket age when the ticket is used.
+     *  That's the purpose of this field.
+     *  Before creating a new ticket, an Mbed TLS server set this field with
+     *  its current time in milliseconds. This time may then be saved in the
+     *  session ticket data by the session ticket writing function and
+     *  recovered by the ticket parsing function later when the ticket is used.
+     *  The ticket module may then use this time to compute the ticket age and
+     *  determine if it has expired or not.
+     *  The Mbed TLS implementations of the session ticket writing and parsing
+     *  functions save and retrieve the ticket creation time as part of the
+     *  session ticket data. The session ticket parsing function relies on
+     *  the mbedtls_ssl_session_get_ticket_creation_time() API to get the
+     *  ticket creation time from the session ticket data.
+     */
+    mbedtls_ms_time_t MBEDTLS_PRIVATE(ticket_creation_time);
+#endif
+
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)
-    uint8_t MBEDTLS_PRIVATE(endpoint);          /*!< 0: client, 1: server */
-    uint8_t MBEDTLS_PRIVATE(ticket_flags);      /*!< Ticket flags */
-    uint32_t MBEDTLS_PRIVATE(ticket_age_add);               /*!< Randomly generated value used to obscure the age of the ticket */
-    uint8_t MBEDTLS_PRIVATE(resumption_key_len);            /*!< resumption_key length */
+    uint32_t MBEDTLS_PRIVATE(ticket_age_add);     /*!< Randomly generated value used to obscure the age of the ticket */
+    uint8_t MBEDTLS_PRIVATE(ticket_flags);        /*!< Ticket flags */
+    uint8_t MBEDTLS_PRIVATE(resumption_key_len);  /*!< resumption_key length */
     unsigned char MBEDTLS_PRIVATE(resumption_key)[MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN];
 
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && defined(MBEDTLS_SSL_CLI_C)
     char *MBEDTLS_PRIVATE(hostname);             /*!< host name binded with tickets */
 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION && MBEDTLS_SSL_CLI_C */
 
-#if defined(MBEDTLS_HAVE_TIME)
-#if defined(MBEDTLS_SSL_CLI_C)
-    mbedtls_ms_time_t MBEDTLS_PRIVATE(ticket_reception_time);   /*!< time when ticket was received. */
+#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_CLI_C)
+    /*! Time in milliseconds when the last ticket was received. */
+    mbedtls_ms_time_t MBEDTLS_PRIVATE(ticket_reception_time);
 #endif
-#if defined(MBEDTLS_SSL_SRV_C)
-    mbedtls_ms_time_t MBEDTLS_PRIVATE(ticket_creation_time);    /*!< time when ticket was created. */
-#endif
-#endif /* MBEDTLS_HAVE_TIME */
-
 #endif /*  MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */
 
 #if defined(MBEDTLS_SSL_EARLY_DATA)
@@ -2630,6 +2646,34 @@
                                          mbedtls_ssl_ticket_write_t *f_ticket_write,
                                          mbedtls_ssl_ticket_parse_t *f_ticket_parse,
                                          void *p_ticket);
+
+#if defined(MBEDTLS_HAVE_TIME)
+/**
+ * \brief Get the creation time of a session ticket.
+ *
+ * \note See the documentation of \c ticket_creation_time for information about
+ *       the intended usage of this function.
+ *
+ * \param session  SSL session
+ * \param ticket_creation_time  On exit, holds the ticket creation time in
+ *                              milliseconds.
+ *
+ * \return         0 on success,
+ *                 MBEDTLS_ERR_SSL_BAD_INPUT_DATA if an input is not valid.
+ */
+static inline int mbedtls_ssl_session_get_ticket_creation_time(
+    mbedtls_ssl_session *session, mbedtls_ms_time_t *ticket_creation_time)
+{
+    if (session == NULL || ticket_creation_time == NULL ||
+        session->MBEDTLS_PRIVATE(endpoint) != MBEDTLS_SSL_IS_SERVER) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    *ticket_creation_time = session->MBEDTLS_PRIVATE(ticket_creation_time);
+
+    return 0;
+}
+#endif /* MBEDTLS_HAVE_TIME */
 #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */
 
 /**
@@ -4737,7 +4781,7 @@
  * \param ssl      The SSL context representing the connection for which to
  *                 to export a session structure for later resumption.
  * \param session  The target structure in which to store the exported session.
- *                 This must have been initialized with mbedtls_ssl_init_session()
+ *                 This must have been initialized with mbedtls_ssl_session_init()
  *                 but otherwise be unused.
  *
  * \note           This function can handle a variety of mechanisms for session
diff --git a/include/mbedtls/ssl_ticket.h b/include/mbedtls/ssl_ticket.h
index 6d59c12..5842049 100644
--- a/include/mbedtls/ssl_ticket.h
+++ b/include/mbedtls/ssl_ticket.h
@@ -50,6 +50,10 @@
 #if defined(MBEDTLS_HAVE_TIME)
     mbedtls_time_t MBEDTLS_PRIVATE(generation_time); /*!< key generation timestamp (seconds) */
 #endif
+    /*! Lifetime of the key in seconds. This is also the lifetime of the
+     *  tickets created under that key.
+     */
+    uint32_t MBEDTLS_PRIVATE(lifetime);
 #if !defined(MBEDTLS_USE_PSA_CRYPTO)
     mbedtls_cipher_context_t MBEDTLS_PRIVATE(ctx);   /*!< context for auth enc/decryption    */
 #else
diff --git a/include/mbedtls/x509.h b/include/mbedtls/x509.h
index be63612..453f598 100644
--- a/include/mbedtls/x509.h
+++ b/include/mbedtls/x509.h
@@ -322,9 +322,151 @@
  */
 int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn);
 
+/**
+ * \brief            Convert the certificate DN string \p name into
+ *                   a linked list of mbedtls_x509_name (equivalent to
+ *                   mbedtls_asn1_named_data).
+ *
+ * \note             This function allocates a linked list, and places the head
+ *                   pointer in \p head. This list must later be freed by a
+ *                   call to mbedtls_asn1_free_named_data_list().
+ *
+ * \param[out] head  Address in which to store the pointer to the head of the
+ *                   allocated list of mbedtls_x509_name
+ * \param[in] name   The string representation of a DN to convert
+ *
+ * \return           0 on success, or a negative error code.
+ */
 int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name);
 
 /**
+ * \brief          Return the next relative DN in an X509 name.
+ *
+ * \note           Intended use is to compare function result to dn->next
+ *                 in order to detect boundaries of multi-valued RDNs.
+ *
+ * \param dn       Current node in the X509 name
+ *
+ * \return         Pointer to the first attribute-value pair of the
+ *                 next RDN in sequence, or NULL if end is reached.
+ */
+static inline mbedtls_x509_name *mbedtls_x509_dn_get_next(
+    mbedtls_x509_name *dn)
+{
+    while (dn->MBEDTLS_PRIVATE(next_merged) && dn->next != NULL) {
+        dn = dn->next;
+    }
+    return dn->next;
+}
+
+/**
+ * \brief          Store the certificate serial in printable form into buf;
+ *                 no more than size characters will be written.
+ *
+ * \param buf      Buffer to write to
+ * \param size     Maximum size of buffer
+ * \param serial   The X509 serial to represent
+ *
+ * \return         The length of the string written (not including the
+ *                 terminated nul byte), or a negative error code.
+ */
+int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial);
+
+/**
+ * \brief          Compare pair of mbedtls_x509_time.
+ *
+ * \param t1       mbedtls_x509_time to compare
+ * \param t2       mbedtls_x509_time to compare
+ *
+ * \return         < 0 if t1 is before t2
+ *                   0 if t1 equals t2
+ *                 > 0 if t1 is after t2
+ */
+int mbedtls_x509_time_cmp(const mbedtls_x509_time *t1, const mbedtls_x509_time *t2);
+
+#if defined(MBEDTLS_HAVE_TIME_DATE)
+/**
+ * \brief          Fill mbedtls_x509_time with provided mbedtls_time_t.
+ *
+ * \param tt       mbedtls_time_t to convert
+ * \param now      mbedtls_x509_time to fill with converted mbedtls_time_t
+ *
+ * \return         \c 0 on success
+ * \return         A non-zero return value on failure.
+ */
+int mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now);
+#endif /* MBEDTLS_HAVE_TIME_DATE */
+
+/**
+ * \brief          Check a given mbedtls_x509_time against the system time
+ *                 and tell if it's in the past.
+ *
+ * \note           Intended usage is "if( is_past( valid_to ) ) ERROR".
+ *                 Hence the return value of 1 if on internal errors.
+ *
+ * \param to       mbedtls_x509_time to check
+ *
+ * \return         1 if the given time is in the past or an error occurred,
+ *                 0 otherwise.
+ */
+int mbedtls_x509_time_is_past(const mbedtls_x509_time *to);
+
+/**
+ * \brief          Check a given mbedtls_x509_time against the system time
+ *                 and tell if it's in the future.
+ *
+ * \note           Intended usage is "if( is_future( valid_from ) ) ERROR".
+ *                 Hence the return value of 1 if on internal errors.
+ *
+ * \param from     mbedtls_x509_time to check
+ *
+ * \return         1 if the given time is in the future or an error occurred,
+ *                 0 otherwise.
+ */
+int mbedtls_x509_time_is_future(const mbedtls_x509_time *from);
+
+/**
+ * \brief          This function parses an item in the SubjectAlternativeNames
+ *                 extension. Please note that this function might allocate
+ *                 additional memory for a subject alternative name, thus
+ *                 mbedtls_x509_free_subject_alt_name has to be called
+ *                 to dispose of this additional memory afterwards.
+ *
+ * \param san_buf  The buffer holding the raw data item of the subject
+ *                 alternative name.
+ * \param san      The target structure to populate with the parsed presentation
+ *                 of the subject alternative name encoded in \p san_buf.
+ *
+ * \note           Supported GeneralName types, as defined in RFC 5280:
+ *                 "rfc822Name", "dnsName", "directoryName",
+ *                 "uniformResourceIdentifier" and "hardware_module_name"
+ *                 of type "otherName", as defined in RFC 4108.
+ *
+ * \note           This function should be called on a single raw data of
+ *                 subject alternative name. For example, after successful
+ *                 certificate parsing, one must iterate on every item in the
+ *                 \c crt->subject_alt_names sequence, and pass it to
+ *                 this function.
+ *
+ * \warning        The target structure contains pointers to the raw data of the
+ *                 parsed certificate, and its lifetime is restricted by the
+ *                 lifetime of the certificate.
+ *
+ * \return         \c 0 on success
+ * \return         #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported
+ *                 SAN type.
+ * \return         Another negative value for any other failure.
+ */
+int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
+                                        mbedtls_x509_subject_alternative_name *san);
+/**
+ * \brief          Unallocate all data related to subject alternative name
+ *
+ * \param san      SAN structure - extra memory owned by this structure will be freed
+ */
+void mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san);
+
+/**
  * \brief          This function parses a CN string as an IP address.
  *
  * \param cn       The CN string to parse. CN string MUST be null-terminated.
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index fe10ee0..73889e0 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -119,8 +119,9 @@
  * value in the structure.
  * The persistent key will be written to storage when the attribute
  * structure is passed to a key creation function such as
- * psa_import_key(), psa_generate_key(),
- * psa_key_derivation_output_key() or psa_copy_key().
+ * psa_import_key(), psa_generate_key(), psa_generate_key_ext(),
+ * psa_key_derivation_output_key(), psa_key_derivation_output_key_ext()
+ * or psa_copy_key().
  *
  * This function may be declared as `static` (i.e. without external
  * linkage). This function may be provided as a function-like macro,
@@ -163,8 +164,9 @@
  * value in the structure.
  * The persistent key will be written to storage when the attribute
  * structure is passed to a key creation function such as
- * psa_import_key(), psa_generate_key(),
- * psa_key_derivation_output_key() or psa_copy_key().
+ * psa_import_key(), psa_generate_key(), psa_generate_key_ext(),
+ * psa_key_derivation_output_key(), psa_key_derivation_output_key_ext()
+ * or psa_copy_key().
  *
  * This function may be declared as `static` (i.e. without external
  * linkage). This function may be provided as a function-like macro,
@@ -3226,7 +3228,8 @@
  *    psa_key_derivation_set_capacity(). You may do this before, in the middle
  *    of or after providing inputs. For some algorithms, this step is mandatory
  *    because the output depends on the maximum capacity.
- * -# To derive a key, call psa_key_derivation_output_key().
+ * -# To derive a key, call psa_key_derivation_output_key() or
+ *    psa_key_derivation_output_key_ext().
  *    To derive a byte string for a different purpose, call
  *    psa_key_derivation_output_bytes().
  *    Successive calls to these functions use successive output bytes
@@ -3449,7 +3452,8 @@
  * \note Once all inputs steps are completed, the operations will allow:
  * - psa_key_derivation_output_bytes() if each input was either a direct input
  *   or  a key with #PSA_KEY_USAGE_DERIVE set;
- * - psa_key_derivation_output_key() if the input for step
+ * - psa_key_derivation_output_key() or psa_key_derivation_output_key_ext()
+ *   if the input for step
  *   #PSA_KEY_DERIVATION_INPUT_SECRET or #PSA_KEY_DERIVATION_INPUT_PASSWORD
  *   was from a key slot with #PSA_KEY_USAGE_DERIVE and each other input was
  *   either a direct input or a key with #PSA_KEY_USAGE_DERIVE set;
@@ -3697,6 +3701,11 @@
  * Future versions of this specification may include additional restrictions
  * on the derived key based on the attributes and strength of the secret key.
  *
+ * \note This function is equivalent to calling
+ *       psa_key_derivation_output_key_ext()
+ *       with the production parameters #PSA_KEY_PRODUCTION_PARAMETERS_INIT
+ *       and `params_data_length == 0` (i.e. `params->data` is empty).
+ *
  * \param[in] attributes    The attributes for the new key.
  *                          If the key type to be created is
  *                          #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in
@@ -3750,6 +3759,83 @@
     psa_key_derivation_operation_t *operation,
     mbedtls_svc_key_id_t *key);
 
+/** Derive a key from an ongoing key derivation operation with custom
+ *  production parameters.
+ *
+ * See the description of psa_key_derivation_out_key() for the operation of
+ * this function with the default production parameters.
+ * Mbed TLS currently does not currently support any non-default production
+ * parameters.
+ *
+ * \note This function is experimental and may change in future minor
+ *       versions of Mbed TLS.
+ *
+ * \param[in] attributes    The attributes for the new key.
+ *                          If the key type to be created is
+ *                          #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in
+ *                          the policy must be the same as in the current
+ *                          operation.
+ * \param[in,out] operation The key derivation operation object to read from.
+ * \param[in] params        Customization parameters for the key derivation.
+ *                          When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT
+ *                          with \p params_data_length = 0,
+ *                          this function is equivalent to
+ *                          psa_key_derivation_output_key().
+ *                          Mbed TLS currently only supports the default
+ *                          production parameters, i.e.
+ *                          #PSA_KEY_PRODUCTION_PARAMETERS_INIT,
+ *                          for all key types.
+ * \param params_data_length
+ *                          Length of `params->data` in bytes.
+ * \param[out] key          On success, an identifier for the newly created
+ *                          key. For persistent keys, this is the key
+ *                          identifier defined in \p attributes.
+ *                          \c 0 on failure.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ *         If the key is persistent, the key material and the key's metadata
+ *         have been saved to persistent storage.
+ * \retval #PSA_ERROR_ALREADY_EXISTS
+ *         This is an attempt to create a persistent key, and there is
+ *         already a persistent key with the given identifier.
+ * \retval #PSA_ERROR_INSUFFICIENT_DATA
+ *         There was not enough data to create the desired key.
+ *         Note that in this case, no output is written to the output buffer.
+ *         The operation's capacity is set to 0, thus subsequent calls to
+ *         this function will not succeed, even with a smaller output buffer.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         The key type or key size is not supported, either by the
+ *         implementation in general or in this particular location.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The provided key attributes are not valid for the operation.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The #PSA_KEY_DERIVATION_INPUT_SECRET or
+ *         #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a
+ *         key; or one of the inputs was a key whose policy didn't allow
+ *         #PSA_KEY_USAGE_DERIVE.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be active and completed
+ *         all required input steps), or the library has not been previously
+ *         initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_key_derivation_output_key_ext(
+    const psa_key_attributes_t *attributes,
+    psa_key_derivation_operation_t *operation,
+    const psa_key_production_parameters_t *params,
+    size_t params_data_length,
+    mbedtls_svc_key_id_t *key);
+
 /** Compare output data from a key derivation operation to an expected value.
  *
  * This function calculates output bytes from a key derivation algorithm and
@@ -3835,7 +3921,8 @@
  *                          and the permitted algorithm must match the
  *                          operation. The value of this key was likely
  *                          computed by a previous call to
- *                          psa_key_derivation_output_key().
+ *                          psa_key_derivation_output_key() or
+ *                          psa_key_derivation_output_key_ext().
  *
  * \retval #PSA_SUCCESS \emptydescription
  * \retval #PSA_ERROR_INVALID_SIGNATURE
@@ -4003,6 +4090,10 @@
  *   between 2^{n-1} and 2^n where n is the bit size specified in the
  *   attributes.
  *
+ * \note This function is equivalent to calling psa_generate_key_ext()
+ *       with the production parameters #PSA_KEY_PRODUCTION_PARAMETERS_INIT
+ *       and `params_data_length == 0` (i.e. `params->data` is empty).
+ *
  * \param[in] attributes    The attributes for the new key.
  * \param[out] key          On success, an identifier for the newly created
  *                          key. For persistent keys, this is the key
@@ -4035,6 +4126,60 @@
 psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
                               mbedtls_svc_key_id_t *key);
 
+/**
+ * \brief Generate a key or key pair using custom production parameters.
+ *
+ * See the description of psa_generate_key() for the operation of this
+ * function with the default production parameters. In addition, this function
+ * supports the following production customizations, described in more detail
+ * in the documentation of ::psa_key_production_parameters_t:
+ *
+ * - RSA keys: generation with a custom public exponent.
+ *
+ * \note This function is experimental and may change in future minor
+ *       versions of Mbed TLS.
+ *
+ * \param[in] attributes    The attributes for the new key.
+ * \param[in] params        Customization parameters for the key generation.
+ *                          When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT
+ *                          with \p params_data_length = 0,
+ *                          this function is equivalent to
+ *                          psa_generate_key().
+ * \param params_data_length
+ *                          Length of `params->data` in bytes.
+ * \param[out] key          On success, an identifier for the newly created
+ *                          key. For persistent keys, this is the key
+ *                          identifier defined in \p attributes.
+ *                          \c 0 on failure.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ *         If the key is persistent, the key material and the key's metadata
+ *         have been saved to persistent storage.
+ * \retval #PSA_ERROR_ALREADY_EXISTS
+ *         This is an attempt to create a persistent key, and there is
+ *         already a persistent key with the given identifier.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes,
+                                  const psa_key_production_parameters_t *params,
+                                  size_t params_data_length,
+                                  mbedtls_svc_key_id_t *key);
+
 /**@}*/
 
 /** \defgroup interruptible_hash Interruptible sign/verify hash
diff --git a/include/psa/crypto_compat.h b/include/psa/crypto_compat.h
index f896fae..2a226c0 100644
--- a/include/psa/crypto_compat.h
+++ b/include/psa/crypto_compat.h
@@ -146,6 +146,83 @@
  */
 psa_status_t psa_close_key(psa_key_handle_t handle);
 
+/** \addtogroup attributes
+ * @{
+ */
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+/** Custom Diffie-Hellman group.
+ *
+ * Mbed TLS does not support custom DH groups.
+ *
+ * \deprecated This value is not useful, so this macro will be removed in
+ *             a future version of the library.
+ */
+#define PSA_DH_FAMILY_CUSTOM                                            \
+    ((psa_dh_family_t) MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(0x7e))
+
+/**
+ * \brief Set domain parameters for a key.
+ *
+ * \deprecated  Mbed TLS no longer supports any domain parameters.
+ *              This function only does the equivalent of
+ *              psa_set_key_type() and will be removed in a future version
+ *              of the library.
+ *
+ * \param[in,out] attributes    Attribute structure where \p type will be set.
+ * \param type                  Key type (a \c PSA_KEY_TYPE_XXX value).
+ * \param[in] data              Ignored.
+ * \param data_length           Must be 0.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ */
+static inline psa_status_t MBEDTLS_DEPRECATED psa_set_key_domain_parameters(
+    psa_key_attributes_t *attributes,
+    psa_key_type_t type, const uint8_t *data, size_t data_length)
+{
+    (void) data;
+    if (data_length != 0) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+    psa_set_key_type(attributes, type);
+    return PSA_SUCCESS;
+}
+
+/**
+ * \brief Get domain parameters for a key.
+ *
+ * \deprecated  Mbed TLS no longer supports any domain parameters.
+ *              This function alwaya has an empty output and will be
+ *              removed in a future version of the library.
+
+ * \param[in] attributes        Ignored.
+ * \param[out] data             Ignored.
+ * \param data_size             Ignored.
+ * \param[out] data_length      Set to 0.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ */
+static inline psa_status_t MBEDTLS_DEPRECATED psa_get_key_domain_parameters(
+    const psa_key_attributes_t *attributes,
+    uint8_t *data, size_t data_size, size_t *data_length)
+{
+    (void) attributes;
+    (void) data;
+    (void) data_size;
+    *data_length = 0;
+    return PSA_SUCCESS;
+}
+
+/** Safe output buffer size for psa_get_key_domain_parameters().
+ *
+ */
+#define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits)      \
+    MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(1u)
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
+/**@}*/
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
index 10a23f6..ac21e3e 100644
--- a/include/psa/crypto_extra.h
+++ b/include/psa/crypto_extra.h
@@ -409,140 +409,11 @@
  * @{
  */
 
-/** Custom Diffie-Hellman group.
- *
- * For keys of type #PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_FAMILY_CUSTOM) or
- * #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_FAMILY_CUSTOM), the group data comes
- * from domain parameters set by psa_set_key_domain_parameters().
- */
-#define PSA_DH_FAMILY_CUSTOM             ((psa_dh_family_t) 0x7e)
-
 /** PAKE operation stages. */
 #define PSA_PAKE_OPERATION_STAGE_SETUP 0
 #define PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS 1
 #define PSA_PAKE_OPERATION_STAGE_COMPUTATION 2
 
-/**
- * \brief Set domain parameters for a key.
- *
- * Some key types require additional domain parameters in addition to
- * the key type identifier and the key size. Use this function instead
- * of psa_set_key_type() when you need to specify domain parameters.
- *
- * The format for the required domain parameters varies based on the key type.
- * Mbed TLS supports the following key type with domain parameters:
- *
- * - For RSA keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY or #PSA_KEY_TYPE_RSA_KEY_PAIR),
- *   the domain parameter data consists of the public exponent,
- *   represented as a big-endian integer with no leading zeros.
- *   This information is used when generating an RSA key pair.
- *   When importing a key, the public exponent is read from the imported
- *   key data and the exponent recorded in the attribute structure is ignored.
- *   As an exception, the public exponent 65537 is represented by an empty
- *   byte string.
- *
- * \note This function may allocate memory or other resources.
- *       Once you have called this function on an attribute structure,
- *       you must call psa_reset_key_attributes() to free these resources.
- *
- * \note This is an experimental extension to the interface. It may change
- *       in future versions of the library.
- *
- * \note Due to an implementation limitation, domain parameters are ignored
- *       for keys that are managed by a driver.
- *
- * \param[in,out] attributes    Attribute structure where the specified domain
- *                              parameters will be stored.
- *                              If this function fails, the content of
- *                              \p attributes is not modified.
- * \param type                  Key type (a \c PSA_KEY_TYPE_XXX value).
- * \param[in] data              Buffer containing the key domain parameters.
- *                              The content of this buffer is interpreted
- *                              according to \p type as described above.
- * \param data_length           Size of the \p data buffer in bytes.
- *
- * \retval #PSA_SUCCESS \emptydescription
- * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
- * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
- */
-#if !defined(PSA_SET_KEY_DOMAIN_PARAMETERS)
-#define PSA_SET_KEY_DOMAIN_PARAMETERS
-psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes,
-                                           psa_key_type_t type,
-                                           const uint8_t *data,
-                                           size_t data_length);
-#endif /* PSA_SET_KEY_DOMAIN_PARAMETERS */
-
-/**
- * \brief Get domain parameters for a key.
- *
- * Get the domain parameters for a key with this function, if any. The format
- * of the domain parameters written to \p data is specified in the
- * documentation for psa_set_key_domain_parameters().
- *
- * \note This is an experimental extension to the interface. It may change
- *       in future versions of the library.
- *
- * \note Due to an implementation limitation, domain parameters are not
- *       supported with keys that are managed by a driver.
- *
- * \param[in] attributes        The key attribute structure to query.
- * \param[out] data             On success, the key domain parameters.
- * \param data_size             Size of the \p data buffer in bytes.
- *                              The buffer is guaranteed to be large
- *                              enough if its size in bytes is at least
- *                              the value given by
- *                              PSA_KEY_DOMAIN_PARAMETERS_SIZE().
- * \param[out] data_length      On success, the number of bytes
- *                              that make up the key domain parameters data.
- *
- * \retval #PSA_SUCCESS \emptydescription
- * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription
- * \retval #PSA_ERROR_NOT_SUPPORTED
- *         The key is managed by a driver.
- */
-psa_status_t psa_get_key_domain_parameters(
-    const psa_key_attributes_t *attributes,
-    uint8_t *data,
-    size_t data_size,
-    size_t *data_length);
-
-/** Safe output buffer size for psa_get_key_domain_parameters().
- *
- * This macro returns a compile-time constant if its arguments are
- * compile-time constants.
- *
- * \warning This function may call its arguments multiple times or
- *          zero times, so you should not pass arguments that contain
- *          side effects.
- *
- * \note This is an experimental extension to the interface. It may change
- *       in future versions of the library.
- *
- * \param key_type  A supported key type.
- * \param key_bits  The size of the key in bits.
- *
- * \return If the parameters are valid and supported, return
- *         a buffer size in bytes that guarantees that
- *         psa_get_key_domain_parameters() will not fail with
- *         #PSA_ERROR_BUFFER_TOO_SMALL.
- *         If the parameters are a valid combination that is not supported
- *         by the implementation, this macro shall return either a
- *         sensible size or 0.
- *         If the parameters are not valid, the
- *         return value is unspecified.
- */
-#define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits)              \
-    (PSA_KEY_TYPE_IS_RSA(key_type) ? sizeof(int) :                      \
-     PSA_KEY_TYPE_IS_DH(key_type) ? PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \
-     PSA_KEY_TYPE_IS_DSA(key_type) ? PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \
-     0)
-#define PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits)     \
-    (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 3 /*without optional parts*/)
-#define PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits)    \
-    (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 2 /*p, g*/ + 34 /*q*/)
-
 /**@}*/
 
 
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
index 34d072b..683d841 100644
--- a/include/psa/crypto_struct.h
+++ b/include/psa/crypto_struct.h
@@ -223,6 +223,22 @@
     return v;
 }
 
+struct psa_key_production_parameters_s {
+    /* Future versions may add other fields in this structure. */
+    uint32_t flags;
+    uint8_t data[];
+};
+
+/** The default production parameters for key generation or key derivation.
+ *
+ * Calling psa_generate_key_ext() or psa_key_derivation_output_key_ext()
+ * with `params=PSA_KEY_PRODUCTION_PARAMETERS_INIT` and
+ * `params_data_length == 0` is equivalent to
+ * calling psa_generate_key() or psa_key_derivation_output_key()
+ * respectively.
+ */
+#define PSA_KEY_PRODUCTION_PARAMETERS_INIT { 0 }
+
 struct psa_key_policy_s {
     psa_key_usage_t MBEDTLS_PRIVATE(usage);
     psa_algorithm_t MBEDTLS_PRIVATE(alg);
@@ -302,20 +318,6 @@
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
     psa_key_slot_number_t MBEDTLS_PRIVATE(slot_number);
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
-    /* Unlike normal buffers, there are three cases for domain_parameters
-     * and domain_parameters_size:
-     * - domain_parameters_size == SIZE_MAX && domain_parameters == NULL:
-     *   Access to domain parameters is not supported for this key.
-     *   This is a hack which should not exist, intended for keys managed
-     *   by a driver, because drivers don't support domain parameters.
-     * - domain_parameters_size == 0 && domain_parameters == NULL:
-     *   The domain parameters are empty.
-     * - domain_parameters_size > 0 &&
-     *   domain_parameters == valid pointer to domain_parameters_size bytes:
-     *   The domain parameters are non-empty.
-     */
-    void *MBEDTLS_PRIVATE(domain_parameters);
-    size_t MBEDTLS_PRIVATE(domain_parameters_size);
     /* With client/service separation, struct psa_key_attributes_s is
      * marshalled through a transport channel between the client and
      * service side implementation of the PSA Crypto APIs, thus having
@@ -326,9 +328,9 @@
 };
 
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-#define PSA_KEY_ATTRIBUTES_INIT { 0, NULL, 0, PSA_CORE_KEY_ATTRIBUTES_INIT }
+#define PSA_KEY_ATTRIBUTES_INIT { 0, PSA_CORE_KEY_ATTRIBUTES_INIT }
 #else
-#define PSA_KEY_ATTRIBUTES_INIT { NULL, 0, PSA_CORE_KEY_ATTRIBUTES_INIT }
+#define PSA_KEY_ATTRIBUTES_INIT { PSA_CORE_KEY_ATTRIBUTES_INIT }
 #endif
 
 static inline struct psa_key_attributes_s psa_key_attributes_init(void)
@@ -421,29 +423,10 @@
     return attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg);
 }
 
-/* This function is declared in crypto_extra.h, which comes after this
- * header file, but we need the function here, so repeat the declaration. */
-#if !defined(PSA_SET_KEY_DOMAIN_PARAMETERS)
-#define PSA_SET_KEY_DOMAIN_PARAMETERS
-psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes,
-                                           psa_key_type_t type,
-                                           const uint8_t *data,
-                                           size_t data_length);
-#endif /* PSA_SET_KEY_DOMAIN_PARAMETERS */
-
 static inline void psa_set_key_type(psa_key_attributes_t *attributes,
                                     psa_key_type_t type)
 {
-    if (attributes->MBEDTLS_PRIVATE(domain_parameters) == NULL) {
-        /* Common case: quick path */
-        attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(type) = type;
-    } else {
-        /* Call the bigger function to free the old domain parameters.
-         * Ignore any errors which may arise due to type requiring
-         * non-default domain parameters, since this function can't
-         * report errors. */
-        (void) psa_set_key_domain_parameters(attributes, type, NULL, 0);
-    }
+    attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(type) = type;
 }
 
 static inline psa_key_type_t psa_get_key_type(
diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h
index e2ebd8a..31ea686 100644
--- a/include/psa/crypto_types.h
+++ b/include/psa/crypto_types.h
@@ -455,6 +455,30 @@
  */
 typedef uint16_t psa_key_derivation_step_t;
 
+/** \brief Custom parameters for key generation or key derivation.
+ *
+ * This is a structure type with at least the following fields:
+ *
+ * - \c flags: an unsigned integer type. 0 for the default production parameters.
+ * - \c data: a flexible array of bytes.
+ *
+ * The interpretation of this structure depend on the type of the
+ * created key.
+ *
+ * - #PSA_KEY_TYPE_RSA_KEY_PAIR:
+ *     - \c flags: must be 0.
+ *     - \c data: the public exponent, in little-endian order.
+ *       This must be an odd integer and must not be 1.
+ *       Implementations must support 65535, should support 3 and may
+ *       support other values.
+ *       When not using a driver, Mbed TLS supports values up to \c INT_MAX.
+ *       If this is empty or if the custom production parameters are omitted
+ *       altogether, the default value 65537 is used.
+ * - Other key types: reserved for future use. \c flags must be 0.
+ *
+ */
+typedef struct psa_key_production_parameters_s psa_key_production_parameters_t;
+
 /**@}*/
 
 #endif /* PSA_CRYPTO_TYPES_H */
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index f311acb..1d678db 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -413,7 +413,7 @@
     ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR)
 /** The public key type corresponding to a key pair type.
  *
- * You may also pass a key pair type as \p type, it will be left unchanged.
+ * You may also pass a public key type as \p type, it will be left unchanged.
  *
  * \param type      A public key type or key pair type.
  *
diff --git a/library/gcm.c b/library/gcm.c
index 033cb59..90c1d1d 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -41,6 +41,12 @@
 
 #if !defined(MBEDTLS_GCM_ALT)
 
+/* Used to select the acceleration mechanism */
+#define MBEDTLS_GCM_ACC_SMALLTABLE  0
+#define MBEDTLS_GCM_ACC_LARGETABLE  1
+#define MBEDTLS_GCM_ACC_AESNI       2
+#define MBEDTLS_GCM_ACC_AESCE       3
+
 /*
  * Initialize a context
  */
@@ -49,6 +55,39 @@
     memset(ctx, 0, sizeof(mbedtls_gcm_context));
 }
 
+static inline void gcm_set_acceleration(mbedtls_gcm_context *ctx)
+{
+#if defined(MBEDTLS_GCM_LARGE_TABLE)
+    ctx->acceleration = MBEDTLS_GCM_ACC_LARGETABLE;
+#else
+    ctx->acceleration = MBEDTLS_GCM_ACC_SMALLTABLE;
+#endif
+
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
+    /* With CLMUL support, we need only h, not the rest of the table */
+    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
+        ctx->acceleration = MBEDTLS_GCM_ACC_AESNI;
+    }
+#endif
+
+#if defined(MBEDTLS_AESCE_HAVE_CODE)
+    if (MBEDTLS_AESCE_HAS_SUPPORT()) {
+        ctx->acceleration = MBEDTLS_GCM_ACC_AESCE;
+    }
+#endif
+}
+
+static inline void gcm_gen_table_rightshift(uint64_t dst[2], const uint64_t src[2])
+{
+    uint8_t *u8Dst = (uint8_t *) dst;
+    uint8_t *u8Src = (uint8_t *) src;
+
+    MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[1], 0) >> 1, &dst[1], 0);
+    u8Dst[8] |= (u8Src[7] & 0x01) << 7;
+    MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[0], 0) >> 1, &dst[0], 0);
+    u8Dst[0] ^= (u8Src[15] & 0x01) ? 0xE1 : 0;
+}
+
 /*
  * Precompute small multiples of H, that is set
  *      HH[i] || HL[i] = H times i,
@@ -60,11 +99,8 @@
 static int gcm_gen_table(mbedtls_gcm_context *ctx)
 {
     int ret, i, j;
-    uint64_t hi, lo;
-    uint64_t vl, vh;
-    unsigned char h[16];
-
-    memset(h, 0, 16);
+    uint64_t u64h[2] = { 0 };
+    uint8_t *h = (uint8_t *) u64h;
 
 #if defined(MBEDTLS_BLOCK_CIPHER_C)
     ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, h, h);
@@ -76,53 +112,48 @@
         return ret;
     }
 
-    /* pack h as two 64-bits ints, big-endian */
-    hi = MBEDTLS_GET_UINT32_BE(h,  0);
-    lo = MBEDTLS_GET_UINT32_BE(h,  4);
-    vh = (uint64_t) hi << 32 | lo;
+    gcm_set_acceleration(ctx);
 
-    hi = MBEDTLS_GET_UINT32_BE(h,  8);
-    lo = MBEDTLS_GET_UINT32_BE(h,  12);
-    vl = (uint64_t) hi << 32 | lo;
+    /* MBEDTLS_GCM_HTABLE_SIZE/2 = 1000 corresponds to 1 in GF(2^128) */
+    ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][0] = u64h[0];
+    ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][1] = u64h[1];
 
-    /* 8 = 1000 corresponds to 1 in GF(2^128) */
-    ctx->HL[8] = vl;
-    ctx->HH[8] = vh;
-
+    switch (ctx->acceleration) {
 #if defined(MBEDTLS_AESNI_HAVE_CODE)
-    /* With CLMUL support, we need only h, not the rest of the table */
-    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
-        return 0;
-    }
+        case MBEDTLS_GCM_ACC_AESNI:
+            return 0;
 #endif
 
 #if defined(MBEDTLS_AESCE_HAVE_CODE)
-    if (MBEDTLS_AESCE_HAS_SUPPORT()) {
-        return 0;
-    }
+        case MBEDTLS_GCM_ACC_AESCE:
+            return 0;
 #endif
 
-    /* 0 corresponds to 0 in GF(2^128) */
-    ctx->HH[0] = 0;
-    ctx->HL[0] = 0;
+        default:
+            /* 0 corresponds to 0 in GF(2^128) */
+            ctx->H[0][0] = 0;
+            ctx->H[0][1] = 0;
 
-    for (i = 4; i > 0; i >>= 1) {
-        uint32_t T = (vl & 1) * 0xe1000000U;
-        vl  = (vh << 63) | (vl >> 1);
-        vh  = (vh >> 1) ^ ((uint64_t) T << 32);
+            for (i = MBEDTLS_GCM_HTABLE_SIZE/4; i > 0; i >>= 1) {
+                gcm_gen_table_rightshift(ctx->H[i], ctx->H[i*2]);
+            }
 
-        ctx->HL[i] = vl;
-        ctx->HH[i] = vh;
-    }
+#if !defined(MBEDTLS_GCM_LARGE_TABLE)
+            /* pack elements of H as 64-bits ints, big-endian */
+            for (i = MBEDTLS_GCM_HTABLE_SIZE/2; i > 0; i >>= 1) {
+                MBEDTLS_PUT_UINT64_BE(ctx->H[i][0], &ctx->H[i][0], 0);
+                MBEDTLS_PUT_UINT64_BE(ctx->H[i][1], &ctx->H[i][1], 0);
+            }
+#endif
 
-    for (i = 2; i <= 8; i *= 2) {
-        uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
-        vh = *HiH;
-        vl = *HiL;
-        for (j = 1; j < i; j++) {
-            HiH[j] = vh ^ ctx->HH[j];
-            HiL[j] = vl ^ ctx->HL[j];
-        }
+            for (i = 2; i < MBEDTLS_GCM_HTABLE_SIZE; i <<= 1) {
+                for (j = 1; j < i; j++) {
+                    mbedtls_xor_no_simd((unsigned char *) ctx->H[i+j],
+                                        (unsigned char *) ctx->H[i],
+                                        (unsigned char *) ctx->H[j],
+                                        16);
+                }
+            }
     }
 
     return 0;
@@ -181,6 +212,80 @@
     return 0;
 }
 
+#if defined(MBEDTLS_GCM_LARGE_TABLE)
+static const uint16_t last8[256] = {
+    0x0000, 0xc201, 0x8403, 0x4602, 0x0807, 0xca06, 0x8c04, 0x4e05,
+    0x100e, 0xd20f, 0x940d, 0x560c, 0x1809, 0xda08, 0x9c0a, 0x5e0b,
+    0x201c, 0xe21d, 0xa41f, 0x661e, 0x281b, 0xea1a, 0xac18, 0x6e19,
+    0x3012, 0xf213, 0xb411, 0x7610, 0x3815, 0xfa14, 0xbc16, 0x7e17,
+    0x4038, 0x8239, 0xc43b, 0x063a, 0x483f, 0x8a3e, 0xcc3c, 0x0e3d,
+    0x5036, 0x9237, 0xd435, 0x1634, 0x5831, 0x9a30, 0xdc32, 0x1e33,
+    0x6024, 0xa225, 0xe427, 0x2626, 0x6823, 0xaa22, 0xec20, 0x2e21,
+    0x702a, 0xb22b, 0xf429, 0x3628, 0x782d, 0xba2c, 0xfc2e, 0x3e2f,
+    0x8070, 0x4271, 0x0473, 0xc672, 0x8877, 0x4a76, 0x0c74, 0xce75,
+    0x907e, 0x527f, 0x147d, 0xd67c, 0x9879, 0x5a78, 0x1c7a, 0xde7b,
+    0xa06c, 0x626d, 0x246f, 0xe66e, 0xa86b, 0x6a6a, 0x2c68, 0xee69,
+    0xb062, 0x7263, 0x3461, 0xf660, 0xb865, 0x7a64, 0x3c66, 0xfe67,
+    0xc048, 0x0249, 0x444b, 0x864a, 0xc84f, 0x0a4e, 0x4c4c, 0x8e4d,
+    0xd046, 0x1247, 0x5445, 0x9644, 0xd841, 0x1a40, 0x5c42, 0x9e43,
+    0xe054, 0x2255, 0x6457, 0xa656, 0xe853, 0x2a52, 0x6c50, 0xae51,
+    0xf05a, 0x325b, 0x7459, 0xb658, 0xf85d, 0x3a5c, 0x7c5e, 0xbe5f,
+    0x00e1, 0xc2e0, 0x84e2, 0x46e3, 0x08e6, 0xcae7, 0x8ce5, 0x4ee4,
+    0x10ef, 0xd2ee, 0x94ec, 0x56ed, 0x18e8, 0xdae9, 0x9ceb, 0x5eea,
+    0x20fd, 0xe2fc, 0xa4fe, 0x66ff, 0x28fa, 0xeafb, 0xacf9, 0x6ef8,
+    0x30f3, 0xf2f2, 0xb4f0, 0x76f1, 0x38f4, 0xfaf5, 0xbcf7, 0x7ef6,
+    0x40d9, 0x82d8, 0xc4da, 0x06db, 0x48de, 0x8adf, 0xccdd, 0x0edc,
+    0x50d7, 0x92d6, 0xd4d4, 0x16d5, 0x58d0, 0x9ad1, 0xdcd3, 0x1ed2,
+    0x60c5, 0xa2c4, 0xe4c6, 0x26c7, 0x68c2, 0xaac3, 0xecc1, 0x2ec0,
+    0x70cb, 0xb2ca, 0xf4c8, 0x36c9, 0x78cc, 0xbacd, 0xfccf, 0x3ece,
+    0x8091, 0x4290, 0x0492, 0xc693, 0x8896, 0x4a97, 0x0c95, 0xce94,
+    0x909f, 0x529e, 0x149c, 0xd69d, 0x9898, 0x5a99, 0x1c9b, 0xde9a,
+    0xa08d, 0x628c, 0x248e, 0xe68f, 0xa88a, 0x6a8b, 0x2c89, 0xee88,
+    0xb083, 0x7282, 0x3480, 0xf681, 0xb884, 0x7a85, 0x3c87, 0xfe86,
+    0xc0a9, 0x02a8, 0x44aa, 0x86ab, 0xc8ae, 0x0aaf, 0x4cad, 0x8eac,
+    0xd0a7, 0x12a6, 0x54a4, 0x96a5, 0xd8a0, 0x1aa1, 0x5ca3, 0x9ea2,
+    0xe0b5, 0x22b4, 0x64b6, 0xa6b7, 0xe8b2, 0x2ab3, 0x6cb1, 0xaeb0,
+    0xf0bb, 0x32ba, 0x74b8, 0xb6b9, 0xf8bc, 0x3abd, 0x7cbf, 0xbebe
+};
+
+static void gcm_mult_largetable(uint8_t *output, const uint8_t *x, uint64_t H[256][2])
+{
+    int i;
+    uint64_t u64z[2];
+    uint16_t *u16z = (uint16_t *) u64z;
+    uint8_t *u8z = (uint8_t *) u64z;
+    uint8_t rem;
+
+    u64z[0] = 0;
+    u64z[1] = 0;
+
+    if (MBEDTLS_IS_BIG_ENDIAN) {
+        for (i = 15; i > 0; i--) {
+            mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16);
+            rem = u8z[15];
+
+            u64z[1] >>= 8;
+            u8z[8] = u8z[7];
+            u64z[0] >>= 8;
+
+            u16z[0] ^= MBEDTLS_GET_UINT16_LE(&last8[rem], 0);
+        }
+    } else {
+        for (i = 15; i > 0; i--) {
+            mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16);
+            rem = u8z[15];
+
+            u64z[1] <<= 8;
+            u8z[8] = u8z[7];
+            u64z[0] <<= 8;
+
+            u16z[0] ^= last8[rem];
+        }
+    }
+
+    mbedtls_xor_no_simd(output, u8z, (uint8_t *) H[x[0]], 16);
+}
+#else
 /*
  * Shoup's method for multiplication use this table with
  *      last4[x] = x times P^128
@@ -194,6 +299,47 @@
     0x9180, 0x8da0, 0xa9c0, 0xb5e0
 };
 
+static void gcm_mult_smalltable(uint8_t *output, const uint8_t *x, uint64_t H[16][2])
+{
+    int i = 0;
+    unsigned char lo, hi, rem;
+    uint64_t u64z[2];
+    const uint64_t *pu64z = NULL;
+    uint8_t *u8z = (uint8_t *) u64z;
+
+    lo = x[15] & 0xf;
+    hi = (x[15] >> 4) & 0xf;
+
+    pu64z = H[lo];
+
+    rem = (unsigned char) pu64z[1] & 0xf;
+    u64z[1] = (pu64z[0] << 60) | (pu64z[1] >> 4);
+    u64z[0] = (pu64z[0] >> 4);
+    u64z[0] ^= (uint64_t) last4[rem] << 48;
+    mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);
+
+    for (i = 14; i >= 0; i--) {
+        lo = x[i] & 0xf;
+        hi = (x[i] >> 4) & 0xf;
+
+        rem = (unsigned char) u64z[1] & 0xf;
+        u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);
+        u64z[0] = (u64z[0] >> 4);
+        u64z[0] ^= (uint64_t) last4[rem] << 48;
+        mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[lo], 16);
+
+        rem = (unsigned char) u64z[1] & 0xf;
+        u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);
+        u64z[0] = (u64z[0] >> 4);
+        u64z[0] ^= (uint64_t) last4[rem] << 48;
+        mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);
+    }
+
+    MBEDTLS_PUT_UINT64_BE(u64z[0], output, 0);
+    MBEDTLS_PUT_UINT64_BE(u64z[1], output, 8);
+}
+#endif
+
 /*
  * Sets output to x times H using the precomputed tables.
  * x and output are seen as elements of GF(2^128) as in [MGV].
@@ -201,71 +347,31 @@
 static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
                      unsigned char output[16])
 {
-    int i = 0;
-    unsigned char lo, hi, rem;
-    uint64_t zh, zl;
-
+    switch (ctx->acceleration) {
 #if defined(MBEDTLS_AESNI_HAVE_CODE)
-    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
-        unsigned char h[16];
-
-        /* mbedtls_aesni_gcm_mult needs big-endian input */
-        MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h,  0);
-        MBEDTLS_PUT_UINT32_BE(ctx->HH[8],       h,  4);
-        MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h,  8);
-        MBEDTLS_PUT_UINT32_BE(ctx->HL[8],       h, 12);
-
-        mbedtls_aesni_gcm_mult(output, x, h);
-        return;
-    }
-#endif /* MBEDTLS_AESNI_HAVE_CODE */
-
-#if defined(MBEDTLS_AESCE_HAVE_CODE)
-    if (MBEDTLS_AESCE_HAS_SUPPORT()) {
-        unsigned char h[16];
-
-        /* mbedtls_aesce_gcm_mult needs big-endian input */
-        MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h,  0);
-        MBEDTLS_PUT_UINT32_BE(ctx->HH[8],       h,  4);
-        MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h,  8);
-        MBEDTLS_PUT_UINT32_BE(ctx->HL[8],       h, 12);
-
-        mbedtls_aesce_gcm_mult(output, x, h);
-        return;
-    }
+        case MBEDTLS_GCM_ACC_AESNI:
+            mbedtls_aesni_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);
+            break;
 #endif
 
-    lo = x[15] & 0xf;
+#if defined(MBEDTLS_AESCE_HAVE_CODE)
+        case MBEDTLS_GCM_ACC_AESCE:
+            mbedtls_aesce_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);
+            break;
+#endif
 
-    zh = ctx->HH[lo];
-    zl = ctx->HL[lo];
-
-    for (i = 15; i >= 0; i--) {
-        lo = x[i] & 0xf;
-        hi = (x[i] >> 4) & 0xf;
-
-        if (i != 15) {
-            rem = (unsigned char) zl & 0xf;
-            zl = (zh << 60) | (zl >> 4);
-            zh = (zh >> 4);
-            zh ^= (uint64_t) last4[rem] << 48;
-            zh ^= ctx->HH[lo];
-            zl ^= ctx->HL[lo];
-
-        }
-
-        rem = (unsigned char) zl & 0xf;
-        zl = (zh << 60) | (zl >> 4);
-        zh = (zh >> 4);
-        zh ^= (uint64_t) last4[rem] << 48;
-        zh ^= ctx->HH[hi];
-        zl ^= ctx->HL[hi];
+#if defined(MBEDTLS_GCM_LARGE_TABLE)
+        case MBEDTLS_GCM_ACC_LARGETABLE:
+            gcm_mult_largetable(output, x, ctx->H);
+            break;
+#else
+        case MBEDTLS_GCM_ACC_SMALLTABLE:
+            gcm_mult_smalltable(output, x, ctx->H);
+            break;
+#endif
     }
 
-    MBEDTLS_PUT_UINT32_BE(zh >> 32, output, 0);
-    MBEDTLS_PUT_UINT32_BE(zh, output, 4);
-    MBEDTLS_PUT_UINT32_BE(zl >> 32, output, 8);
-    MBEDTLS_PUT_UINT32_BE(zl, output, 12);
+    return;
 }
 
 int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
diff --git a/library/pem.c b/library/pem.c
index 539134c..0fee5df 100644
--- a/library/pem.c
+++ b/library/pem.c
@@ -240,6 +240,29 @@
 }
 #endif /* MBEDTLS_AES_C */
 
+#if defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C)
+static int pem_check_pkcs_padding(unsigned char *input, size_t input_len, size_t *data_len)
+{
+    /* input_len > 0 is guaranteed by mbedtls_pem_read_buffer(). */
+    size_t pad_len = input[input_len - 1];
+    size_t i;
+
+    if (pad_len > input_len) {
+        return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
+    }
+
+    *data_len = input_len - pad_len;
+
+    for (i = *data_len; i < input_len; i++) {
+        if (input[i] != pad_len) {
+            return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
+        }
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_DES_C || MBEDTLS_AES_C */
+
 #endif /* PEM_RFC1421 */
 
 int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer,
@@ -389,6 +412,10 @@
         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret);
     }
 
+    if (len == 0) {
+        return MBEDTLS_ERR_PEM_BAD_INPUT_DATA;
+    }
+
     if ((buf = mbedtls_calloc(1, len)) == NULL) {
         return MBEDTLS_ERR_PEM_ALLOC_FAILED;
     }
@@ -426,20 +453,20 @@
 #endif /* MBEDTLS_AES_C */
 
         if (ret != 0) {
-            mbedtls_free(buf);
+            mbedtls_zeroize_and_free(buf, len);
             return ret;
         }
 
-        /*
-         * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3
-         * length bytes (allow 4 to be sure) in all known use cases.
-         *
-         * Use that as a heuristic to try to detect password mismatches.
-         */
-        if (len <= 2 || buf[0] != 0x30 || buf[1] > 0x83) {
+        /* Check PKCS padding and update data length based on padding info.
+         * This can be used to detect invalid padding data and password
+         * mismatches. */
+        size_t unpadded_len;
+        ret = pem_check_pkcs_padding(buf, len, &unpadded_len);
+        if (ret != 0) {
             mbedtls_zeroize_and_free(buf, len);
-            return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
+            return ret;
         }
+        len = unpadded_len;
 #else
         mbedtls_zeroize_and_free(buf, len);
         return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE;
diff --git a/library/pk.c b/library/pk.c
index 076d3a8..1ded487 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -18,10 +18,8 @@
 
 #if defined(MBEDTLS_RSA_C)
 #include "mbedtls/rsa.h"
-#if defined(MBEDTLS_PKCS1_V21) && !defined(MBEDTLS_USE_PSA_CRYPTO)
 #include "rsa_internal.h"
 #endif
-#endif
 #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
 #include "mbedtls/ecp.h"
 #endif
@@ -579,6 +577,285 @@
 
     return 0;
 }
+
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) || defined(MBEDTLS_USE_PSA_CRYPTO)
+static psa_status_t export_import_into_psa(mbedtls_svc_key_id_t old_key_id,
+                                           const psa_key_attributes_t *attributes,
+                                           mbedtls_svc_key_id_t *new_key_id)
+{
+    unsigned char key_buffer[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
+    size_t key_length = 0;
+    psa_status_t status = psa_export_key(old_key_id,
+                                         key_buffer, sizeof(key_buffer),
+                                         &key_length);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+    status = psa_import_key(attributes, key_buffer, key_length, new_key_id);
+    mbedtls_platform_zeroize(key_buffer, key_length);
+    return status;
+}
+
+static int copy_into_psa(mbedtls_svc_key_id_t old_key_id,
+                         const psa_key_attributes_t *attributes,
+                         mbedtls_svc_key_id_t *new_key_id)
+{
+    /* Normally, we prefer copying: it's more efficient and works even
+     * for non-exportable keys. */
+    psa_status_t status = psa_copy_key(old_key_id, attributes, new_key_id);
+    if (status == PSA_ERROR_NOT_PERMITTED /*missing COPY usage*/ ||
+        status == PSA_ERROR_INVALID_ARGUMENT /*incompatible policy*/) {
+        /* There are edge cases where copying won't work, but export+import
+         * might:
+         * - If the old key does not allow PSA_KEY_USAGE_COPY.
+         * - If the old key's usage does not allow what attributes wants.
+         *   Because the key was intended for use in the pk module, and may
+         *   have had a policy chosen solely for what pk needs rather than
+         *   based on a detailed understanding of PSA policies, we are a bit
+         *   more liberal than psa_copy_key() here.
+         */
+        /* Here we need to check that the types match, otherwise we risk
+         * importing nonsensical data. */
+        psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;
+        status = psa_get_key_attributes(old_key_id, &old_attributes);
+        if (status != PSA_SUCCESS) {
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+        }
+        psa_key_type_t old_type = psa_get_key_type(&old_attributes);
+        psa_reset_key_attributes(&old_attributes);
+        if (old_type != psa_get_key_type(attributes)) {
+            return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+        }
+        status = export_import_into_psa(old_key_id, attributes, new_key_id);
+    }
+    return PSA_PK_TO_MBEDTLS_ERR(status);
+}
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_USE_PSA_CRYPTO */
+
+static int import_pair_into_psa(const mbedtls_pk_context *pk,
+                                const psa_key_attributes_t *attributes,
+                                mbedtls_svc_key_id_t *key_id)
+{
+    switch (mbedtls_pk_get_type(pk)) {
+#if defined(MBEDTLS_RSA_C)
+        case MBEDTLS_PK_RSA:
+        {
+            if (psa_get_key_type(attributes) != PSA_KEY_TYPE_RSA_KEY_PAIR) {
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            unsigned char key_buffer[
+                PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS)];
+            unsigned char *const key_end = key_buffer + sizeof(key_buffer);
+            unsigned char *key_data = key_end;
+            int ret = mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk),
+                                            key_buffer, &key_data);
+            if (ret < 0) {
+                return ret;
+            }
+            size_t key_length = key_end - key_data;
+            ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,
+                                                       key_data, key_length,
+                                                       key_id));
+            mbedtls_platform_zeroize(key_data, key_length);
+            return ret;
+        }
+#endif /* MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+        case MBEDTLS_PK_ECKEY:
+        case MBEDTLS_PK_ECKEY_DH:
+        case MBEDTLS_PK_ECDSA:
+        {
+            /* We need to check the curve family, otherwise the import could
+             * succeed with nonsensical data.
+             * We don't check the bit-size: it's optional in attributes,
+             * and if it's specified, psa_import_key() will know from the key
+             * data length and will check that the bit-size matches. */
+            psa_key_type_t to_type = psa_get_key_type(attributes);
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+            psa_ecc_family_t from_family = pk->ec_family;
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+            /* We're only reading the key, but mbedtls_ecp_write_key()
+             * is missing a const annotation on its key parameter, so
+             * we need the non-const accessor here. */
+            mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk);
+            size_t from_bits = 0;
+            psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id,
+                                                                    &from_bits);
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+            if (to_type != PSA_KEY_TYPE_ECC_KEY_PAIR(from_family)) {
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+            if (mbedtls_svc_key_id_is_null(pk->priv_id)) {
+                /* We have a public key and want a key pair. */
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            return copy_into_psa(pk->priv_id, attributes, key_id);
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+            if (ec->d.n == 0) {
+                /* Private key not set. Assume the input is a public key only.
+                 * (The other possibility is that it's an incomplete object
+                 * where the group is set but neither the public key nor
+                 * the private key. This is not possible through ecp.h
+                 * functions, so we don't bother reporting a more suitable
+                 * error in that case.) */
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            unsigned char key_buffer[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
+            /* Make sure to pass the exact key length to
+             * mbedtls_ecp_write_key(), because it writes Montgomery keys
+             * at the start of the buffer but Weierstrass keys at the
+             * end of the buffer. */
+            size_t key_length = PSA_BITS_TO_BYTES(ec->grp.nbits);
+            int ret = mbedtls_ecp_write_key(ec, key_buffer, key_length);
+            if (ret < 0) {
+                return ret;
+            }
+            ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,
+                                                       key_buffer, key_length,
+                                                       key_id));
+            mbedtls_platform_zeroize(key_buffer, key_length);
+            return ret;
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+        }
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        case MBEDTLS_PK_OPAQUE:
+            return copy_into_psa(pk->priv_id, attributes, key_id);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+        default:
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+}
+
+static int import_public_into_psa(const mbedtls_pk_context *pk,
+                                  const psa_key_attributes_t *attributes,
+                                  mbedtls_svc_key_id_t *key_id)
+{
+    psa_key_type_t psa_type = psa_get_key_type(attributes);
+
+#if defined(MBEDTLS_RSA_C) ||                                           \
+    (defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA)) || \
+    defined(MBEDTLS_USE_PSA_CRYPTO)
+    unsigned char key_buffer[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
+#endif
+    unsigned char *key_data = NULL;
+    size_t key_length = 0;
+
+    switch (mbedtls_pk_get_type(pk)) {
+#if defined(MBEDTLS_RSA_C)
+        case MBEDTLS_PK_RSA:
+        {
+            if (psa_type != PSA_KEY_TYPE_RSA_PUBLIC_KEY) {
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            unsigned char *const key_end = key_buffer + sizeof(key_buffer);
+            key_data = key_end;
+            int ret = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*pk),
+                                               key_buffer, &key_data);
+            if (ret < 0) {
+                return ret;
+            }
+            key_length = (size_t) ret;
+            break;
+        }
+#endif /*MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+        case MBEDTLS_PK_ECKEY:
+        case MBEDTLS_PK_ECKEY_DH:
+        case MBEDTLS_PK_ECDSA:
+        {
+            /* We need to check the curve family, otherwise the import could
+             * succeed with nonsensical data.
+             * We don't check the bit-size: it's optional in attributes,
+             * and if it's specified, psa_import_key() will know from the key
+             * data length and will check that the bit-size matches. */
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+            if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family)) {
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            key_data = (unsigned char *) pk->pub_raw;
+            key_length = pk->pub_raw_len;
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+            const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);
+            size_t from_bits = 0;
+            psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id,
+                                                                    &from_bits);
+            if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(from_family)) {
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            int ret = mbedtls_ecp_write_public_key(
+                ec, MBEDTLS_ECP_PF_UNCOMPRESSED,
+                &key_length, key_buffer, sizeof(key_buffer));
+            if (ret < 0) {
+                return ret;
+            }
+            key_data = key_buffer;
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+            break;
+        }
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        case MBEDTLS_PK_OPAQUE:
+        {
+            psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;
+            psa_status_t status =
+                psa_get_key_attributes(pk->priv_id, &old_attributes);
+            if (status != PSA_SUCCESS) {
+                return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+            }
+            psa_key_type_t old_type = psa_get_key_type(&old_attributes);
+            psa_reset_key_attributes(&old_attributes);
+            if (psa_type != PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(old_type)) {
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            status = psa_export_public_key(pk->priv_id,
+                                           key_buffer, sizeof(key_buffer),
+                                           &key_length);
+            if (status != PSA_SUCCESS) {
+                return PSA_PK_TO_MBEDTLS_ERR(status);
+            }
+            key_data = key_buffer;
+            break;
+        }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+        default:
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    return PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,
+                                                key_data, key_length,
+                                                key_id));
+}
+
+int mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk,
+                               const psa_key_attributes_t *attributes,
+                               mbedtls_svc_key_id_t *key_id)
+{
+    /* Set the output immediately so that it won't contain garbage even
+     * if we error out before calling psa_import_key(). */
+    *key_id = MBEDTLS_SVC_KEY_ID_INIT;
+
+#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
+    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA_ALT) {
+        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+    }
+#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
+
+    int want_public = PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_get_key_type(attributes));
+    if (want_public) {
+        return import_public_into_psa(pk, attributes, key_id);
+    } else {
+        return import_pair_into_psa(pk, attributes, key_id);
+    }
+}
 #endif /* MBEDTLS_PSA_CRYPTO_C */
 
 /*
diff --git a/library/pk_internal.h b/library/pk_internal.h
index da6c7f1..f5924ad 100644
--- a/library/pk_internal.h
+++ b/library/pk_internal.h
@@ -17,7 +17,7 @@
 #include "mbedtls/ecp.h"
 #endif
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
 #include "psa/crypto.h"
 
 #include "psa_util_internal.h"
@@ -28,7 +28,7 @@
 #define PSA_PK_ECDSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
                                                                     psa_to_pk_ecdsa_errors,        \
                                                                     psa_pk_status_to_mbedtls)
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
 
 /* Headers/footers for PEM files */
 #define PEM_BEGIN_PUBLIC_KEY    "-----BEGIN PUBLIC KEY-----"
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index 69e1baf..846175e 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -74,8 +74,7 @@
     int key_len;
     unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
     unsigned char *p = buf + sizeof(buf);
-    psa_algorithm_t psa_alg_md =
-        PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_md_psa_alg_from_type(md_alg));
+    psa_algorithm_t psa_alg_md;
     size_t rsa_len = mbedtls_rsa_get_len(rsa);
 
 #if SIZE_MAX > UINT_MAX
@@ -84,6 +83,12 @@
     }
 #endif
 
+    if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
+        psa_alg_md = PSA_ALG_RSA_PSS(mbedtls_md_psa_alg_from_type(md_alg));
+    } else {
+        psa_alg_md = PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_md_psa_alg_from_type(md_alg));
+    }
+
     if (sig_len < rsa_len) {
         return MBEDTLS_ERR_RSA_VERIFY_FAILED;
     }
@@ -235,10 +240,14 @@
     if (psa_md_alg == 0) {
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
+    psa_algorithm_t psa_alg;
+    if (mbedtls_rsa_get_padding_mode(mbedtls_pk_rsa(*pk)) == MBEDTLS_RSA_PKCS_V21) {
+        psa_alg = PSA_ALG_RSA_PSS(psa_md_alg);
+    } else {
+        psa_alg = PSA_ALG_RSA_PKCS1V15_SIGN(psa_md_alg);
+    }
 
-    return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PKCS1V15_SIGN(
-                                           psa_md_alg),
-                                       pk->pk_ctx, hash, hash_len,
+    return mbedtls_pk_psa_rsa_sign_ext(psa_alg, pk->pk_ctx, hash, hash_len,
                                        sig, sig_size, sig_len);
 }
 #else /* MBEDTLS_USE_PSA_CRYPTO */
@@ -276,6 +285,7 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_algorithm_t psa_md_alg, decrypt_alg;
     psa_status_t status;
     int key_len;
     unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES];
@@ -284,12 +294,6 @@
     ((void) f_rng);
     ((void) p_rng);
 
-#if !defined(MBEDTLS_RSA_ALT)
-    if (rsa->padding != MBEDTLS_RSA_PKCS_V15) {
-        return MBEDTLS_ERR_RSA_INVALID_PADDING;
-    }
-#endif /* !MBEDTLS_RSA_ALT */
-
     if (ilen != mbedtls_rsa_get_len(rsa)) {
         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
@@ -301,7 +305,13 @@
 
     psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
     psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
-    psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
+    if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
+        psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa));
+        decrypt_alg = PSA_ALG_RSA_OAEP(psa_md_alg);
+    } else {
+        decrypt_alg = PSA_ALG_RSA_PKCS1V15_CRYPT;
+    }
+    psa_set_key_algorithm(&attributes, decrypt_alg);
 
     status = psa_import_key(&attributes,
                             buf + sizeof(buf) - key_len, key_len,
@@ -311,7 +321,7 @@
         goto cleanup;
     }
 
-    status = psa_asymmetric_decrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
+    status = psa_asymmetric_decrypt(key_id, decrypt_alg,
                                     input, ilen,
                                     NULL, 0,
                                     output, osize, olen);
@@ -358,6 +368,7 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_algorithm_t psa_md_alg;
     psa_status_t status;
     int key_len;
     unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
@@ -366,12 +377,6 @@
     ((void) f_rng);
     ((void) p_rng);
 
-#if !defined(MBEDTLS_RSA_ALT)
-    if (rsa->padding != MBEDTLS_RSA_PKCS_V15) {
-        return MBEDTLS_ERR_RSA_INVALID_PADDING;
-    }
-#endif
-
     if (mbedtls_rsa_get_len(rsa) > osize) {
         return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
     }
@@ -382,7 +387,12 @@
     }
 
     psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
-    psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
+    if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
+        psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa));
+        psa_set_key_algorithm(&attributes, PSA_ALG_RSA_OAEP(psa_md_alg));
+    } else {
+        psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
+    }
     psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);
 
     status = psa_import_key(&attributes,
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 4a0666b..ca01e76 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -909,8 +909,13 @@
  * into a key slot if not already done.
  *
  * On success, the returned key slot has been registered for reading.
- * It is the responsibility of the caller to call psa_unregister_read(slot)
- * when they have finished reading the contents of the slot.
+ * It is the responsibility of the caller to then unregister
+ * once they have finished reading the contents of the slot.
+ * The caller unregisters by calling psa_unregister_read() or
+ * psa_unregister_read_under_mutex(). psa_unregister_read() must be called
+ * if and only if the caller already holds the global key slot mutex
+ * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates
+ * the unregister with mutex lock and unlock operations.
  */
 static psa_status_t psa_get_and_lock_key_slot_with_policy(
     mbedtls_svc_key_id_t key,
@@ -954,7 +959,7 @@
 
 error:
     *p_slot = NULL;
-    psa_unregister_read(slot);
+    psa_unregister_read_under_mutex(slot);
 
     return status;
 }
@@ -970,8 +975,13 @@
  * for a cryptographic operation.
  *
  * On success, the returned key slot has been registered for reading.
- * It is the responsibility of the caller to call psa_unregister_read(slot)
- * when they have finished reading the contents of the slot.
+ * It is the responsibility of the caller to then unregister
+ * once they have finished reading the contents of the slot.
+ * The caller unregisters by calling psa_unregister_read() or
+ * psa_unregister_read_under_mutex(). psa_unregister_read() must be called
+ * if and only if the caller already holds the global key slot mutex
+ * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates
+ * psa_unregister_read() with mutex lock and unlock operations.
  */
 static psa_status_t psa_get_and_lock_transparent_key_slot_with_policy(
     mbedtls_svc_key_id_t key,
@@ -986,7 +996,7 @@
     }
 
     if (psa_key_lifetime_is_external((*p_slot)->attr.lifetime)) {
-        psa_unregister_read(*p_slot);
+        psa_unregister_read_under_mutex(*p_slot);
         *p_slot = NULL;
         return PSA_ERROR_NOT_SUPPORTED;
     }
@@ -1201,58 +1211,12 @@
     return overall_status;
 }
 
-#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
-    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
-static psa_status_t psa_get_rsa_public_exponent(
-    const mbedtls_rsa_context *rsa,
-    psa_key_attributes_t *attributes)
-{
-    mbedtls_mpi mpi;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    uint8_t *buffer = NULL;
-    size_t buflen;
-    mbedtls_mpi_init(&mpi);
-
-    ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &mpi);
-    if (ret != 0) {
-        goto exit;
-    }
-    if (mbedtls_mpi_cmp_int(&mpi, 65537) == 0) {
-        /* It's the default value, which is reported as an empty string,
-         * so there's nothing to do. */
-        goto exit;
-    }
-
-    buflen = mbedtls_mpi_size(&mpi);
-    buffer = mbedtls_calloc(1, buflen);
-    if (buffer == NULL) {
-        ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
-        goto exit;
-    }
-    ret = mbedtls_mpi_write_binary(&mpi, buffer, buflen);
-    if (ret != 0) {
-        goto exit;
-    }
-    attributes->domain_parameters = buffer;
-    attributes->domain_parameters_size = buflen;
-
-exit:
-    mbedtls_mpi_free(&mpi);
-    if (ret != 0) {
-        mbedtls_free(buffer);
-    }
-    return mbedtls_to_psa_error(ret);
-}
-#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) ||
-        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
-
 /** Retrieve all the publicly-accessible attributes of a key.
  */
 psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key,
                                     psa_key_attributes_t *attributes)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
 
     psa_reset_key_attributes(attributes);
@@ -1273,55 +1237,7 @@
     }
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
-    switch (slot->attr.type) {
-#if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \
-    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \
-    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
-        case PSA_KEY_TYPE_RSA_KEY_PAIR:
-        case PSA_KEY_TYPE_RSA_PUBLIC_KEY:
-            /* TODO: This is a temporary situation where domain parameters are deprecated,
-             * but we need it for namely generating an RSA key with a non-default exponent.
-             * This would be improved after https://github.com/Mbed-TLS/mbedtls/issues/6494.
-             */
-            if (!psa_key_lifetime_is_external(slot->attr.lifetime)) {
-                mbedtls_rsa_context *rsa = NULL;
-
-                status = mbedtls_psa_rsa_load_representation(
-                    slot->attr.type,
-                    slot->key.data,
-                    slot->key.bytes,
-                    &rsa);
-                if (status != PSA_SUCCESS) {
-                    break;
-                }
-
-                status = psa_get_rsa_public_exponent(rsa,
-                                                     attributes);
-                mbedtls_rsa_free(rsa);
-                mbedtls_free(rsa);
-            }
-            break;
-#else
-        case PSA_KEY_TYPE_RSA_KEY_PAIR:
-        case PSA_KEY_TYPE_RSA_PUBLIC_KEY:
-            attributes->domain_parameters = NULL;
-            attributes->domain_parameters_size = SIZE_MAX;
-            break;
-#endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \
-        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) ||
-        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
-        default:
-            /* Nothing else to do. */
-            break;
-    }
-
-    if (status != PSA_SUCCESS) {
-        psa_reset_key_attributes(attributes);
-    }
-
-    unlock_status = psa_unregister_read(slot);
-
-    return (status == PSA_SUCCESS) ? unlock_status : status;
+    return psa_unregister_read_under_mutex(slot);
 }
 
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
@@ -1415,7 +1331,7 @@
                                            slot->key.data, slot->key.bytes,
                                            data, data_size, data_length);
 
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
 
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
@@ -1529,7 +1445,7 @@
         data, data_size, data_length);
 
 exit:
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
 
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
@@ -1679,7 +1595,15 @@
         return status;
     }
 
+#if defined(MBEDTLS_THREADING_C)
+    PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
     status = psa_reserve_free_key_slot(&volatile_key_id, p_slot);
+#if defined(MBEDTLS_THREADING_C)
+    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
     if (status != PSA_SUCCESS) {
         return status;
     }
@@ -1799,6 +1723,11 @@
     (void) slot;
     (void) driver;
 
+#if defined(MBEDTLS_THREADING_C)
+    PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
+
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
     if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
@@ -1838,6 +1767,11 @@
         status = psa_save_se_persistent_data(driver);
         if (status != PSA_SUCCESS) {
             psa_destroy_persistent_key(slot->attr.id);
+
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                                      &mbedtls_threading_key_slot_mutex));
+#endif
             return status;
         }
         status = psa_crypto_stop_transaction();
@@ -1853,6 +1787,10 @@
         }
     }
 
+#if defined(MBEDTLS_THREADING_C)
+    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
     return status;
 }
 
@@ -1877,6 +1815,13 @@
         return;
     }
 
+#if defined(MBEDTLS_THREADING_C)
+    /* If the lock operation fails we still wipe the slot.
+     * Operations will no longer work after a failed lock,
+     * but we still need to wipe the slot of confidential data. */
+    mbedtls_mutex_lock(&mbedtls_threading_key_slot_mutex);
+#endif
+
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
     /* TODO: If the key has already been created in the secure
      * element, and the failure happened later (when saving metadata
@@ -1895,6 +1840,10 @@
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
     psa_wipe_key_slot(slot);
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_key_slot_mutex);
+#endif
 }
 
 /** Validate optional attributes during key creation.
@@ -1916,57 +1865,6 @@
         }
     }
 
-    if (attributes->domain_parameters_size != 0) {
-#if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \
-        defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \
-        defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
-        if (PSA_KEY_TYPE_IS_RSA(slot->attr.type)) {
-            mbedtls_rsa_context *rsa = NULL;
-            mbedtls_mpi actual, required;
-            int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-            psa_status_t status = mbedtls_psa_rsa_load_representation(
-                slot->attr.type,
-                slot->key.data,
-                slot->key.bytes,
-                &rsa);
-            if (status != PSA_SUCCESS) {
-                return status;
-            }
-
-            mbedtls_mpi_init(&actual);
-            mbedtls_mpi_init(&required);
-            ret = mbedtls_rsa_export(rsa,
-                                     NULL, NULL, NULL, NULL, &actual);
-            mbedtls_rsa_free(rsa);
-            mbedtls_free(rsa);
-            if (ret != 0) {
-                goto rsa_exit;
-            }
-            ret = mbedtls_mpi_read_binary(&required,
-                                          attributes->domain_parameters,
-                                          attributes->domain_parameters_size);
-            if (ret != 0) {
-                goto rsa_exit;
-            }
-            if (mbedtls_mpi_cmp_mpi(&actual, &required) != 0) {
-                ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
-            }
-rsa_exit:
-            mbedtls_mpi_free(&actual);
-            mbedtls_mpi_free(&required);
-            if (ret != 0) {
-                return mbedtls_to_psa_error(ret);
-            }
-        } else
-#endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) &&
-        *  defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) ||
-        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
-        {
-            return PSA_ERROR_INVALID_ARGUMENT;
-        }
-    }
-
     if (attributes->core.bits != 0) {
         if (attributes->core.bits != slot->attr.bits) {
             return PSA_ERROR_INVALID_ARGUMENT;
@@ -2201,7 +2099,7 @@
         psa_fail_key_creation(target_slot, driver);
     }
 
-    unlock_status = psa_unregister_read(source_slot);
+    unlock_status = psa_unregister_read_under_mutex(source_slot);
 
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
@@ -2522,7 +2420,7 @@
         psa_mac_abort(operation);
     }
 
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
 
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
@@ -2708,7 +2606,7 @@
 
     psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length);
 
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
 
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
@@ -2852,7 +2750,7 @@
     psa_wipe_tag_output_buffer(signature, status, signature_size,
                                *signature_length);
 
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
 
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
@@ -2900,7 +2798,7 @@
             signature, signature_length);
     }
 
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
 
     return (status == PSA_SUCCESS) ? unlock_status : status;
 
@@ -3167,7 +3065,7 @@
         alg, input, input_length, salt, salt_length,
         output, output_size, output_length);
 exit:
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
 
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
@@ -3219,7 +3117,7 @@
         output, output_size, output_length);
 
 exit:
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
 
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
@@ -3328,7 +3226,7 @@
         psa_sign_hash_abort_internal(operation);
     }
 
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
 
     if (unlock_status != PSA_SUCCESS) {
         operation->error_occurred = 1;
@@ -3473,7 +3371,7 @@
         psa_verify_hash_abort_internal(operation);
     }
 
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
 
     if (unlock_status != PSA_SUCCESS) {
         operation->error_occurred = 1;
@@ -4045,7 +3943,7 @@
         psa_cipher_abort(operation);
     }
 
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
 
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
@@ -4290,7 +4188,7 @@
         output_size - default_iv_length, output_length);
 
 exit:
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
     if (status == PSA_SUCCESS) {
         status = unlock_status;
     }
@@ -4351,7 +4249,7 @@
         output, output_size, output_length);
 
 exit:
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
     if (status == PSA_SUCCESS) {
         status = unlock_status;
     }
@@ -4477,7 +4375,7 @@
     }
 
 exit:
-    psa_unregister_read(slot);
+    psa_unregister_read_under_mutex(slot);
 
     return status;
 }
@@ -4532,7 +4430,7 @@
     }
 
 exit:
-    psa_unregister_read(slot);
+    psa_unregister_read_under_mutex(slot);
 
     return status;
 }
@@ -4644,7 +4542,7 @@
     operation->key_type = psa_get_key_type(&attributes);
 
 exit:
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
 
     if (status == PSA_SUCCESS) {
         status = unlock_status;
@@ -6023,9 +5921,28 @@
     return status;
 }
 
-psa_status_t psa_key_derivation_output_key(const psa_key_attributes_t *attributes,
-                                           psa_key_derivation_operation_t *operation,
-                                           mbedtls_svc_key_id_t *key)
+static const psa_key_production_parameters_t default_production_parameters =
+    PSA_KEY_PRODUCTION_PARAMETERS_INIT;
+
+int psa_key_production_parameters_are_default(
+    const psa_key_production_parameters_t *params,
+    size_t params_data_length)
+{
+    if (params->flags != 0) {
+        return 0;
+    }
+    if (params_data_length != 0) {
+        return 0;
+    }
+    return 1;
+}
+
+psa_status_t psa_key_derivation_output_key_ext(
+    const psa_key_attributes_t *attributes,
+    psa_key_derivation_operation_t *operation,
+    const psa_key_production_parameters_t *params,
+    size_t params_data_length,
+    mbedtls_svc_key_id_t *key)
 {
     psa_status_t status;
     psa_key_slot_t *slot = NULL;
@@ -6039,6 +5956,10 @@
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 
+    if (!psa_key_production_parameters_are_default(params, params_data_length)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
     if (operation->alg == PSA_ALG_NONE) {
         return PSA_ERROR_BAD_STATE;
     }
@@ -6070,6 +5991,15 @@
     return status;
 }
 
+psa_status_t psa_key_derivation_output_key(
+    const psa_key_attributes_t *attributes,
+    psa_key_derivation_operation_t *operation,
+    mbedtls_svc_key_id_t *key)
+{
+    return psa_key_derivation_output_key_ext(attributes, operation,
+                                             &default_production_parameters, 0,
+                                             key);
+}
 
 
 /****************************************************************/
@@ -7018,7 +6948,7 @@
                                                slot->key.data,
                                                slot->key.bytes);
 
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
 
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
@@ -7175,7 +7105,7 @@
         }
     }
 
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
 
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
@@ -7236,7 +7166,7 @@
         *output_length = output_size;
     }
 
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
 
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
@@ -7466,15 +7396,15 @@
 
 psa_status_t psa_generate_key_internal(
     const psa_key_attributes_t *attributes,
+    const psa_key_production_parameters_t *params, size_t params_data_length,
     uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_type_t type = attributes->core.type;
 
-    if ((attributes->domain_parameters == NULL) &&
-        (attributes->domain_parameters_size != 0)) {
-        return PSA_ERROR_INVALID_ARGUMENT;
-    }
+    /* Only used for RSA */
+    (void) params;
+    (void) params_data_length;
 
     if (key_type_is_raw_bytes(type)) {
         status = psa_generate_random(key_buffer, key_buffer_size);
@@ -7492,6 +7422,7 @@
 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
     if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
         return mbedtls_psa_rsa_generate_key(attributes,
+                                            params, params_data_length,
                                             key_buffer,
                                             key_buffer_size,
                                             key_buffer_length);
@@ -7523,8 +7454,10 @@
     return PSA_SUCCESS;
 }
 
-psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
-                              mbedtls_svc_key_id_t *key)
+psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes,
+                                  const psa_key_production_parameters_t *params,
+                                  size_t params_data_length,
+                                  mbedtls_svc_key_id_t *key)
 {
     psa_status_t status;
     psa_key_slot_t *slot = NULL;
@@ -7544,6 +7477,17 @@
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+    if (attributes->core.type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
+        if (params->flags != 0) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+    } else
+#endif
+    if (!psa_key_production_parameters_are_default(params, params_data_length)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
     status = psa_start_key_creation(PSA_KEY_CREATION_GENERATE, attributes,
                                     &slot, &driver);
     if (status != PSA_SUCCESS) {
@@ -7581,8 +7525,9 @@
     }
 
     status = psa_driver_wrapper_generate_key(attributes,
-                                             slot->key.data, slot->key.bytes, &slot->key.bytes);
-
+                                             params, params_data_length,
+                                             slot->key.data, slot->key.bytes,
+                                             &slot->key.bytes);
     if (status != PSA_SUCCESS) {
         psa_remove_key_data_from_memory(slot);
     }
@@ -7598,6 +7543,14 @@
     return status;
 }
 
+psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
+                              mbedtls_svc_key_id_t *key)
+{
+    return psa_generate_key_ext(attributes,
+                                &default_production_parameters, 0,
+                                key);
+}
+
 /****************************************************************/
 /* Module setup */
 /****************************************************************/
@@ -7910,7 +7863,7 @@
     if (status != PSA_SUCCESS) {
         psa_pake_abort(operation);
     }
-    unlock_status = psa_unregister_read(slot);
+    unlock_status = psa_unregister_read_under_mutex(slot);
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
 
diff --git a/library/psa_crypto_client.c b/library/psa_crypto_client.c
index 472d3d3..72f671d 100644
--- a/library/psa_crypto_client.c
+++ b/library/psa_crypto_client.c
@@ -16,57 +16,7 @@
 
 void psa_reset_key_attributes(psa_key_attributes_t *attributes)
 {
-    mbedtls_free(attributes->domain_parameters);
     memset(attributes, 0, sizeof(*attributes));
 }
 
-psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes,
-                                           psa_key_type_t type,
-                                           const uint8_t *data,
-                                           size_t data_length)
-{
-    uint8_t *copy = NULL;
-
-    if (data_length != 0) {
-        copy = mbedtls_calloc(1, data_length);
-        if (copy == NULL) {
-            return PSA_ERROR_INSUFFICIENT_MEMORY;
-        }
-        memcpy(copy, data, data_length);
-    }
-    /* After this point, this function is guaranteed to succeed, so it
-     * can start modifying `*attributes`. */
-
-    if (attributes->domain_parameters != NULL) {
-        mbedtls_free(attributes->domain_parameters);
-        attributes->domain_parameters = NULL;
-        attributes->domain_parameters_size = 0;
-    }
-
-    attributes->domain_parameters = copy;
-    attributes->domain_parameters_size = data_length;
-    attributes->core.type = type;
-    return PSA_SUCCESS;
-}
-
-psa_status_t psa_get_key_domain_parameters(
-    const psa_key_attributes_t *attributes,
-    uint8_t *data, size_t data_size, size_t *data_length)
-{
-    if (attributes->domain_parameters == NULL &&
-        attributes->domain_parameters_size == SIZE_MAX) {
-        return PSA_ERROR_NOT_SUPPORTED;
-    }
-
-    if (attributes->domain_parameters_size > data_size) {
-        return PSA_ERROR_BUFFER_TOO_SMALL;
-    }
-    *data_length = attributes->domain_parameters_size;
-    if (attributes->domain_parameters_size != 0) {
-        memcpy(data, attributes->domain_parameters,
-               attributes->domain_parameters_size);
-    }
-    return PSA_SUCCESS;
-}
-
 #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h
index dc376d7..afa8659 100644
--- a/library/psa_crypto_core.h
+++ b/library/psa_crypto_core.h
@@ -89,7 +89,9 @@
      * A function must call psa_register_read(slot) before reading the current
      * contents of the slot for an operation.
      * They then must call psa_unregister_read(slot) once they have finished
-     * reading the current contents of the slot.
+     * reading the current contents of the slot. If the key slot mutex is not
+     * held (when mutexes are enabled), this call must be done via a call to
+     * psa_unregister_read_under_mutex(slot).
      * A function must call psa_key_slot_has_readers(slot) to check if
      * the slot is in use for reading.
      *
@@ -396,6 +398,18 @@
     const uint8_t *key_buffer, size_t key_buffer_size,
     uint8_t *data, size_t data_size, size_t *data_length);
 
+/** Whether a key production parameters structure is the default.
+ *
+ * Calls to a key generation driver with non-default production parameters
+ * require a driver supporting custom production parameters.
+ *
+ * \param[in] params            The key production parameters to check.
+ * \param params_data_length    Size of `params->data` in bytes.
+ */
+int psa_key_production_parameters_are_default(
+    const psa_key_production_parameters_t *params,
+    size_t params_data_length);
+
 /**
  * \brief Generate a key.
  *
@@ -403,6 +417,9 @@
  *       entry point.
  *
  * \param[in]  attributes         The attributes for the key to generate.
+ * \param[in]  params             The production parameters from
+ *                                psa_generate_key_ext().
+ * \param      params_data_length The size of `params->data` in bytes.
  * \param[out] key_buffer         Buffer where the key data is to be written.
  * \param[in]  key_buffer_size    Size of \p key_buffer in bytes.
  * \param[out] key_buffer_length  On success, the number of bytes written in
@@ -417,6 +434,8 @@
  *         The size of \p key_buffer is too small.
  */
 psa_status_t psa_generate_key_internal(const psa_key_attributes_t *attributes,
+                                       const psa_key_production_parameters_t *params,
+                                       size_t params_data_length,
                                        uint8_t *key_buffer,
                                        size_t key_buffer_size,
                                        size_t *key_buffer_length);
diff --git a/library/psa_crypto_ecp.c b/library/psa_crypto_ecp.c
index db08541..7edea81 100644
--- a/library/psa_crypto_ecp.c
+++ b/library/psa_crypto_ecp.c
@@ -345,10 +345,6 @@
         mbedtls_ecp_curve_info_from_grp_id(grp_id);
     mbedtls_ecp_keypair ecp;
 
-    if (attributes->domain_parameters_size != 0) {
-        return PSA_ERROR_NOT_SUPPORTED;
-    }
-
     if (grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL) {
         return PSA_ERROR_NOT_SUPPORTED;
     }
diff --git a/library/psa_crypto_rsa.c b/library/psa_crypto_rsa.c
index 4a574d1..84a8667 100644
--- a/library/psa_crypto_rsa.c
+++ b/library/psa_crypto_rsa.c
@@ -216,26 +216,21 @@
         * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
 
 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
-static psa_status_t psa_rsa_read_exponent(const uint8_t *domain_parameters,
-                                          size_t domain_parameters_size,
+static psa_status_t psa_rsa_read_exponent(const uint8_t *e_bytes,
+                                          size_t e_length,
                                           int *exponent)
 {
     size_t i;
     uint32_t acc = 0;
 
-    if (domain_parameters_size == 0) {
-        *exponent = 65537;
-        return PSA_SUCCESS;
-    }
-
     /* Mbed TLS encodes the public exponent as an int. For simplicity, only
      * support values that fit in a 32-bit integer, which is larger than
      * int on just about every platform anyway. */
-    if (domain_parameters_size > sizeof(acc)) {
+    if (e_length > sizeof(acc)) {
         return PSA_ERROR_NOT_SUPPORTED;
     }
-    for (i = 0; i < domain_parameters_size; i++) {
-        acc = (acc << 8) | domain_parameters[i];
+    for (i = 0; i < e_length; i++) {
+        acc = (acc << 8) | e_bytes[i];
     }
     if (acc > INT_MAX) {
         return PSA_ERROR_NOT_SUPPORTED;
@@ -246,18 +241,20 @@
 
 psa_status_t mbedtls_psa_rsa_generate_key(
     const psa_key_attributes_t *attributes,
+    const psa_key_production_parameters_t *params, size_t params_data_length,
     uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
 {
     psa_status_t status;
     mbedtls_rsa_context rsa;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    int exponent;
+    int exponent = 65537;
 
-    status = psa_rsa_read_exponent(attributes->domain_parameters,
-                                   attributes->domain_parameters_size,
-                                   &exponent);
-    if (status != PSA_SUCCESS) {
-        return status;
+    if (params_data_length != 0) {
+        status = psa_rsa_read_exponent(params->data, params_data_length,
+                                       &exponent);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
     }
 
     mbedtls_rsa_init(&rsa);
diff --git a/library/psa_crypto_rsa.h b/library/psa_crypto_rsa.h
index e4c5caf..ffeef26 100644
--- a/library/psa_crypto_rsa.h
+++ b/library/psa_crypto_rsa.h
@@ -109,6 +109,15 @@
  *       entry point.
  *
  * \param[in]  attributes         The attributes for the RSA key to generate.
+ * \param[in]  params             Production parameters for the key
+ *                                generation. This function only uses
+ *                                `params->data`,
+ *                                which contains the public exponent.
+ *                                This can be a null pointer if
+ *                                \c params_data_length is 0.
+ * \param params_data_length      Length of `params->data` in bytes.
+ *                                This can be 0, in which case the
+ *                                public exponent will be 65537.
  * \param[out] key_buffer         Buffer where the key data is to be written.
  * \param[in]  key_buffer_size    Size of \p key_buffer in bytes.
  * \param[out] key_buffer_length  On success, the number of bytes written in
@@ -123,6 +132,7 @@
  */
 psa_status_t mbedtls_psa_rsa_generate_key(
     const psa_key_attributes_t *attributes,
+    const psa_key_production_parameters_t *params, size_t params_data_length,
     uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length);
 
 /** Sign an already-calculated hash with an RSA private key.
diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c
index dc38662..b2a3c7e 100644
--- a/library/psa_crypto_slot_management.c
+++ b/library/psa_crypto_slot_management.c
@@ -70,6 +70,9 @@
  * On success, the function locks the key slot. It is the responsibility of
  * the caller to unlock the key slot when it does not access it anymore.
  *
+ * If multi-threading is enabled, the caller must hold the
+ * global key slot mutex.
+ *
  * \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
@@ -94,16 +97,14 @@
     if (psa_key_id_is_volatile(key_id)) {
         slot = &global_data.key_slots[key_id - PSA_KEY_ID_VOLATILE_MIN];
 
-        /*
-         * Check if both the PSA key identifier key_id and the owner
-         * identifier of key match those of the key slot.
-         *
-         * Note that, if the key slot is not occupied, its PSA key identifier
-         * is equal to zero. This is an invalid value for a PSA key identifier
-         * and thus cannot be equal to the valid PSA key identifier key_id.
-         */
-        status = mbedtls_svc_key_id_equal(key, slot->attr.id) ?
-                 PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST;
+        /* Check if both the PSA key identifier key_id and the owner
+         * identifier of key match those of the key slot. */
+        if ((slot->state == PSA_SLOT_FULL) &&
+            (mbedtls_svc_key_id_equal(key, slot->attr.id))) {
+            status = PSA_SUCCESS;
+        } else {
+            status = PSA_ERROR_DOES_NOT_EXIST;
+        }
     } else {
         if (!psa_is_valid_key_id(key, 1)) {
             return PSA_ERROR_INVALID_HANDLE;
@@ -248,11 +249,6 @@
         data = (psa_se_key_data_storage_t *) key_data;
         status = psa_copy_key_material_into_slot(
             slot, data->slot_number, sizeof(data->slot_number));
-
-        if (status == PSA_SUCCESS) {
-            status = psa_key_slot_state_transition(slot, PSA_SLOT_FILLING,
-                                                   PSA_SLOT_FULL);
-        }
         goto exit;
     }
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
@@ -262,9 +258,6 @@
         goto exit;
     }
 
-    status = psa_key_slot_state_transition(slot, PSA_SLOT_FILLING,
-                                           PSA_SLOT_FULL);
-
 exit:
     psa_free_persistent_key_data(key_data, key_data_length);
     return status;
@@ -337,9 +330,6 @@
     /* Copy actual key length and core attributes into the slot on success */
     slot->key.bytes = key_buffer_length;
     slot->attr = attributes.core;
-
-    status = psa_key_slot_state_transition(slot, PSA_SLOT_FILLING,
-                                           PSA_SLOT_FULL);
 exit:
     if (status != PSA_SUCCESS) {
         psa_remove_key_data_from_memory(slot);
@@ -358,12 +348,27 @@
         return PSA_ERROR_BAD_STATE;
     }
 
+#if defined(MBEDTLS_THREADING_C)
+    /* We need to set status as success, otherwise CORRUPTION_DETECTED
+     * would be returned if the lock fails. */
+    status = PSA_SUCCESS;
+    /* If the key is persistent and not loaded, we cannot unlock the mutex
+     * between checking if the key is loaded and setting the slot as FULL,
+     * as otherwise another thread may load and then destroy the key
+     * in the meantime. */
+    PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
     /*
      * On success, the pointer to the slot is passed directly to the caller
      * thus no need to unlock the key slot here.
      */
     status = psa_get_and_lock_key_slot_in_memory(key, p_slot);
     if (status != PSA_ERROR_DOES_NOT_EXIST) {
+#if defined(MBEDTLS_THREADING_C)
+        PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                                  &mbedtls_threading_key_slot_mutex));
+#endif
         return status;
     }
 
@@ -374,6 +379,10 @@
 
     status = psa_reserve_free_key_slot(&volatile_key_id, p_slot);
     if (status != PSA_SUCCESS) {
+#if defined(MBEDTLS_THREADING_C)
+        PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                                  &mbedtls_threading_key_slot_mutex));
+#endif
         return status;
     }
 
@@ -407,10 +416,15 @@
         status = psa_register_read(*p_slot);
     }
 
-    return status;
 #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
-    return PSA_ERROR_INVALID_HANDLE;
+    status = PSA_ERROR_INVALID_HANDLE;
 #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
+
+#if defined(MBEDTLS_THREADING_C)
+    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
+    return status;
 }
 
 psa_status_t psa_unregister_read(psa_key_slot_t *slot)
@@ -447,6 +461,24 @@
     return PSA_ERROR_CORRUPTION_DETECTED;
 }
 
+psa_status_t psa_unregister_read_under_mutex(psa_key_slot_t *slot)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+#if defined(MBEDTLS_THREADING_C)
+    /* We need to set status as success, otherwise CORRUPTION_DETECTED
+     * would be returned if the lock fails. */
+    status = PSA_SUCCESS;
+    PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
+    status = psa_unregister_read(slot);
+#if defined(MBEDTLS_THREADING_C)
+    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
+    return status;
+}
+
 psa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime,
                                        psa_se_drv_table_entry_t **p_drv)
 {
@@ -510,7 +542,7 @@
 
     *handle = key;
 
-    return psa_unregister_read(slot);
+    return psa_unregister_read_under_mutex(slot);
 
 #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
     (void) key;
diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h
index 18a9144..bcfc9d8 100644
--- a/library/psa_crypto_slot_management.h
+++ b/library/psa_crypto_slot_management.h
@@ -107,6 +107,9 @@
  * It is the responsibility of the caller to change the slot's state to
  * PSA_SLOT_EMPTY/FULL once key creation has finished.
  *
+ * If multi-threading is enabled, the caller must hold the
+ * global key slot mutex.
+ *
  * \param[out] volatile_key_id   On success, volatile key identifier
  *                               associated to the returned slot.
  * \param[out] p_slot            On success, a pointer to the slot.
@@ -202,6 +205,27 @@
  */
 psa_status_t psa_unregister_read(psa_key_slot_t *slot);
 
+/** Wrap a call to psa_unregister_read in the global key slot mutex.
+ *
+ * If threading is disabled, this simply calls psa_unregister_read.
+ *
+ * \note To ease the handling of errors in retrieving a key slot
+ *       a NULL input pointer is valid, and the function returns
+ *       successfully without doing anything in that case.
+ *
+ * \param[in] slot  The key slot.
+ * \retval #PSA_SUCCESS
+ *             \p slot is NULL or the key slot reader counter has been
+ *             decremented (and potentially wiped) successfully.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ *             The slot's state was neither PSA_SLOT_FULL nor
+ *             PSA_SLOT_PENDING_DELETION.
+ *             Or a wipe was attempted and the slot's state was not
+ *             PSA_SLOT_PENDING_DELETION.
+ *             Or registered_readers was equal to 0.
+ */
+psa_status_t psa_unregister_read_under_mutex(psa_key_slot_t *slot);
+
 /** Test whether a lifetime designates a key in an external cryptoprocessor.
  *
  * \param lifetime      The lifetime to test.
diff --git a/library/psa_util.c b/library/psa_util.c
index fd119bf..125b173 100644
--- a/library/psa_util.c
+++ b/library/psa_util.c
@@ -164,6 +164,8 @@
             return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
         case PSA_ERROR_INVALID_ARGUMENT:
             return MBEDTLS_ERR_PK_INVALID_ALG;
+        case PSA_ERROR_NOT_PERMITTED:
+            return MBEDTLS_ERR_PK_TYPE_MISMATCH;
         case PSA_ERROR_INSUFFICIENT_MEMORY:
             return MBEDTLS_ERR_PK_ALLOC_FAILED;
         case PSA_ERROR_BAD_STATE:
diff --git a/library/rsa.c b/library/rsa.c
index 8351463..5debc69 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -108,8 +108,9 @@
         return ret;
     }
 
-    /* mbedtls_asn1_get_tag() already ensures that len is valid (i.e. p+len <= end)*/
-    end = p + len;
+    if (end != p + len) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
     if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
         return ret;
@@ -241,8 +242,9 @@
         return ret;
     }
 
-    /* mbedtls_asn1_get_tag() already ensures that len is valid (i.e. p+len <= end)*/
-    end = p + len;
+    if (end != p + len) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
 
     /* Import N */
     if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
diff --git a/library/ssl_ticket.c b/library/ssl_ticket.c
index cd730fb..5da3887 100644
--- a/library/ssl_ticket.c
+++ b/library/ssl_ticket.c
@@ -75,6 +75,10 @@
 #if defined(MBEDTLS_HAVE_TIME)
     key->generation_time = mbedtls_time(NULL);
 #endif
+    /* The lifetime of a key is the configured lifetime of the tickets when
+     * the key is created.
+     */
+    key->lifetime = ctx->ticket_lifetime;
 
     if ((ret = ctx->f_rng(ctx->p_rng, key->name, sizeof(key->name))) != 0) {
         return ret;
@@ -116,16 +120,17 @@
 #if !defined(MBEDTLS_HAVE_TIME)
     ((void) ctx);
 #else
-    if (ctx->ticket_lifetime != 0) {
+    mbedtls_ssl_ticket_key * const key = ctx->keys + ctx->active;
+    if (key->lifetime != 0) {
         mbedtls_time_t current_time = mbedtls_time(NULL);
-        mbedtls_time_t key_time = ctx->keys[ctx->active].generation_time;
+        mbedtls_time_t key_time = key->generation_time;
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
         psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 #endif
 
         if (current_time >= key_time &&
-            (uint64_t) (current_time - key_time) < ctx->ticket_lifetime) {
+            (uint64_t) (current_time - key_time) < key->lifetime) {
             return 0;
         }
 
@@ -198,6 +203,8 @@
 #if defined(MBEDTLS_HAVE_TIME)
     key->generation_time = mbedtls_time(NULL);
 #endif
+    key->lifetime = lifetime;
+
     return 0;
 }
 
@@ -331,7 +338,7 @@
 
     key = &ctx->keys[ctx->active];
 
-    *ticket_lifetime = ctx->ticket_lifetime;
+    *ticket_lifetime = key->lifetime;
 
     memcpy(key_name, key->name, TICKET_KEY_NAME_BYTES);
 
@@ -495,43 +502,22 @@
     }
 
 #if defined(MBEDTLS_HAVE_TIME)
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-    if (session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
-        /* Check for expiration */
-        mbedtls_ms_time_t ticket_age = -1;
-#if defined(MBEDTLS_SSL_SRV_C)
-        if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
-            ticket_age = mbedtls_ms_time() - session->ticket_creation_time;
-        }
-#endif
-#if defined(MBEDTLS_SSL_CLI_C)
-        if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
-            ticket_age = mbedtls_ms_time() - session->ticket_reception_time;
-        }
-#endif
+    mbedtls_ms_time_t ticket_creation_time, ticket_age;
+    mbedtls_ms_time_t ticket_lifetime =
+        (mbedtls_ms_time_t) ctx->ticket_lifetime * 1000;
 
-        mbedtls_ms_time_t ticket_lifetime =
-            (mbedtls_ms_time_t) ctx->ticket_lifetime * 1000;
-
-        if (ticket_age < 0 || ticket_age > ticket_lifetime) {
-            ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
-            goto cleanup;
-        }
+    ret = mbedtls_ssl_session_get_ticket_creation_time(session,
+                                                       &ticket_creation_time);
+    if (ret != 0) {
+        goto cleanup;
     }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    if (session->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {
-        /* Check for expiration */
-        mbedtls_time_t current_time = mbedtls_time(NULL);
 
-        if (current_time < session->start ||
-            (uint32_t) (current_time - session->start) > ctx->ticket_lifetime) {
-            ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
-            goto cleanup;
-        }
+    ticket_age = mbedtls_ms_time() - ticket_creation_time;
+    if (ticket_age < 0 || ticket_age > ticket_lifetime) {
+        ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
+        goto cleanup;
     }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-#endif /* MBEDTLS_HAVE_TIME */
+#endif
 
 cleanup:
 #if defined(MBEDTLS_THREADING_C)
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 41ecd3c..5b0a4b9 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -2459,8 +2459,6 @@
  *     } ClientOnlyData;
  *
  *     struct {
- *       uint8 endpoint;
- *       uint8 ciphersuite[2];
  *       uint32 ticket_age_add;
  *       uint8 ticket_flags;
  *       opaque resumption_key<0..255>;
@@ -2486,11 +2484,9 @@
     size_t hostname_len = (session->hostname == NULL) ?
                           0 : strlen(session->hostname) + 1;
 #endif
-    size_t needed =   1                             /* endpoint */
-                    + 2                             /* ciphersuite */
-                    + 4                             /* ticket_age_add */
-                    + 1                             /* ticket_flags */
-                    + 1;                            /* resumption_key length */
+    size_t needed =   4  /* ticket_age_add */
+                    + 1  /* ticket_flags */
+                    + 1; /* resumption_key length */
     *olen = 0;
 
     if (session->resumption_key_len > MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN) {
@@ -2533,14 +2529,12 @@
         return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
     }
 
-    p[0] = session->endpoint;
-    MBEDTLS_PUT_UINT16_BE(session->ciphersuite, p, 1);
-    MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 3);
-    p[7] = session->ticket_flags;
+    MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 0);
+    p[4] = session->ticket_flags;
 
     /* save resumption_key */
-    p[8] = session->resumption_key_len;
-    p += 9;
+    p[5] = session->resumption_key_len;
+    p += 6;
     memcpy(p, session->resumption_key, session->resumption_key_len);
     p += session->resumption_key_len;
 
@@ -2599,17 +2593,15 @@
     const unsigned char *p = buf;
     const unsigned char *end = buf + len;
 
-    if (end - p < 9) {
+    if (end - p < 6) {
         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-    session->endpoint = p[0];
-    session->ciphersuite = MBEDTLS_GET_UINT16_BE(p, 1);
-    session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 3);
-    session->ticket_flags = p[7];
+    session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 0);
+    session->ticket_flags = p[4];
 
     /* load resumption_key */
-    session->resumption_key_len = p[8];
-    p += 9;
+    session->resumption_key_len = p[5];
+    p += 6;
 
     if (end - p < session->resumption_key_len) {
         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
@@ -3787,11 +3779,16 @@
     }
 
     /*
-     * TLS version identifier
+     * TLS version identifier, endpoint, ciphersuite
      */
-    used += 1;
+    used += 1    /* TLS version */
+            + 1  /* endpoint */
+            + 2; /* ciphersuite */
     if (used <= buf_len) {
         *p++ = MBEDTLS_BYTE_0(session->tls_version);
+        *p++ = session->endpoint;
+        MBEDTLS_PUT_UINT16_BE(session->ciphersuite, p, 0);
+        p += 2;
     }
 
     /* Forward to version-specific serialization routine. */
@@ -3874,12 +3871,15 @@
     }
 
     /*
-     * TLS version identifier
+     * TLS version identifier, endpoint, ciphersuite
      */
-    if (1 > (size_t) (end - p)) {
+    if (4 > (size_t) (end - p)) {
         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
     session->tls_version = (mbedtls_ssl_protocol_version) (0x0300 | *p++);
+    session->endpoint = *p++;
+    session->ciphersuite = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
 
     /* Dispatch according to TLS version. */
     remaining_len = (size_t) (end - p);
@@ -8951,19 +8951,24 @@
 /* Serialization of TLS 1.2 sessions:
  *
  * struct {
- *    uint64 start_time;
- *    uint8 ciphersuite[2];           // defined by the standard
- *    uint8 session_id_len;           // at most 32
- *    opaque session_id[32];
- *    opaque master[48];              // fixed length in the standard
- *    uint32 verify_result;
- *    opaque peer_cert<0..2^24-1>;    // length 0 means no peer cert
- *    opaque ticket<0..2^24-1>;       // length 0 means no ticket
- *    uint32 ticket_lifetime;
- *    uint8 mfl_code;                 // up to 255 according to standard
- *    uint8 encrypt_then_mac;         // 0 or 1
- * } serialized_session_tls12;
+ *     opaque ticket<0..2^24-1>;       // length 0 means no ticket
+ *     uint32 ticket_lifetime;
+ * } ClientOnlyData;
  *
+ * struct {
+ *     uint64 start_time;
+ *     uint8 session_id_len;           // at most 32
+ *     opaque session_id[32];
+ *     opaque master[48];              // fixed length in the standard
+ *     uint32 verify_result;
+ *     opaque peer_cert<0..2^24-1>;    // length 0 means no peer cert
+ *     select (endpoint) {
+ *         case client: ClientOnlyData;
+ *         case server: uint64 ticket_creation_time;
+ *     };
+ *     uint8 mfl_code;                 // up to 255 according to standard
+ *     uint8 encrypt_then_mac;         // 0 or 1
+ * } serialized_session_tls12;
  */
 static size_t ssl_tls12_session_save(const mbedtls_ssl_session *session,
                                      unsigned char *buf,
@@ -8998,16 +9003,12 @@
     /*
      * Basic mandatory fields
      */
-    used += 2   /* ciphersuite */
-            + 1 /* id_len */
+    used += 1 /* id_len */
             + sizeof(session->id)
             + sizeof(session->master)
             + 4; /* verify_result */
 
     if (used <= buf_len) {
-        MBEDTLS_PUT_UINT16_BE(session->ciphersuite, p, 0);
-        p += 2;
-
         *p++ = MBEDTLS_BYTE_0(session->id_len);
         memcpy(p, session->id, 32);
         p += 32;
@@ -9065,23 +9066,37 @@
     /*
      * Session ticket if any, plus associated data
      */
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
-    used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+#if defined(MBEDTLS_SSL_CLI_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */
 
-    if (used <= buf_len) {
-        *p++ = MBEDTLS_BYTE_2(session->ticket_len);
-        *p++ = MBEDTLS_BYTE_1(session->ticket_len);
-        *p++ = MBEDTLS_BYTE_0(session->ticket_len);
+        if (used <= buf_len) {
+            *p++ = MBEDTLS_BYTE_2(session->ticket_len);
+            *p++ = MBEDTLS_BYTE_1(session->ticket_len);
+            *p++ = MBEDTLS_BYTE_0(session->ticket_len);
 
-        if (session->ticket != NULL) {
-            memcpy(p, session->ticket, session->ticket_len);
-            p += session->ticket_len;
+            if (session->ticket != NULL) {
+                memcpy(p, session->ticket, session->ticket_len);
+                p += session->ticket_len;
+            }
+
+            MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0);
+            p += 4;
         }
-
-        MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0);
-        p += 4;
     }
-#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
+#endif /* MBEDTLS_SSL_CLI_C */
+#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
+        used += 8;
+
+        if (used <= buf_len) {
+            MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_creation_time, p, 0);
+            p += 8;
+        }
+    }
+#endif /* MBEDTLS_HAVE_TIME && MBEDTLS_SSL_SRV_C */
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
     /*
      * Misc extension-related info
@@ -9139,13 +9154,10 @@
     /*
      * Basic mandatory fields
      */
-    if (2 + 1 + 32 + 48 + 4 > (size_t) (end - p)) {
+    if (1 + 32 + 48 + 4 > (size_t) (end - p)) {
         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    session->ciphersuite = MBEDTLS_GET_UINT16_BE(p, 0);
-    p += 2;
-
     session->id_len = *p++;
     memcpy(session->id, p, 32);
     p += 32;
@@ -9246,35 +9258,48 @@
     /*
      * Session ticket and associated data
      */
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
-    if (3 > (size_t) (end - p)) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-
-    session->ticket_len = MBEDTLS_GET_UINT24_BE(p, 0);
-    p += 3;
-
-    if (session->ticket_len != 0) {
-        if (session->ticket_len > (size_t) (end - p)) {
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+#if defined(MBEDTLS_SSL_CLI_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        if (3 > (size_t) (end - p)) {
             return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
         }
 
-        session->ticket = mbedtls_calloc(1, session->ticket_len);
-        if (session->ticket == NULL) {
-            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        session->ticket_len = MBEDTLS_GET_UINT24_BE(p, 0);
+        p += 3;
+
+        if (session->ticket_len != 0) {
+            if (session->ticket_len > (size_t) (end - p)) {
+                return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+            }
+
+            session->ticket = mbedtls_calloc(1, session->ticket_len);
+            if (session->ticket == NULL) {
+                return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+            }
+
+            memcpy(session->ticket, p, session->ticket_len);
+            p += session->ticket_len;
         }
 
-        memcpy(session->ticket, p, session->ticket_len);
-        p += session->ticket_len;
-    }
+        if (4 > (size_t) (end - p)) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
 
-    if (4 > (size_t) (end - p)) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0);
+        p += 4;
     }
-
-    session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0);
-    p += 4;
-#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
+#endif /* MBEDTLS_SSL_CLI_C */
+#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
+        if (8 > (size_t) (end - p)) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+        session->ticket_creation_time = MBEDTLS_GET_UINT64_BE(p, 0);
+        p += 8;
+    }
+#endif /* MBEDTLS_HAVE_TIME && MBEDTLS_SSL_SRV_C */
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
     /*
      * Misc extension-related info
diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c
index c1ca60c..eac6a3a 100644
--- a/library/ssl_tls12_client.c
+++ b/library/ssl_tls12_client.c
@@ -1268,6 +1268,7 @@
     ssl->tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version(buf,
                                                                                ssl->conf->transport);
     ssl->session_negotiate->tls_version = ssl->tls_version;
+    ssl->session_negotiate->endpoint = ssl->conf->endpoint;
 
     if (ssl->tls_version < ssl->conf->min_tls_version ||
         ssl->tls_version > ssl->conf->max_tls_version) {
diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c
index f242faa..53a9ce2 100644
--- a/library/ssl_tls12_server.c
+++ b/library/ssl_tls12_server.c
@@ -1161,6 +1161,7 @@
     ssl->tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version(buf,
                                                                                ssl->conf->transport);
     ssl->session_negotiate->tls_version = ssl->tls_version;
+    ssl->session_negotiate->endpoint = ssl->conf->endpoint;
 
     if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_2) {
         MBEDTLS_SSL_DEBUG_MSG(1, ("server only supports TLS 1.2"));
@@ -4281,6 +4282,9 @@
      * 10 .  9+n ticket content
      */
 
+#if defined(MBEDTLS_HAVE_TIME)
+    ssl->session_negotiate->ticket_creation_time = mbedtls_ms_time();
+#endif
     if ((ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket,
                                          ssl->session_negotiate,
                                          ssl->out_msg + 10,
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 5d7a495..1e8df1b 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -1478,10 +1478,8 @@
         return SSL_SERVER_HELLO_TLS1_2;
     }
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    ssl->session_negotiate->endpoint = ssl->conf->endpoint;
     ssl->session_negotiate->tls_version = ssl->tls_version;
-#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+    ssl->session_negotiate->endpoint = ssl->conf->endpoint;
 
     handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;
 
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index 05693f3..1411446 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -1437,12 +1437,8 @@
      * We negotiate TLS 1.3.
      */
     ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    /* Store minor version for later use with ticket serialization. */
     ssl->session_negotiate->tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
     ssl->session_negotiate->endpoint = ssl->conf->endpoint;
-#endif
 
     /*
      * We are negotiating the version 1.3 of the protocol. Do what we have
@@ -3132,10 +3128,6 @@
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> prepare NewSessionTicket msg"));
 
-#if defined(MBEDTLS_HAVE_TIME)
-    session->ticket_creation_time = mbedtls_ms_time();
-#endif
-
     /* Set ticket_flags depends on the advertised psk key exchange mode */
     mbedtls_ssl_tls13_session_clear_ticket_flags(
         session, MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);
@@ -3270,6 +3262,9 @@
     MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4 + 4 + 1 + ticket_nonce_size + 2);
 
     /* Generate ticket and ticket_lifetime */
+#if defined(MBEDTLS_HAVE_TIME)
+    session->ticket_creation_time = mbedtls_ms_time();
+#endif
     ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket,
                                     session,
                                     p + 9 + ticket_nonce_size + 2,
diff --git a/library/x509_internal.h b/library/x509_internal.h
index 15e097a..8a2d2ed 100644
--- a/library/x509_internal.h
+++ b/library/x509_internal.h
@@ -21,133 +21,6 @@
 #include "mbedtls/rsa.h"
 #endif
 
-/**
- * \brief          Return the next relative DN in an X509 name.
- *
- * \note           Intended use is to compare function result to dn->next
- *                 in order to detect boundaries of multi-valued RDNs.
- *
- * \param dn       Current node in the X509 name
- *
- * \return         Pointer to the first attribute-value pair of the
- *                 next RDN in sequence, or NULL if end is reached.
- */
-static inline mbedtls_x509_name *mbedtls_x509_dn_get_next(
-    mbedtls_x509_name *dn)
-{
-    while (dn->MBEDTLS_PRIVATE(next_merged) && dn->next != NULL) {
-        dn = dn->next;
-    }
-    return dn->next;
-}
-
-/**
- * \brief          Store the certificate serial in printable form into buf;
- *                 no more than size characters will be written.
- *
- * \param buf      Buffer to write to
- * \param size     Maximum size of buffer
- * \param serial   The X509 serial to represent
- *
- * \return         The length of the string written (not including the
- *                 terminated nul byte), or a negative error code.
- */
-int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial);
-
-/**
- * \brief          Compare pair of mbedtls_x509_time.
- *
- * \param t1       mbedtls_x509_time to compare
- * \param t2       mbedtls_x509_time to compare
- *
- * \return         < 0 if t1 is before t2
- *                   0 if t1 equals t2
- *                 > 0 if t1 is after t2
- */
-int mbedtls_x509_time_cmp(const mbedtls_x509_time *t1, const mbedtls_x509_time *t2);
-
-#if defined(MBEDTLS_HAVE_TIME_DATE)
-/**
- * \brief          Fill mbedtls_x509_time with provided mbedtls_time_t.
- *
- * \param tt       mbedtls_time_t to convert
- * \param now      mbedtls_x509_time to fill with converted mbedtls_time_t
- *
- * \return         \c 0 on success
- * \return         A non-zero return value on failure.
- */
-int mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now);
-#endif /* MBEDTLS_HAVE_TIME_DATE */
-
-/**
- * \brief          Check a given mbedtls_x509_time against the system time
- *                 and tell if it's in the past.
- *
- * \note           Intended usage is "if( is_past( valid_to ) ) ERROR".
- *                 Hence the return value of 1 if on internal errors.
- *
- * \param to       mbedtls_x509_time to check
- *
- * \return         1 if the given time is in the past or an error occurred,
- *                 0 otherwise.
- */
-int mbedtls_x509_time_is_past(const mbedtls_x509_time *to);
-
-/**
- * \brief          Check a given mbedtls_x509_time against the system time
- *                 and tell if it's in the future.
- *
- * \note           Intended usage is "if( is_future( valid_from ) ) ERROR".
- *                 Hence the return value of 1 if on internal errors.
- *
- * \param from     mbedtls_x509_time to check
- *
- * \return         1 if the given time is in the future or an error occurred,
- *                 0 otherwise.
- */
-int mbedtls_x509_time_is_future(const mbedtls_x509_time *from);
-
-/**
- * \brief          This function parses an item in the SubjectAlternativeNames
- *                 extension. Please note that this function might allocate
- *                 additional memory for a subject alternative name, thus
- *                 mbedtls_x509_free_subject_alt_name has to be called
- *                 to dispose of this additional memory afterwards.
- *
- * \param san_buf  The buffer holding the raw data item of the subject
- *                 alternative name.
- * \param san      The target structure to populate with the parsed presentation
- *                 of the subject alternative name encoded in \p san_buf.
- *
- * \note           Supported GeneralName types, as defined in RFC 5280:
- *                 "rfc822Name", "dnsName", "directoryName",
- *                 "uniformResourceIdentifier" and "hardware_module_name"
- *                 of type "otherName", as defined in RFC 4108.
- *
- * \note           This function should be called on a single raw data of
- *                 subject alternative name. For example, after successful
- *                 certificate parsing, one must iterate on every item in the
- *                 \c crt->subject_alt_names sequence, and pass it to
- *                 this function.
- *
- * \warning        The target structure contains pointers to the raw data of the
- *                 parsed certificate, and its lifetime is restricted by the
- *                 lifetime of the certificate.
- *
- * \return         \c 0 on success
- * \return         #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported
- *                 SAN type.
- * \return         Another negative value for any other failure.
- */
-int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
-                                        mbedtls_x509_subject_alternative_name *san);
-/**
- * \brief          Unallocate all data related to subject alternative name
- *
- * \param san      SAN structure - extra memory owned by this structure will be freed
- */
-void mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san);
-
 int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end,
                           mbedtls_x509_name *cur);
 int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end,
diff --git a/programs/fuzz/fuzz_client.c b/programs/fuzz/fuzz_client.c
index d4e1d74..07ca96e 100644
--- a/programs/fuzz/fuzz_client.c
+++ b/programs/fuzz/fuzz_client.c
@@ -1,5 +1,3 @@
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
-
 #include "mbedtls/ssl.h"
 #include "mbedtls/entropy.h"
 #include "mbedtls/ctr_drbg.h"
diff --git a/programs/fuzz/fuzz_dtlsclient.c b/programs/fuzz/fuzz_dtlsclient.c
index 3659026..6581dcb 100644
--- a/programs/fuzz/fuzz_dtlsclient.c
+++ b/programs/fuzz/fuzz_dtlsclient.c
@@ -1,5 +1,3 @@
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
-
 #include <string.h>
 #include <stdlib.h>
 #include <stdint.h>
diff --git a/programs/fuzz/fuzz_dtlsserver.c b/programs/fuzz/fuzz_dtlsserver.c
index 1632e9d..fd3e0aa 100644
--- a/programs/fuzz/fuzz_dtlsserver.c
+++ b/programs/fuzz/fuzz_dtlsserver.c
@@ -1,5 +1,3 @@
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
-
 #include <string.h>
 #include <stdlib.h>
 #include <stdint.h>
@@ -137,7 +135,7 @@
     ret = mbedtls_ssl_handshake(&ssl);
 
     if (ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) {
-        biomemfuzz.Offset = ssl.next_record_offset;
+        biomemfuzz.Offset = ssl.MBEDTLS_PRIVATE(next_record_offset);
         mbedtls_ssl_session_reset(&ssl);
         mbedtls_ssl_set_bio(&ssl, &biomemfuzz, dummy_send, fuzz_recv, fuzz_recv_timeout);
         if (mbedtls_ssl_set_client_transport_id(&ssl, client_ip, sizeof(client_ip)) != 0) {
diff --git a/programs/fuzz/fuzz_privkey.c b/programs/fuzz/fuzz_privkey.c
index ce75624..7530964 100644
--- a/programs/fuzz/fuzz_privkey.c
+++ b/programs/fuzz/fuzz_privkey.c
@@ -1,5 +1,3 @@
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
-
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
@@ -73,7 +71,7 @@
         if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_ECKEY ||
             mbedtls_pk_get_type(&pk) == MBEDTLS_PK_ECKEY_DH) {
             mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(pk);
-            mbedtls_ecp_group_id grp_id = ecp->grp.id;
+            mbedtls_ecp_group_id grp_id = mbedtls_ecp_keypair_get_group_id(ecp);
             const mbedtls_ecp_curve_info *curve_info =
                 mbedtls_ecp_curve_info_from_grp_id(grp_id);
 
diff --git a/programs/fuzz/fuzz_pubkey.c b/programs/fuzz/fuzz_pubkey.c
index 9203b4e..0b153b1 100644
--- a/programs/fuzz/fuzz_pubkey.c
+++ b/programs/fuzz/fuzz_pubkey.c
@@ -1,5 +1,3 @@
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
-
 #include <stdint.h>
 #include <stdlib.h>
 #include "mbedtls/pk.h"
@@ -49,7 +47,7 @@
         if (mbedtls_pk_get_type(&pk) == MBEDTLS_PK_ECKEY ||
             mbedtls_pk_get_type(&pk) == MBEDTLS_PK_ECKEY_DH) {
             mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(pk);
-            mbedtls_ecp_group_id grp_id = ecp->grp.id;
+            mbedtls_ecp_group_id grp_id = mbedtls_ecp_keypair_get_group_id(ecp);
             const mbedtls_ecp_curve_info *curve_info =
                 mbedtls_ecp_curve_info_from_grp_id(grp_id);
 
@@ -61,9 +59,15 @@
 
             /* It's a public key, so the private value should not have
              * been changed from its initialization to 0. */
-            if (mbedtls_mpi_cmp_int(&ecp->d, 0) != 0) {
+            mbedtls_mpi d;
+            mbedtls_mpi_init(&d);
+            if (mbedtls_ecp_export(ecp, NULL, &d, NULL) != 0) {
                 abort();
             }
+            if (mbedtls_mpi_cmp_int(&d, 0) != 0) {
+                abort();
+            }
+            mbedtls_mpi_free(&d);
         } else
 #endif
         {
diff --git a/programs/fuzz/fuzz_server.c b/programs/fuzz/fuzz_server.c
index e767859..64b35ed 100644
--- a/programs/fuzz/fuzz_server.c
+++ b/programs/fuzz/fuzz_server.c
@@ -1,5 +1,3 @@
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
-
 #include "mbedtls/ssl.h"
 #include "mbedtls/entropy.h"
 #include "mbedtls/ctr_drbg.h"
diff --git a/programs/fuzz/fuzz_x509crl.c b/programs/fuzz/fuzz_x509crl.c
index 313540d..151db92 100644
--- a/programs/fuzz/fuzz_x509crl.c
+++ b/programs/fuzz/fuzz_x509crl.c
@@ -1,5 +1,3 @@
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
-
 #include <stdint.h>
 #include "mbedtls/x509_crl.h"
 
diff --git a/programs/fuzz/fuzz_x509crt.c b/programs/fuzz/fuzz_x509crt.c
index 8442090..3eee072 100644
--- a/programs/fuzz/fuzz_x509crt.c
+++ b/programs/fuzz/fuzz_x509crt.c
@@ -1,5 +1,3 @@
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
-
 #include <stdint.h>
 #include "mbedtls/x509_crt.h"
 
diff --git a/programs/fuzz/fuzz_x509csr.c b/programs/fuzz/fuzz_x509csr.c
index 395d3c2..7946e57 100644
--- a/programs/fuzz/fuzz_x509csr.c
+++ b/programs/fuzz/fuzz_x509csr.c
@@ -1,5 +1,3 @@
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
-
 #include <stdint.h>
 #include "mbedtls/x509_csr.h"
 
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 1b3dedb..05bb2ff 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -833,7 +833,7 @@
     mbedtls_net_init(&server_fd);
     mbedtls_ssl_init(&ssl);
     mbedtls_ssl_config_init(&conf);
-    memset(&saved_session, 0, sizeof(mbedtls_ssl_session));
+    mbedtls_ssl_session_init(&saved_session);
     rng_init(&rng);
 #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
     mbedtls_x509_crt_init(&cacert);
diff --git a/programs/ssl/ssl_context_info.c b/programs/ssl/ssl_context_info.c
index c3ae942..ee2cdb7 100644
--- a/programs/ssl/ssl_context_info.c
+++ b/programs/ssl/ssl_context_info.c
@@ -5,8 +5,6 @@
  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
-
 #include "mbedtls/build_info.h"
 #include "mbedtls/debug.h"
 #include "mbedtls/platform.h"
@@ -551,23 +549,23 @@
         const mbedtls_md_info_t *md_info;
 #endif
 
-        printf("\tciphersuite    : %s\n", ciphersuite_info->name);
-        printf("\tcipher flags   : 0x%02X\n", ciphersuite_info->flags);
+        printf("\tciphersuite    : %s\n", mbedtls_ssl_ciphersuite_get_name(ciphersuite_info));
+        printf("\tcipher flags   : 0x%02X\n", ciphersuite_info->MBEDTLS_PRIVATE(flags));
 
 #if defined(MBEDTLS_CIPHER_C)
         const mbedtls_cipher_info_t *cipher_info;
-        cipher_info = mbedtls_cipher_info_from_type(ciphersuite_info->cipher);
+        cipher_info = mbedtls_cipher_info_from_type(ciphersuite_info->MBEDTLS_PRIVATE(cipher));
         if (cipher_info == NULL) {
             printf_err("Cannot find cipher info\n");
         } else {
-            printf("\tcipher         : %s\n", cipher_info->name);
+            printf("\tcipher         : %s\n", mbedtls_cipher_info_get_name(cipher_info));
         }
 #else /* MBEDTLS_CIPHER_C */
-        printf("\tcipher type     : %d\n", ciphersuite_info->cipher);
+        printf("\tcipher type     : %d\n", ciphersuite_info->MBEDTLS_PRIVATE(cipher));
 #endif /* MBEDTLS_CIPHER_C */
 
 #if defined(MBEDTLS_MD_C)
-        md_info = mbedtls_md_info_from_type(ciphersuite_info->mac);
+        md_info = mbedtls_md_info_from_type(ciphersuite_info->MBEDTLS_PRIVATE(mac));
         if (md_info == NULL) {
             printf_err("Cannot find Message-Digest info\n");
         } else {
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 48b2282..abf33de 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -1420,7 +1420,6 @@
             return MBEDTLS_ERR_SSL_INVALID_MAC;
         case 2:
             return MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
         case 3:
             /* Creation time in the future. */
             session->ticket_creation_time = mbedtls_ms_time() + 1000;
@@ -1430,6 +1429,7 @@
             session->ticket_creation_time = mbedtls_ms_time() -
                                             (7 * 24 * 3600 * 1000 + 1000);
             break;
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
         case 5:
             /* Ticket is valid, but client age is below the lower bound of the tolerance window. */
             session->ticket_age_add += MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE + 4 * 1000;
diff --git a/programs/ssl/ssl_test_lib.c b/programs/ssl/ssl_test_lib.c
index a65332a..d3ac526 100644
--- a/programs/ssl/ssl_test_lib.c
+++ b/programs/ssl/ssl_test_lib.c
@@ -8,7 +8,6 @@
  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
 
 #include "ssl_test_lib.h"
 
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index 8fa5d62..93c1729 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -5,8 +5,6 @@
  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
-
 #include "mbedtls/build_info.h"
 
 #include "mbedtls/platform.h"
@@ -1188,141 +1186,44 @@
     }
 #endif
 
-#if defined(MBEDTLS_ECDH_C) && defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
-    if (todo.ecdh) {
-        mbedtls_ecdh_context ecdh;
-        mbedtls_mpi z;
-        const mbedtls_ecp_curve_info montgomery_curve_list[] = {
-#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
-            { MBEDTLS_ECP_DP_CURVE25519, 0, 0, "Curve25519" },
-#endif
-#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
-            { MBEDTLS_ECP_DP_CURVE448, 0, 0, "Curve448" },
-#endif
-            { MBEDTLS_ECP_DP_NONE, 0, 0, 0 }
-        };
-        const mbedtls_ecp_curve_info *curve_info;
-        size_t olen;
-        const mbedtls_ecp_curve_info *selected_montgomery_curve_list =
-            montgomery_curve_list;
-
-        if (curve_list == (const mbedtls_ecp_curve_info *) &single_curve) {
-            mbedtls_ecp_group grp;
-
-            mbedtls_ecp_group_init(&grp);
-            if (mbedtls_ecp_group_load(&grp, curve_list->grp_id) != 0) {
-                mbedtls_exit(1);
-            }
-            if (mbedtls_ecp_get_type(&grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
-                selected_montgomery_curve_list = single_curve;
-            } else { /* empty list */
-                selected_montgomery_curve_list = single_curve + 1;
-            }
-            mbedtls_ecp_group_free(&grp);
-        }
-
-        for (curve_info = curve_list;
-             curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
-             curve_info++) {
-            if (!mbedtls_ecdh_can_do(curve_info->grp_id)) {
-                continue;
-            }
-
-            mbedtls_ecdh_init(&ecdh);
-
-            CHECK_AND_CONTINUE(mbedtls_ecp_group_load(&ecdh.grp, curve_info->grp_id));
-            CHECK_AND_CONTINUE(mbedtls_ecdh_make_public(&ecdh, &olen, buf, sizeof(buf),
-                                                        myrand, NULL));
-            CHECK_AND_CONTINUE(mbedtls_ecp_copy(&ecdh.Qp, &ecdh.Q));
-
-            mbedtls_snprintf(title, sizeof(title), "ECDHE-%s",
-                             curve_info->name);
-            TIME_PUBLIC(title, "handshake",
-                        CHECK_AND_CONTINUE(mbedtls_ecdh_make_public(&ecdh, &olen, buf, sizeof(buf),
-                                                                    myrand, NULL));
-                        CHECK_AND_CONTINUE(mbedtls_ecdh_calc_secret(&ecdh, &olen, buf, sizeof(buf),
-                                                                    myrand, NULL)));
-            mbedtls_ecdh_free(&ecdh);
-        }
-
-        /* Montgomery curves need to be handled separately */
-        for (curve_info = selected_montgomery_curve_list;
-             curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
-             curve_info++) {
-            mbedtls_ecdh_init(&ecdh);
-            mbedtls_mpi_init(&z);
-
-            CHECK_AND_CONTINUE(mbedtls_ecp_group_load(&ecdh.grp, curve_info->grp_id));
-            CHECK_AND_CONTINUE(mbedtls_ecdh_gen_public(&ecdh.grp, &ecdh.d, &ecdh.Qp, myrand, NULL));
-
-            mbedtls_snprintf(title, sizeof(title), "ECDHE-%s",
-                             curve_info->name);
-            TIME_PUBLIC(title, "handshake",
-                        CHECK_AND_CONTINUE(mbedtls_ecdh_gen_public(&ecdh.grp, &ecdh.d, &ecdh.Q,
-                                                                   myrand, NULL));
-                        CHECK_AND_CONTINUE(mbedtls_ecdh_compute_shared(&ecdh.grp, &z, &ecdh.Qp,
-                                                                       &ecdh.d,
-                                                                       myrand, NULL)));
-
-            mbedtls_ecdh_free(&ecdh);
-            mbedtls_mpi_free(&z);
-        }
-
-        for (curve_info = curve_list;
-             curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
-             curve_info++) {
-            if (!mbedtls_ecdh_can_do(curve_info->grp_id)) {
-                continue;
-            }
-
-            mbedtls_ecdh_init(&ecdh);
-
-            CHECK_AND_CONTINUE(mbedtls_ecp_group_load(&ecdh.grp, curve_info->grp_id));
-            CHECK_AND_CONTINUE(mbedtls_ecdh_make_public(&ecdh, &olen, buf, sizeof(buf),
-                                                        myrand, NULL));
-            CHECK_AND_CONTINUE(mbedtls_ecp_copy(&ecdh.Qp, &ecdh.Q));
-            CHECK_AND_CONTINUE(mbedtls_ecdh_make_public(&ecdh, &olen, buf, sizeof(buf),
-                                                        myrand, NULL));
-
-            mbedtls_snprintf(title, sizeof(title), "ECDH-%s",
-                             curve_info->name);
-            TIME_PUBLIC(title, "handshake",
-                        CHECK_AND_CONTINUE(mbedtls_ecdh_calc_secret(&ecdh, &olen, buf, sizeof(buf),
-                                                                    myrand, NULL)));
-            mbedtls_ecdh_free(&ecdh);
-        }
-
-        /* Montgomery curves need to be handled separately */
-        for (curve_info = selected_montgomery_curve_list;
-             curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
-             curve_info++) {
-            mbedtls_ecdh_init(&ecdh);
-            mbedtls_mpi_init(&z);
-
-            CHECK_AND_CONTINUE(mbedtls_ecp_group_load(&ecdh.grp, curve_info->grp_id));
-            CHECK_AND_CONTINUE(mbedtls_ecdh_gen_public(&ecdh.grp, &ecdh.d, &ecdh.Qp,
-                                                       myrand, NULL));
-            CHECK_AND_CONTINUE(mbedtls_ecdh_gen_public(&ecdh.grp, &ecdh.d, &ecdh.Q, myrand, NULL));
-
-            mbedtls_snprintf(title, sizeof(title), "ECDH-%s",
-                             curve_info->name);
-            TIME_PUBLIC(title, "handshake",
-                        CHECK_AND_CONTINUE(mbedtls_ecdh_compute_shared(&ecdh.grp, &z, &ecdh.Qp,
-                                                                       &ecdh.d,
-                                                                       myrand, NULL)));
-
-            mbedtls_ecdh_free(&ecdh);
-            mbedtls_mpi_free(&z);
-        }
-    }
-#endif
-
 #if defined(MBEDTLS_ECDH_C)
     if (todo.ecdh) {
         mbedtls_ecdh_context ecdh_srv, ecdh_cli;
         unsigned char buf_srv[BUFSIZE], buf_cli[BUFSIZE];
         const mbedtls_ecp_curve_info *curve_info;
-        size_t olen;
+        size_t params_len, publen, seclen;
+
+        for (curve_info = curve_list;
+             curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
+             curve_info++) {
+            if (!mbedtls_ecdh_can_do(curve_info->grp_id)) {
+                continue;
+            }
+
+            mbedtls_ecdh_init(&ecdh_srv);
+
+            CHECK_AND_CONTINUE(mbedtls_ecdh_setup(&ecdh_srv, curve_info->grp_id));
+            CHECK_AND_CONTINUE(mbedtls_ecdh_make_params(&ecdh_srv, &params_len, buf_srv,
+                                                        sizeof(buf_srv), myrand, NULL));
+
+            mbedtls_snprintf(title, sizeof(title), "ECDHE-%s", curve_info->name);
+            TIME_PUBLIC(title,
+                        "ephemeral handshake",
+                        const unsigned char *p_srv = buf_srv;
+                        mbedtls_ecdh_init(&ecdh_cli);
+
+                        CHECK_AND_CONTINUE(mbedtls_ecdh_read_params(&ecdh_cli, &p_srv,
+                                                                    p_srv + params_len));
+                        CHECK_AND_CONTINUE(mbedtls_ecdh_make_public(&ecdh_cli, &publen, buf_cli,
+                                                                    sizeof(buf_cli), myrand, NULL));
+
+                        CHECK_AND_CONTINUE(mbedtls_ecdh_calc_secret(&ecdh_cli, &seclen, buf_cli,
+                                                                    sizeof(buf_cli), myrand, NULL));
+                        mbedtls_ecdh_free(&ecdh_cli);
+                        );
+
+            mbedtls_ecdh_free(&ecdh_srv);
+        }
 
         for (curve_info = curve_list;
              curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
@@ -1334,31 +1235,26 @@
             mbedtls_ecdh_init(&ecdh_srv);
             mbedtls_ecdh_init(&ecdh_cli);
 
-            mbedtls_snprintf(title, sizeof(title), "ECDHE-%s", curve_info->name);
+            CHECK_AND_CONTINUE(mbedtls_ecdh_setup(&ecdh_srv, curve_info->grp_id));
+            CHECK_AND_CONTINUE(mbedtls_ecdh_make_params(&ecdh_srv, &params_len, buf_srv,
+                                                        sizeof(buf_srv), myrand, NULL));
+
+            const unsigned char *p_srv = buf_srv;
+            CHECK_AND_CONTINUE(mbedtls_ecdh_read_params(&ecdh_cli, &p_srv,
+                                                        p_srv + params_len));
+            CHECK_AND_CONTINUE(mbedtls_ecdh_make_public(&ecdh_cli, &publen, buf_cli,
+                                                        sizeof(buf_cli), myrand, NULL));
+
+
+            mbedtls_snprintf(title, sizeof(title), "ECDH-%s", curve_info->name);
             TIME_PUBLIC(title,
-                        "full handshake",
-                        const unsigned char *p_srv = buf_srv;
-
-                        CHECK_AND_CONTINUE(mbedtls_ecdh_setup(&ecdh_srv, curve_info->grp_id));
-                        CHECK_AND_CONTINUE(mbedtls_ecdh_make_params(&ecdh_srv, &olen, buf_srv,
-                                                                    sizeof(buf_srv), myrand, NULL));
-
-                        CHECK_AND_CONTINUE(mbedtls_ecdh_read_params(&ecdh_cli, &p_srv,
-                                                                    p_srv + olen));
-                        CHECK_AND_CONTINUE(mbedtls_ecdh_make_public(&ecdh_cli, &olen, buf_cli,
+                        "static handshake",
+                        CHECK_AND_CONTINUE(mbedtls_ecdh_calc_secret(&ecdh_cli, &seclen, buf_cli,
                                                                     sizeof(buf_cli), myrand, NULL));
-
-                        CHECK_AND_CONTINUE(mbedtls_ecdh_read_public(&ecdh_srv, buf_cli, olen));
-                        CHECK_AND_CONTINUE(mbedtls_ecdh_calc_secret(&ecdh_srv, &olen, buf_srv,
-                                                                    sizeof(buf_srv), myrand, NULL));
-
-                        CHECK_AND_CONTINUE(mbedtls_ecdh_calc_secret(&ecdh_cli, &olen, buf_cli,
-                                                                    sizeof(buf_cli), myrand, NULL));
-                        mbedtls_ecdh_free(&ecdh_cli);
-
-                        mbedtls_ecdh_free(&ecdh_srv);
                         );
 
+            mbedtls_ecdh_free(&ecdh_cli);
+            mbedtls_ecdh_free(&ecdh_srv);
         }
     }
 #endif
diff --git a/programs/test/metatest.c b/programs/test/metatest.c
index 8e798cd..5a45f71 100644
--- a/programs/test/metatest.c
+++ b/programs/test/metatest.c
@@ -26,7 +26,6 @@
  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
 
 #include <mbedtls/platform.h>
 #include <mbedtls/platform_util.h>
diff --git a/programs/test/selftest.c b/programs/test/selftest.c
index e132e4c..043209b 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -5,8 +5,6 @@
  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
-
 #include "mbedtls/build_info.h"
 
 #include "mbedtls/entropy.h"
diff --git a/programs/test/udp_proxy.c b/programs/test/udp_proxy.c
index c6b56ec..beaa8bd 100644
--- a/programs/test/udp_proxy.c
+++ b/programs/test/udp_proxy.c
@@ -11,7 +11,6 @@
  * example of good general usage.
  */
 
-#define MBEDTLS_ALLOW_PRIVATE_ACCESS
 
 #include "mbedtls/build_info.h"
 
diff --git a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.h.jinja b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.h.jinja
index 924b08c..4f9764d 100644
--- a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.h.jinja
+++ b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.h.jinja
@@ -731,12 +731,27 @@
 
 static inline psa_status_t psa_driver_wrapper_generate_key(
     const psa_key_attributes_t *attributes,
+    const psa_key_production_parameters_t *params, size_t params_data_length,
     uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_location_t location =
         PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime);
 
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+    int is_default_production =
+        psa_key_production_parameters_are_default(params, params_data_length);
+    if( location != PSA_KEY_LOCATION_LOCAL_STORAGE && !is_default_production )
+    {
+        /* We don't support passing custom production parameters
+         * to drivers yet. */
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+#else
+    int is_default_production = 1;
+    (void) is_default_production;
+#endif
+
     /* Try dynamically-registered SE interface first */
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
     const psa_drv_se_t *drv;
@@ -762,8 +777,11 @@
     {
         case PSA_KEY_LOCATION_LOCAL_STORAGE:
 #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
-            /* Transparent drivers are limited to generating asymmetric keys */
-            if( PSA_KEY_TYPE_IS_ASYMMETRIC( attributes->core.type ) )
+            /* Transparent drivers are limited to generating asymmetric keys. */
+            /* We don't support passing custom production parameters
+             * to drivers yet. */
+            if( PSA_KEY_TYPE_IS_ASYMMETRIC( attributes->core.type ) &&
+                is_default_production )
             {
             /* Cycle through all known transparent accelerators */
 #if defined(PSA_CRYPTO_DRIVER_TEST)
@@ -793,7 +811,8 @@
 
             /* Software fallback */
             status = psa_generate_key_internal(
-                attributes, key_buffer, key_buffer_size, key_buffer_length );
+                attributes, params, params_data_length,
+                key_buffer, key_buffer_size, key_buffer_length );
             break;
 
         /* Add cases for opaque driver here */
diff --git a/tests/include/test/psa_exercise_key.h b/tests/include/test/psa_exercise_key.h
index a658d17..44f5c08 100644
--- a/tests/include/test/psa_exercise_key.h
+++ b/tests/include/test/psa_exercise_key.h
@@ -14,21 +14,17 @@
 
 #include <psa/crypto.h>
 
+#if defined(MBEDTLS_PK_C)
+#include <mbedtls/pk.h>
+#endif
+
 /** \def KNOWN_SUPPORTED_HASH_ALG
  *
  * A hash algorithm that is known to be supported.
  *
  * This is used in some smoke tests.
  */
-#if defined(PSA_WANT_ALG_MD5)
-#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_MD5
-/* PSA_WANT_ALG_RIPEMD160 omitted. This is necessary for the sake of
- * exercise_signature_key() because Mbed TLS doesn't support RIPEMD160
- * in RSA PKCS#1v1.5 signatures. A RIPEMD160-only configuration would be
- * implausible anyway. */
-#elif defined(PSA_WANT_ALG_SHA_1)
-#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_1
-#elif defined(PSA_WANT_ALG_SHA_256)
+#if defined(PSA_WANT_ALG_SHA_256)
 #define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_256
 #elif defined(PSA_WANT_ALG_SHA_384)
 #define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_384
@@ -36,6 +32,14 @@
 #define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_512
 #elif defined(PSA_WANT_ALG_SHA3_256)
 #define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA3_256
+#elif defined(PSA_WANT_ALG_SHA_1)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_SHA_1
+#elif defined(PSA_WANT_ALG_MD5)
+#define KNOWN_SUPPORTED_HASH_ALG PSA_ALG_MD5
+/* PSA_WANT_ALG_RIPEMD160 omitted. This is necessary for the sake of
+ * exercise_signature_key() because Mbed TLS doesn't support RIPEMD160
+ * in RSA PKCS#1v1.5 signatures. A RIPEMD160-only configuration would be
+ * implausible anyway. */
 #else
 #undef KNOWN_SUPPORTED_HASH_ALG
 #endif
@@ -221,4 +225,37 @@
 psa_key_usage_t mbedtls_test_psa_usage_to_exercise(psa_key_type_t type,
                                                    psa_algorithm_t alg);
 
+/** Whether the specified algorithm can be exercised.
+ *
+ * \note This function is solely based on the algorithm and does not
+ *       consider potential issues with the compatibility of a key.
+ *       The idea is that you already have a key, so you know that the
+ *       key type is supported, and you want to exercise the key but
+ *       only if the algorithm given in its policy is enabled in the
+ *       compile-time configuration.
+ *
+ * \note This function currently only supports signature algorithms
+ *       (including wildcards).
+ *       TODO: a more general mechanism, which should be automatically
+ *       generated and possibly available as a library function?
+ */
+int mbedtls_test_can_exercise_psa_algorithm(psa_algorithm_t alg);
+
+#if defined(MBEDTLS_PK_C)
+/** PK-PSA key consistency test.
+ *
+ * This function tests that the pk context and the PSA key are
+ * consistent. At a minimum:
+ *
+ * - The two objects must contain keys of the same type,
+ *   or a key pair and a public key of the matching type.
+ * - The two objects must have the same public key.
+ *
+ * \retval 0 The key failed the consistency tests.
+ * \retval 1 The key passed the consistency tests.
+ */
+int mbedtls_test_key_consistency_psa_pk(mbedtls_svc_key_id_t psa_key,
+                                        const mbedtls_pk_context *pk);
+#endif /* MBEDTLS_PK_C */
+
 #endif /* PSA_EXERCISE_KEY_H */
diff --git a/tests/include/test/ssl_helpers.h b/tests/include/test/ssl_helpers.h
index 3506609..9a078f6 100644
--- a/tests/include/test/ssl_helpers.h
+++ b/tests/include/test/ssl_helpers.h
@@ -532,6 +532,7 @@
  */
 int mbedtls_test_ssl_tls12_populate_session(mbedtls_ssl_session *session,
                                             int ticket_len,
+                                            int endpoint_type,
                                             const char *crt_file);
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index f18bfad..c25f044 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -5036,6 +5036,19 @@
     programs/test/selftest
 }
 
+component_test_gcm_largetable () {
+    msg "build: default config + GCM_LARGE_TABLE - AESNI_C - AESCE_C"
+    scripts/config.py set MBEDTLS_GCM_LARGE_TABLE
+    scripts/config.py unset MBEDTLS_PADLOCK_C
+    scripts/config.py unset MBEDTLS_AESNI_C
+    scripts/config.py unset MBEDTLS_AESCE_C
+
+    make CFLAGS='-O2 -Werror -Wall -Wextra'
+
+    msg "test: default config - GCM_LARGE_TABLE - AESNI_C - AESCE_C"
+    make test
+}
+
 component_test_aes_fewer_tables () {
     msg "build: default config with AES_FEWER_TABLES enabled"
     scripts/config.py set MBEDTLS_AES_FEWER_TABLES
diff --git a/tests/scripts/analyze_outcomes.py b/tests/scripts/analyze_outcomes.py
index 11e4836..5b4deb6 100755
--- a/tests/scripts/analyze_outcomes.py
+++ b/tests/scripts/analyze_outcomes.py
@@ -570,6 +570,11 @@
                     re.compile(r'mbedtls_ct_zeroize_if .*'),
                     re.compile(r'mbedtls_ct_memmove_left .*')
                 ],
+                'test_suite_psa_crypto': [
+                    # We don't support generate_key_ext entry points
+                    # in drivers yet.
+                    re.compile(r'PSA generate key ext: RSA, e=.*'),
+                ],
             }
         }
     },
@@ -614,8 +619,7 @@
                 'test_suite_pem': [
                     # Following tests require AES_C, but this is diabled in the
                     # accelerated component.
-                    'PEM read (AES-128-CBC + invalid iv)',
-                    'PEM read (malformed PEM AES-128-CBC)',
+                    re.compile('PEM read .*AES.*'),
                     'PEM read (unknown encryption algorithm)',
                 ],
                 'test_suite_error': [
diff --git a/tests/scripts/depends.py b/tests/scripts/depends.py
index 1a84531..1990cd2 100755
--- a/tests/scripts/depends.py
+++ b/tests/scripts/depends.py
@@ -199,7 +199,10 @@
         success = True
         for command in self.commands:
             log_command(command)
-            ret = subprocess.call(command)
+            env = os.environ.copy()
+            if 'MBEDTLS_TEST_CONFIGURATION' in env:
+                env['MBEDTLS_TEST_CONFIGURATION'] += '-' + self.name
+            ret = subprocess.call(command, env=env)
             if ret != 0:
                 if command[0] not in ['make', options.make_command]:
                     log_line('*** [{}] Error {}'.format(' '.join(command), ret))
diff --git a/tests/src/drivers/test_driver_key_management.c b/tests/src/drivers/test_driver_key_management.c
index a3d532d..866b31e 100644
--- a/tests/src/drivers/test_driver_key_management.c
+++ b/tests/src/drivers/test_driver_key_management.c
@@ -225,10 +225,13 @@
         defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
         return libtestdriver1_mbedtls_psa_rsa_generate_key(
             (const libtestdriver1_psa_key_attributes_t *) attributes,
+            NULL, 0, /* We don't support custom e in the test driver yet */
             key, key_size, key_length);
 #elif defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
         return mbedtls_psa_rsa_generate_key(
-            attributes, key, key_size, key_length);
+            attributes,
+            NULL, 0, /* We don't support custom e in the test driver yet */
+            key, key_size, key_length);
 #endif
     } else if (PSA_KEY_TYPE_IS_DH(psa_get_key_type(attributes))
                && PSA_KEY_TYPE_IS_KEY_PAIR(psa_get_key_type(attributes))) {
diff --git a/tests/src/helpers.c b/tests/src/helpers.c
index b9233be..2433422 100644
--- a/tests/src/helpers.c
+++ b/tests/src/helpers.c
@@ -31,7 +31,16 @@
 #endif /* MBEDTLS_THREADING_C */
 
 /*----------------------------------------------------------------------------*/
-/* Mbedtls Test Info accessors */
+/* Mbedtls Test Info accessors
+ *
+ * NOTE - there are two types of accessors here: public accessors and internal
+ * accessors. The public accessors have prototypes in helpers.h and lock
+ * mbedtls_test_info_mutex (if mutexes are enabled). The _internal accessors,
+ * which are expected to be used from this module *only*, do not lock the mutex.
+ * These are designed to be called from within public functions which already
+ * hold the mutex. The main reason for this difference is the need to set
+ * multiple test data values atomically (without releasing the mutex) to prevent
+ * race conditions. */
 
 mbedtls_test_result_t mbedtls_test_get_result(void)
 {
@@ -50,8 +59,8 @@
     return result;
 }
 
-void mbedtls_test_set_result(mbedtls_test_result_t result, const char *test,
-                             int line_no, const char *filename)
+static void mbedtls_test_set_result_internal(mbedtls_test_result_t result, const char *test,
+                                             int line_no, const char *filename)
 {
     /* Internal function only - mbedtls_test_info_mutex should be held prior
      * to calling this function. */
@@ -144,7 +153,7 @@
     return step;
 }
 
-void mbedtls_test_reset_step(void)
+static void mbedtls_test_reset_step_internal(void)
 {
     /* Internal function only - mbedtls_test_info_mutex should be held prior
      * to calling this function. */
@@ -178,7 +187,7 @@
 #endif /* MBEDTLS_THREADING_C */
 }
 
-void mbedtls_test_set_line1(const char *line)
+static void mbedtls_test_set_line1_internal(const char *line)
 {
     /* Internal function only - mbedtls_test_info_mutex should be held prior
      * to calling this function. */
@@ -203,7 +212,7 @@
 #endif /* MBEDTLS_THREADING_C */
 }
 
-void mbedtls_test_set_line2(const char *line)
+static void mbedtls_test_set_line2_internal(const char *line)
 {
     /* Internal function only - mbedtls_test_info_mutex should be held prior
      * to calling this function. */
@@ -219,7 +228,19 @@
 #if defined(MBEDTLS_TEST_MUTEX_USAGE)
 const char *mbedtls_test_get_mutex_usage_error(void)
 {
-    return mbedtls_test_info.mutex_usage_error;
+    const char *usage_error;
+
+#ifdef MBEDTLS_THREADING_C
+    mbedtls_mutex_lock(&mbedtls_test_info_mutex);
+#endif /* MBEDTLS_THREADING_C */
+
+    usage_error = mbedtls_test_info.mutex_usage_error;
+
+#ifdef MBEDTLS_THREADING_C
+    mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
+#endif /* MBEDTLS_THREADING_C */
+
+    return usage_error;
 }
 
 void mbedtls_test_set_mutex_usage_error(const char *msg)
@@ -255,7 +276,7 @@
     return test_case_uses_negative_0;
 }
 
-void mbedtls_test_set_case_uses_negative_0(unsigned uses)
+static void mbedtls_test_set_case_uses_negative_0_internal(unsigned uses)
 {
     /* Internal function only - mbedtls_test_info_mutex should be held prior
      * to calling this function. */
@@ -350,7 +371,7 @@
     if (mbedtls_test_info.result != MBEDTLS_TEST_RESULT_FAILED) {
         /* If we have already recorded the test as having failed then don't
          * overwrite any previous information about the failure. */
-        mbedtls_test_set_result(MBEDTLS_TEST_RESULT_FAILED, test, line_no, filename);
+        mbedtls_test_set_result_internal(MBEDTLS_TEST_RESULT_FAILED, test, line_no, filename);
     }
 }
 
@@ -373,7 +394,7 @@
     mbedtls_mutex_lock(&mbedtls_test_info_mutex);
 #endif /* MBEDTLS_THREADING_C */
 
-    mbedtls_test_set_result(MBEDTLS_TEST_RESULT_SKIPPED, test, line_no, filename);
+    mbedtls_test_set_result_internal(MBEDTLS_TEST_RESULT_SKIPPED, test, line_no, filename);
 
 #ifdef MBEDTLS_THREADING_C
     mbedtls_mutex_unlock(&mbedtls_test_info_mutex);
@@ -386,13 +407,13 @@
     mbedtls_mutex_lock(&mbedtls_test_info_mutex);
 #endif /* MBEDTLS_THREADING_C */
 
-    mbedtls_test_set_result(MBEDTLS_TEST_RESULT_SUCCESS, 0, 0, 0);
-    mbedtls_test_reset_step();
-    mbedtls_test_set_line1(NULL);
-    mbedtls_test_set_line2(NULL);
+    mbedtls_test_set_result_internal(MBEDTLS_TEST_RESULT_SUCCESS, 0, 0, 0);
+    mbedtls_test_reset_step_internal();
+    mbedtls_test_set_line1_internal(NULL);
+    mbedtls_test_set_line2_internal(NULL);
 
 #if defined(MBEDTLS_BIGNUM_C)
-    mbedtls_test_set_case_uses_negative_0(0);
+    mbedtls_test_set_case_uses_negative_0_internal(0);
 #endif
 
 #ifdef MBEDTLS_THREADING_C
@@ -424,11 +445,11 @@
         (void) mbedtls_snprintf(buf, sizeof(buf),
                                 "lhs = 0x%016llx = %lld",
                                 value1, (long long) value1);
-        mbedtls_test_set_line1(buf);
+        mbedtls_test_set_line1_internal(buf);
         (void) mbedtls_snprintf(buf, sizeof(buf),
                                 "rhs = 0x%016llx = %lld",
                                 value2, (long long) value2);
-        mbedtls_test_set_line2(buf);
+        mbedtls_test_set_line2_internal(buf);
     }
 
 #ifdef MBEDTLS_THREADING_C
@@ -462,11 +483,11 @@
         (void) mbedtls_snprintf(buf, sizeof(buf),
                                 "lhs = 0x%016llx = %llu",
                                 value1, value1);
-        mbedtls_test_set_line1(buf);
+        mbedtls_test_set_line1_internal(buf);
         (void) mbedtls_snprintf(buf, sizeof(buf),
                                 "rhs = 0x%016llx = %llu",
                                 value2, value2);
-        mbedtls_test_set_line2(buf);
+        mbedtls_test_set_line2_internal(buf);
     }
 
 #ifdef MBEDTLS_THREADING_C
@@ -500,11 +521,11 @@
         (void) mbedtls_snprintf(buf, sizeof(buf),
                                 "lhs = 0x%016llx = %lld",
                                 (unsigned long long) value1, value1);
-        mbedtls_test_set_line1(buf);
+        mbedtls_test_set_line1_internal(buf);
         (void) mbedtls_snprintf(buf, sizeof(buf),
                                 "rhs = 0x%016llx = %lld",
                                 (unsigned long long) value2, value2);
-        mbedtls_test_set_line2(buf);
+        mbedtls_test_set_line2_internal(buf);
     }
 
 #ifdef MBEDTLS_THREADING_C
diff --git a/tests/src/psa_exercise_key.c b/tests/src/psa_exercise_key.c
index 560b711..7b81052 100644
--- a/tests/src/psa_exercise_key.c
+++ b/tests/src/psa_exercise_key.c
@@ -20,6 +20,16 @@
 #include <psa_crypto_slot_management.h>
 #include <test/psa_crypto_helpers.h>
 
+#if defined(MBEDTLS_PK_C)
+#include <pk_internal.h>
+#endif
+#if defined(MBEDTLS_ECP_C)
+#include <mbedtls/ecp.h>
+#endif
+#if defined(MBEDTLS_RSA_C)
+#include <rsa_internal.h>
+#endif
+
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
 static int lifetime_is_dynamic_secure_element(psa_key_lifetime_t lifetime)
 {
@@ -283,23 +293,25 @@
                                   psa_key_usage_t usage,
                                   psa_algorithm_t alg)
 {
+    /* If the policy allows signing with any hash, just pick one. */
+    psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
+    if (PSA_ALG_IS_SIGN_HASH(alg) && hash_alg == PSA_ALG_ANY_HASH &&
+        usage & (PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH |
+                 PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE)) {
+#if defined(KNOWN_SUPPORTED_HASH_ALG)
+        hash_alg = KNOWN_SUPPORTED_HASH_ALG;
+        alg ^= PSA_ALG_ANY_HASH ^ hash_alg;
+#else
+        TEST_FAIL("No hash algorithm for hash-and-sign testing");
+#endif
+    }
+
     if (usage & (PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH) &&
         PSA_ALG_IS_SIGN_HASH(alg)) {
         unsigned char payload[PSA_HASH_MAX_SIZE] = { 1 };
         size_t payload_length = 16;
         unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = { 0 };
         size_t signature_length = sizeof(signature);
-        psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
-
-        /* If the policy allows signing with any hash, just pick one. */
-        if (PSA_ALG_IS_SIGN_HASH(alg) && hash_alg == PSA_ALG_ANY_HASH) {
-    #if defined(KNOWN_SUPPORTED_HASH_ALG)
-            hash_alg = KNOWN_SUPPORTED_HASH_ALG;
-            alg ^= PSA_ALG_ANY_HASH ^ hash_alg;
-    #else
-            TEST_FAIL("No hash algorithm for hash-and-sign testing");
-    #endif
-        }
 
         /* Some algorithms require the payload to have the size of
          * the hash encoded in the algorithm. Use this input size
@@ -362,8 +374,10 @@
                                               psa_key_usage_t usage,
                                               psa_algorithm_t alg)
 {
-    unsigned char plaintext[256] = "Hello, world...";
-    unsigned char ciphertext[256] = "(wabblewebblewibblewobblewubble)";
+    unsigned char plaintext[PSA_ASYMMETRIC_DECRYPT_OUTPUT_MAX_SIZE] =
+        "Hello, world...";
+    unsigned char ciphertext[PSA_ASYMMETRIC_ENCRYPT_OUTPUT_MAX_SIZE] =
+        "(wabblewebblewibblewobblewubble)";
     size_t ciphertext_length = sizeof(ciphertext);
     size_t plaintext_length = 16;
 
@@ -1005,4 +1019,142 @@
 
 }
 
+int mbedtls_test_can_exercise_psa_algorithm(psa_algorithm_t alg)
+{
+    /* Reject algorithms that we know are not supported. Default to
+     * attempting exercise, so that if an algorithm is missing from this
+     * function, the result will be a test failure and not silently
+     * omitting exercise. */
+#if !defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT)
+    if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) {
+        return 0;
+    }
+#endif
+#if !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN)
+    if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) {
+        return 0;
+    }
+#endif
+#if !defined(PSA_WANT_ALG_RSA_PSS)
+    if (PSA_ALG_IS_RSA_PSS_STANDARD_SALT(alg)) {
+        return 0;
+    }
+#endif
+#if !defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT)
+    if (PSA_ALG_IS_RSA_PSS_ANY_SALT(alg)) {
+        return 0;
+    }
+#endif
+#if !defined(PSA_WANT_ALG_ECDSA)
+    if (PSA_ALG_IS_ECDSA(alg)) {
+        return 0;
+    }
+#endif
+#if !defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)
+    if (PSA_ALG_IS_DETERMINISTIC_ECDSA(alg)) {
+        return 0;
+    }
+#endif
+#if !defined(PSA_WANT_ALG_ECDH)
+    if (PSA_ALG_IS_ECDH(alg)) {
+        return 0;
+    }
+#endif
+    (void) alg;
+    return 1;
+}
+
+#if defined(MBEDTLS_PK_C)
+int mbedtls_test_key_consistency_psa_pk(mbedtls_svc_key_id_t psa_key,
+                                        const mbedtls_pk_context *pk)
+{
+    psa_key_attributes_t psa_attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_attributes_t pk_attributes = PSA_KEY_ATTRIBUTES_INIT;
+    int ok = 0;
+
+    PSA_ASSERT(psa_get_key_attributes(psa_key, &psa_attributes));
+    psa_key_type_t psa_type = psa_get_key_type(&psa_attributes);
+    mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk);
+
+    TEST_ASSERT(PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_type) ||
+                PSA_KEY_TYPE_IS_KEY_PAIR(psa_type));
+    TEST_EQUAL(psa_get_key_bits(&psa_attributes), mbedtls_pk_get_bitlen(pk));
+
+    uint8_t pk_public_buffer[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
+    const uint8_t *pk_public = NULL;
+    size_t pk_public_length = 0;
+
+    switch (pk_type) {
+#if defined(MBEDTLS_RSA_C)
+        case MBEDTLS_PK_RSA:
+            TEST_ASSERT(PSA_KEY_TYPE_IS_RSA(psa_type));
+            const mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
+            uint8_t *const end = pk_public_buffer + sizeof(pk_public_buffer);
+            uint8_t *cursor = end;
+            TEST_LE_U(1, mbedtls_rsa_write_pubkey(rsa,
+                                                  pk_public_buffer, &cursor));
+            pk_public = cursor;
+            pk_public_length = end - pk_public;
+            break;
+#endif
+
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+        case MBEDTLS_PK_ECKEY:
+        case MBEDTLS_PK_ECKEY_DH:
+        case MBEDTLS_PK_ECDSA:
+            TEST_ASSERT(PSA_KEY_TYPE_IS_ECC(psa_type));
+            TEST_EQUAL(PSA_KEY_TYPE_ECC_GET_FAMILY(psa_type), pk->ec_family);
+            pk_public = pk->pub_raw;
+            pk_public_length = pk->pub_raw_len;
+            break;
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+        case MBEDTLS_PK_ECKEY:
+        case MBEDTLS_PK_ECKEY_DH:
+        case MBEDTLS_PK_ECDSA:
+            TEST_ASSERT(PSA_KEY_TYPE_IS_ECC(psa_get_key_type(&psa_attributes)));
+            const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);
+            TEST_EQUAL(mbedtls_ecp_write_public_key(
+                           ec, MBEDTLS_ECP_PF_UNCOMPRESSED, &pk_public_length,
+                           pk_public_buffer, sizeof(pk_public_buffer)), 0);
+            pk_public = pk_public_buffer;
+            break;
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_PK_USE_PSA_EC_DATA */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        case MBEDTLS_PK_OPAQUE:
+            PSA_ASSERT(psa_get_key_attributes(pk->priv_id, &pk_attributes));
+            psa_key_type_t pk_psa_type = psa_get_key_type(&pk_attributes);
+            TEST_EQUAL(PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(psa_type),
+                       PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(pk_psa_type));
+            PSA_ASSERT(psa_export_public_key(psa_key,
+                                             pk_public_buffer,
+                                             sizeof(pk_public_buffer),
+                                             &pk_public_length));
+            pk_public = pk_public_buffer;
+            break;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+        default:
+            TEST_FAIL("pk type not supported");
+    }
+
+    uint8_t psa_public[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
+    size_t psa_public_length = 0;
+    PSA_ASSERT(psa_export_public_key(psa_key,
+                                     psa_public, sizeof(psa_public),
+                                     &psa_public_length));
+    TEST_MEMORY_COMPARE(pk_public, pk_public_length,
+                        psa_public, psa_public_length);
+
+    ok = 1;
+
+exit:
+    psa_reset_key_attributes(&psa_attributes);
+    psa_reset_key_attributes(&pk_attributes);
+    return ok;
+}
+#endif /* MBEDTLS_PK_C */
+
 #endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/tests/src/test_helpers/ssl_helpers.c b/tests/src/test_helpers/ssl_helpers.c
index ad4c070..7a28bd8 100644
--- a/tests/src/test_helpers/ssl_helpers.c
+++ b/tests/src/test_helpers/ssl_helpers.c
@@ -1646,12 +1646,20 @@
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
 int mbedtls_test_ssl_tls12_populate_session(mbedtls_ssl_session *session,
                                             int ticket_len,
+                                            int endpoint_type,
                                             const char *crt_file)
 {
+    (void) ticket_len;
+
 #if defined(MBEDTLS_HAVE_TIME)
     session->start = mbedtls_time(NULL) - 42;
 #endif
     session->tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+
+    TEST_ASSERT(endpoint_type == MBEDTLS_SSL_IS_CLIENT ||
+                endpoint_type == MBEDTLS_SSL_IS_SERVER);
+
+    session->endpoint = endpoint_type;
     session->ciphersuite = 0xabcd;
     session->id_len = sizeof(session->id);
     memset(session->id, 66, session->id_len);
@@ -1717,7 +1725,8 @@
 #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED && MBEDTLS_FS_IO */
     session->verify_result = 0xdeadbeef;
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+#if defined(MBEDTLS_SSL_CLI_C)
     if (ticket_len != 0) {
         session->ticket = mbedtls_calloc(1, ticket_len);
         if (session->ticket == NULL) {
@@ -1727,9 +1736,14 @@
     }
     session->ticket_len = ticket_len;
     session->ticket_lifetime = 86401;
-#else
-    (void) ticket_len;
+#endif /* MBEDTLS_SSL_CLI_C */
+
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_HAVE_TIME)
+    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
+        session->ticket_creation_time = mbedtls_ms_time() - 42;
+    }
 #endif
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
     session->mfl_code = 1;
@@ -1738,6 +1752,7 @@
     session->encrypt_then_mac = 1;
 #endif
 
+exit:
     return 0;
 }
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
diff --git a/tests/src/threading_helpers.c b/tests/src/threading_helpers.c
index ff0c712..c1686c2 100644
--- a/tests/src/threading_helpers.c
+++ b/tests/src/threading_helpers.c
@@ -317,22 +317,26 @@
 
 void mbedtls_test_mutex_usage_check(void)
 {
-    if (live_mutexes != 0) {
-        /* A positive number (more init than free) means that a mutex resource
-         * is leaking (on platforms where a mutex consumes more than the
-         * mbedtls_threading_mutex_t object itself). The rare case of a
-         * negative number means a missing init somewhere. */
-        mbedtls_fprintf(stdout, "[mutex: %d leaked] ", live_mutexes);
-        live_mutexes = 0;
-        mbedtls_test_set_mutex_usage_error("missing free");
+    if (mutex_functions.lock(&mbedtls_test_mutex_mutex) == 0) {
+        if (live_mutexes != 0) {
+            /* A positive number (more init than free) means that a mutex resource
+             * is leaking (on platforms where a mutex consumes more than the
+             * mbedtls_threading_mutex_t object itself). The (hopefully) rare
+             * case of a negative number means a missing init somewhere. */
+            mbedtls_fprintf(stdout, "[mutex: %d leaked] ", live_mutexes);
+            live_mutexes = 0;
+            mbedtls_test_set_mutex_usage_error("missing free");
+        }
+        if (mbedtls_test_get_mutex_usage_error() != NULL &&
+            mbedtls_test_get_result() != MBEDTLS_TEST_RESULT_FAILED) {
+            /* Functionally, the test passed. But there was a mutex usage error,
+             * so mark the test as failed after all. */
+            mbedtls_test_fail("Mutex usage error", __LINE__, __FILE__);
+        }
+        mbedtls_test_set_mutex_usage_error(NULL);
+
+        mutex_functions.unlock(&mbedtls_test_mutex_mutex);
     }
-    if (mbedtls_test_get_mutex_usage_error() != NULL &&
-        mbedtls_test_get_result() != MBEDTLS_TEST_RESULT_FAILED) {
-        /* Functionally, the test passed. But there was a mutex usage error,
-         * so mark the test as failed after all. */
-        mbedtls_test_fail("Mutex usage error", __LINE__, __FILE__);
-    }
-    mbedtls_test_set_mutex_usage_error(NULL);
 }
 
 void mbedtls_test_mutex_usage_end(void)
diff --git a/tests/suites/test_suite_pem.data b/tests/suites/test_suite_pem.data
index a4dff45..007ba10 100644
--- a/tests/suites/test_suite_pem.data
+++ b/tests/suites/test_suite_pem.data
@@ -22,6 +22,9 @@
 PEM read (unencrypted, valid)
 mbedtls_pem_read_buffer:"^":"$":"^\nTWJlZCBUTFM=\n$":"":0:"4d62656420544c53"
 
+PEM read (unencrypted, empty content)
+mbedtls_pem_read_buffer:"-----BEGIN EC PRIVATE KEY-----":"-----END EC PRIVATE KEY-----":"-----BEGIN EC PRIVATE KEY-----\n\n-----END EC PRIVATE KEY-----":"":MBEDTLS_ERR_PEM_BAD_INPUT_DATA:""
+
 PEM read (DES-EDE3-CBC + invalid iv)
 depends_on:MBEDTLS_MD_CAN_MD5:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_DES_C
 mbedtls_pem_read_buffer:"^":"$":"^\nProc-Type\: 4,ENCRYPTED\nDEK-Info\: DES-EDE3-CBC,00$":"pwd":MBEDTLS_ERR_PEM_INVALID_ENC_IV:""
@@ -49,3 +52,35 @@
 PEM read (malformed PEM AES-128-CBC)
 depends_on:MBEDTLS_MD_CAN_MD5:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
 mbedtls_pem_read_buffer:"-----BEGIN EC PRIVATE KEY-----":"-----END EC PRIVATE KEY-----":"-----BEGIN EC PRIVATE KEY-----\nProc-Type\: 4,ENCRYPTED\nDEK-Info\: AES-128-CBC,AA94892A169FA426AA94892A169FA426\n\nMAAA\n-----END EC PRIVATE KEY-----":"pwd":MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH:""
+
+# The output sequence's length is not multiple of block size (16 bytes). This
+# proves that the pem_context->len value is properly updated based on the SEQUENCE
+# length read from the decoded ASN.1 data (i.e. extra padding, if any, is ignored).
+PEM read (valid EC key encoded with AES-128-CBC)
+depends_on:MBEDTLS_MD_CAN_MD5:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+mbedtls_pem_read_buffer:"-----BEGIN EC PRIVATE KEY-----":"-----END EC PRIVATE KEY-----":"-----BEGIN EC PRIVATE KEY-----\nProc-Type\: 4,ENCRYPTED\nDEK-Info\: AES-128-CBC,151F851B6A7F3FBDAA5B7173117D0127\n\nLw+0OM+0Bwcl+ls/vxQbLrVshGc7bsNPvvtj2sJeMFFEq3V1mj/IO++0KK/CDhMH\nh6CZPsmgVOeM5uFpqYaq0fJbUduN2eDMWszWRm0SFkY=\n-----END EC PRIVATE KEY-----":"pwdpwd":0:"3041020101040f00d8023c809afd45e426d1a4dbe0ffa00706052b81040004a1220320000400da1ecfa53d528237625e119e2e0500d2eb671724f16deb6a63749516b7"
+
+# The text "hello world" together with some invalid padding data is encoded
+# with AES-128-CBC in order to test padding validation.
+# Since PBKDF1 isn't supported in OpenSSL, here's the steps:
+# 1. generate the key (password="password";  IV=0x3132333435363738 in hex or "12345678" as string)
+#       echo -n "password12345678" | openssl md5
+# 2. encode data
+#   echo -n -e "\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x01\x02\x03\x04\x05" | openssl aes-128-cbc -e -base64 -p -K "bbb0ddff1b944b3cc68eaaeb7ac20099" -iv "3132333435363738" -nopad
+PEM read (AES-128-CBC, invalid padding data)
+depends_on:MBEDTLS_MD_CAN_MD5:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+mbedtls_pem_read_buffer:"-----BEGIN EC PRIVATE KEY-----":"-----END EC PRIVATE KEY-----":"-----BEGIN EC PRIVATE KEY-----\nProc-Type\: 4,ENCRYPTED\nDEK-Info\: AES-128-CBC,31323334353637380000000000000000\n\n333hxynfxEdXrSHQfIabxQ==\n-----END EC PRIVATE KEY-----":"password":MBEDTLS_ERR_PEM_PASSWORD_MISMATCH:""
+
+# Padding data (0x11) is larger than AES block size (16).
+# Generated with:
+#   echo -n -e "\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x11\x11\x11\x11\x11" | openssl aes-128-cbc -e -base64 -p -K "bbb0ddff1b944b3cc68eaaeb7ac20099" -iv "3132333435363738" -nopad
+PEM read (AES-128-CBC, padding data is larger than AES block length)
+depends_on:MBEDTLS_MD_CAN_MD5:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
+mbedtls_pem_read_buffer:"-----BEGIN EC PRIVATE KEY-----":"-----END EC PRIVATE KEY-----":"-----BEGIN EC PRIVATE KEY-----\nProc-Type\: 4,ENCRYPTED\nDEK-Info\: AES-128-CBC,31323334353637380000000000000000\n\n5wA/XVXHuMsQAAOGFQmK0g==\n-----END EC PRIVATE KEY-----":"password":MBEDTLS_ERR_PEM_PASSWORD_MISMATCH:""
+
+# Padding data (0x9) is larger than DES block size (8).
+# Generated with:
+#   echo -n -e "\x68\x65\x6c\x6c\x6f\x09\x09\x09" | openssl des-cbc -e -base64 -p -K "bbb0ddff1b944b3cc68eaaeb7ac20099" -iv "3132333435363738" -nopad
+PEM read (DES-CBC, padding data is larger than DES block length)
+depends_on:MBEDTLS_MD_CAN_MD5:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
+mbedtls_pem_read_buffer:"-----BEGIN EC PRIVATE KEY-----":"-----END EC PRIVATE KEY-----":"-----BEGIN EC PRIVATE KEY-----\nProc-Type\: 4,ENCRYPTED\nDEK-Info\: DES-CBC,3132333435363738\n\n6a+B2WineBM=\n-----END EC PRIVATE KEY-----":"password":MBEDTLS_ERR_PEM_PASSWORD_MISMATCH:""
diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data
index 35f02cb..989235d 100644
--- a/tests/suites/test_suite_pk.data
+++ b/tests/suites/test_suite_pk.data
@@ -326,13 +326,33 @@
 depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
 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 #1 (good)
+RSA verify test vector: PKCS1v1.5 (explicit), SHA1, good
 depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_PKCS1_V15
-pk_rsa_verify_test_vec:"6a8a1f225703fe39753c1017b43eec9e070a70b1":MBEDTLS_MD_SHA1:1024:"e28a13548525e5f36dccb24ecb7cc332cc689dfd64012604c9c7816d72a16c3f5fcdc0e86e7c03280b1c69b586ce0cd8aec722cc73a5d3b730310bf7dfebdc77ce5d94bbc369dc18a2f7b07bd505ab0f82224aef09fdc1e5063234255e0b3c40a52e9e8ae60898eb88a766bdd788fe9493d8fd86bcdd2884d5c06216c65469e5":"3":"5abc01f5de25b70867ff0c24e222c61f53c88daf42586fddcd56f3c4588f074be3c328056c063388688b6385a8167957c6e5355a510e005b8a851d69c96b36ec6036644078210e5d7d326f96365ee0648882921492bc7b753eb9c26cdbab37555f210df2ca6fec1b25b463d38b81c0dcea202022b04af5da58aa03d77be949b7":0
+pk_rsa_verify_test_vec:"6a8a1f225703fe39753c1017b43eec9e070a70b1":MBEDTLS_RSA_PKCS_V15:MBEDTLS_MD_SHA1:1024:"e28a13548525e5f36dccb24ecb7cc332cc689dfd64012604c9c7816d72a16c3f5fcdc0e86e7c03280b1c69b586ce0cd8aec722cc73a5d3b730310bf7dfebdc77ce5d94bbc369dc18a2f7b07bd505ab0f82224aef09fdc1e5063234255e0b3c40a52e9e8ae60898eb88a766bdd788fe9493d8fd86bcdd2884d5c06216c65469e5":"3":"5abc01f5de25b70867ff0c24e222c61f53c88daf42586fddcd56f3c4588f074be3c328056c063388688b6385a8167957c6e5355a510e005b8a851d69c96b36ec6036644078210e5d7d326f96365ee0648882921492bc7b753eb9c26cdbab37555f210df2ca6fec1b25b463d38b81c0dcea202022b04af5da58aa03d77be949b7":0
 
-RSA verify test vector #2 (bad)
+RSA verify test vector: PKCS1v1.5 (default), SHA1, good
 depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_PKCS1_V15
-pk_rsa_verify_test_vec:"9f294f0c7b32da6221a3ef83654322038e8968fa":MBEDTLS_MD_SHA1:1024:"e28a13548525e5f36dccb24ecb7cc332cc689dfd64012604c9c7816d72a16c3f5fcdc0e86e7c03280b1c69b586ce0cd8aec722cc73a5d3b730310bf7dfebdc77ce5d94bbc369dc18a2f7b07bd505ab0f82224aef09fdc1e5063234255e0b3c40a52e9e8ae60898eb88a766bdd788fe9493d8fd86bcdd2884d5c06216c65469e5":"3":"3203b7647fb7e345aa457681e5131777f1adc371f2fba8534928c4e52ef6206a856425d6269352ecbf64db2f6ad82397768cafdd8cd272e512d617ad67992226da6bc291c31404c17fd4b7e2beb20eff284a44f4d7af47fd6629e2c95809fa7f2241a04f70ac70d3271bb13258af1ed5c5988c95df7fa26603515791075feccd":MBEDTLS_ERR_RSA_VERIFY_FAILED
+pk_rsa_verify_test_vec:"6a8a1f225703fe39753c1017b43eec9e070a70b1":-1:MBEDTLS_MD_SHA1:1024:"e28a13548525e5f36dccb24ecb7cc332cc689dfd64012604c9c7816d72a16c3f5fcdc0e86e7c03280b1c69b586ce0cd8aec722cc73a5d3b730310bf7dfebdc77ce5d94bbc369dc18a2f7b07bd505ab0f82224aef09fdc1e5063234255e0b3c40a52e9e8ae60898eb88a766bdd788fe9493d8fd86bcdd2884d5c06216c65469e5":"3":"5abc01f5de25b70867ff0c24e222c61f53c88daf42586fddcd56f3c4588f074be3c328056c063388688b6385a8167957c6e5355a510e005b8a851d69c96b36ec6036644078210e5d7d326f96365ee0648882921492bc7b753eb9c26cdbab37555f210df2ca6fec1b25b463d38b81c0dcea202022b04af5da58aa03d77be949b7":0
+
+RSA verify test vector: PKCS1v1.5, SHA1, wrong signature
+depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_PKCS1_V15
+pk_rsa_verify_test_vec:"6a8a1f225703fe39753c1017b43eec9e070a70b1":MBEDTLS_RSA_PKCS_V15:MBEDTLS_MD_SHA1:1024:"e28a13548525e5f36dccb24ecb7cc332cc689dfd64012604c9c7816d72a16c3f5fcdc0e86e7c03280b1c69b586ce0cd8aec722cc73a5d3b730310bf7dfebdc77ce5d94bbc369dc18a2f7b07bd505ab0f82224aef09fdc1e5063234255e0b3c40a52e9e8ae60898eb88a766bdd788fe9493d8fd86bcdd2884d5c06216c65469e5":"3":"5abc01f5de25b70867ff0c24e222c61f53c88daf42586fddcd56f3c4588f074be3c328056c063388688b6385a8167957c6e5355a510e005b8a851d69c96b36ec6036644078210e5d7d326f96365ee0648882921492bc7b753eb9c26cdbab37555f210df2ca6fec1b25b463d38b81c0dcea202022b04af5da58aa03d77be949b8":MBEDTLS_ERR_RSA_VERIFY_FAILED
+
+RSA verify test vector: PSS, SHA1, good
+depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_PKCS1_V21
+pk_rsa_verify_test_vec:"37b66ae0445843353d47ecb0b4fd14c110e62d6a":MBEDTLS_RSA_PKCS_V21:MBEDTLS_MD_SHA1:1024:"a2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5":"010001":"8daa627d3de7595d63056c7ec659e54406f10610128baae821c8b2a0f3936d54dc3bdce46689f6b7951bb18e840542769718d5715d210d85efbb596192032c42be4c29972c856275eb6d5a45f05f51876fc6743deddd28caec9bb30ea99e02c3488269604fe497f74ccd7c7fca1671897123cbd30def5d54a2b5536ad90a747e":0
+
+RSA verify test vector: PSS, SHA1, wrong signature
+depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_PKCS1_V21
+pk_rsa_verify_test_vec:"37b66ae0445843353d47ecb0b4fd14c110e62d6a":MBEDTLS_RSA_PKCS_V21:MBEDTLS_MD_SHA1:1024:"a2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5":"010001":"8daa627d3de7595d63056c7ec659e54406f10610128baae821c8b2a0f3936d54dc3bdce46689f6b7951bb18e840542769718d5715d210d85efbb596192032c42be4c29972c856275eb6d5a45f05f51876fc6743deddd28caec9bb30ea99e02c3488269604fe497f74ccd7c7fca1671897123cbd30def5d54a2b5536ad90a747f":MBEDTLS_ERR_RSA_VERIFY_FAILED
+
+RSA verify test vector: PSS, SHA1, signature is PKCS1v1.5
+depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_PKCS1_V21
+pk_rsa_verify_test_vec:"6a8a1f225703fe39753c1017b43eec9e070a70b1":MBEDTLS_RSA_PKCS_V21:MBEDTLS_MD_SHA1:1024:"e28a13548525e5f36dccb24ecb7cc332cc689dfd64012604c9c7816d72a16c3f5fcdc0e86e7c03280b1c69b586ce0cd8aec722cc73a5d3b730310bf7dfebdc77ce5d94bbc369dc18a2f7b07bd505ab0f82224aef09fdc1e5063234255e0b3c40a52e9e8ae60898eb88a766bdd788fe9493d8fd86bcdd2884d5c06216c65469e5":"3":"5abc01f5de25b70867ff0c24e222c61f53c88daf42586fddcd56f3c4588f074be3c328056c063388688b6385a8167957c6e5355a510e005b8a851d69c96b36ec6036644078210e5d7d326f96365ee0648882921492bc7b753eb9c26cdbab37555f210df2ca6fec1b25b463d38b81c0dcea202022b04af5da58aa03d77be949b7":MBEDTLS_ERR_RSA_VERIFY_FAILED
+
+RSA verify test vector: PKCS1v1.5, SHA1, signature is PSS
+depends_on:MBEDTLS_MD_CAN_SHA1:MBEDTLS_PKCS1_V15
+pk_rsa_verify_test_vec:"37b66ae0445843353d47ecb0b4fd14c110e62d6a":MBEDTLS_RSA_PKCS_V15:MBEDTLS_MD_SHA1:1024:"a2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5":"010001":"8daa627d3de7595d63056c7ec659e54406f10610128baae821c8b2a0f3936d54dc3bdce46689f6b7951bb18e840542769718d5715d210d85efbb596192032c42be4c29972c856275eb6d5a45f05f51876fc6743deddd28caec9bb30ea99e02c3488269604fe497f74ccd7c7fca1671897123cbd30def5d54a2b5536ad90a747e":MBEDTLS_ERR_RSA_VERIFY_FAILED
 
 ECDSA verify test vector #1 (good)
 depends_on:MBEDTLS_ECP_HAVE_SECP192R1
@@ -384,51 +404,79 @@
 
 ECDSA sign-verify: SECP192R1
 depends_on:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_ECP_HAVE_SECP192R1
-pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP192R1:0:0
+pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP192R1:0:0:0:0
 
 ECDSA sign-verify: SECP256R1
 depends_on:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_ECP_HAVE_SECP256R1
-pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP256R1:0:0
+pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP256R1:0:0:0:0
 
 ECDSA sign-verify: SECP384R1
 depends_on:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_ECP_HAVE_SECP384R1
-pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP384R1:0:0
+pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP384R1:0:0:0:0
 
 ECDSA sign-verify: SECP521R1
 depends_on:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_ECP_HAVE_SECP521R1
-pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP521R1:0:0
+pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP521R1:0:0:0:0
 
 ECDSA sign-verify: BP256R1
 depends_on:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_ECP_HAVE_BP256R1
-pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_BP256R1:0:0
+pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_BP256R1:0:0:0:0
 
 ECDSA sign-verify: BP512R1
 depends_on:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_ECP_HAVE_BP512R1
-pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_BP512R1:0:0
+pk_sign_verify:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_BP512R1:0:0:0:0
 
 EC(DSA) sign-verify: SECP192R1
 depends_on:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_ECP_HAVE_SECP192R1
-pk_sign_verify:MBEDTLS_PK_ECKEY:MBEDTLS_ECP_DP_SECP192R1:0:0
+pk_sign_verify:MBEDTLS_PK_ECKEY:MBEDTLS_ECP_DP_SECP192R1:0:0:0:0
 
 EC_DH (no) sign-verify: SECP192R1
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_ECP_HAVE_SECP192R1
-pk_sign_verify:MBEDTLS_PK_ECKEY_DH:MBEDTLS_ECP_DP_SECP192R1:MBEDTLS_ERR_PK_TYPE_MISMATCH:MBEDTLS_ERR_PK_TYPE_MISMATCH
+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
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_GENPRIME:MBEDTLS_RSA_GEN_KEY_MIN_BITS >= 512
-pk_sign_verify:MBEDTLS_PK_RSA:MBEDTLS_RSA_GEN_KEY_MIN_BITS:0:0
+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
+
+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
+
+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
+
+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
 
 RSA encrypt-decrypt test
 depends_on:MBEDTLS_PKCS1_V15
 pk_rsa_encrypt_decrypt_test:"4E636AF98E40F3ADCFCCB698F4E80B9F":2048:"e79a373182bfaa722eb035f772ad2a9464bd842de59432c18bbab3a7dfeae318c9b915ee487861ab665a40bd6cda560152578e8579016c929df99fea05b4d64efca1d543850bc8164b40d71ed7f3fa4105df0fb9b9ad2a18ce182c8a4f4f975bea9aa0b9a1438a27a28e97ac8330ef37383414d1bd64607d6979ac050424fd17":"c6749cbb0db8c5a177672d4728a8b22392b2fc4d3b8361d5c0d5055a1b4e46d821f757c24eef2a51c561941b93b3ace7340074c058c9bb48e7e7414f42c41da4cccb5c2ba91deb30c586b7fb18af12a52995592ad139d3be429add6547e044becedaf31fa3b39421e24ee034fbf367d11f6b8f88ee483d163b431e1654ad3e89":"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":"3":0
 
-RSA decrypt test vector #1
+RSA decrypt test vector - PKCS1v1.5
 depends_on:MBEDTLS_PKCS1_V15
-pk_rsa_decrypt_test_vec:"a42eda41e56235e666e7faaa77100197f657288a1bf183e4820f0c37ce2c456b960278d6003e0bbcd4be4a969f8e8fd9231e1f492414f00ed09844994c86ec32db7cde3bec7f0c3dbf6ae55baeb2712fa609f5fc3207a824eb3dace31849cd6a6084318523912bccb84cf42e3c6d6d1685131d69bb545acec827d2b0dfdd5568b7dcc4f5a11d6916583fefa689d367f8c9e1d95dcd2240895a9470b0c1730f97cd6e8546860bd254801769f54be96e16362ddcbf34d56035028890199e0f48db38642cb66a4181e028a6443a404fea284ce02b4614b683367d40874e505611d23142d49f06feea831d52d347b13610b413c4efc43a6de9f0b08d2a951dc503b6":2048:"e79a373182bfaa722eb035f772ad2a9464bd842de59432c18bbab3a7dfeae318c9b915ee487861ab665a40bd6cda560152578e8579016c929df99fea05b4d64efca1d543850bc8164b40d71ed7f3fa4105df0fb9b9ad2a18ce182c8a4f4f975bea9aa0b9a1438a27a28e97ac8330ef37383414d1bd64607d6979ac050424fd17":"c6749cbb0db8c5a177672d4728a8b22392b2fc4d3b8361d5c0d5055a1b4e46d821f757c24eef2a51c561941b93b3ace7340074c058c9bb48e7e7414f42c41da4cccb5c2ba91deb30c586b7fb18af12a52995592ad139d3be429add6547e044becedaf31fa3b39421e24ee034fbf367d11f6b8f88ee483d163b431e1654ad3e89":"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":"3":"4E636AF98E40F3ADCFCCB698F4E80B9F":0
+pk_rsa_decrypt_test_vec:"28818cb14236ad18f4527e7f1f7633e96cef021bc3234475d7f61e88702b6335b42a352ed3f3267ac7c3e9ba4af17e45096c63eefd8d9a7cb42dfc52fffb2f5b8afb305b46312c2eb50634123b4437a2287ac57b7509d59a583fb741989a49f32625e9267b4641a6607b7303d35c68489db53c8d387b620d0d46a852e72ea43c":1024:MBEDTLS_RSA_PKCS_V15:MBEDTLS_MD_NONE:"eecfae81b1b9b3c908810b10a1b5600199eb9f44aef4fda493b81a9e3d84f632124ef0236e5d1e3b7e28fae7aa040a2d5b252176459d1f397541ba2a58fb6599":"c97fb1f027f453f6341233eaaad1d9353f6c42d08866b1d05a0f2035028b9d869840b41666b42e92ea0da3b43204b5cfce3352524d0416a5a441e700af461503":"bbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb":"11":"d436e99569fd32a7c8a05bbc90d32c49":0
 
-RSA decrypt test vector #2
+RSA decrypt test vector - PKCS1v1.5, corrupted encrypted data
 depends_on:MBEDTLS_PKCS1_V15
-pk_rsa_decrypt_test_vec:"a42eda41e56235e666e7faaa77100197f657288a1bf183e4820f0c37ce2c456b960278d6003e0bbcd4be4a969f8e8fd9231e1f492414f00ed09844994c86ec32db7cde3bec7f0c3dbf6ae55baeb2712fa609f5fc3207a824eb3dace31849cd6a6084318523912bccb84cf42e3c6d6d1685131d69bb545acec827d2b0dfdd5568b7dcc4f5a11d6916583fefa689d367f8c9e1d95dcd2240895a9470b0c1730f97cd6e8546860bd254801769f54be96e16362ddcbf34d56035028890199e0f48db38642cb66a4181e028a6443a404feb284ce02b4614b683367d40874e505611d23142d49f06feea831d52d347b13610b413c4efc43a6de9f0b08d2a951dc503b6":2048:"e79a373182bfaa722eb035f772ad2a9464bd842de59432c18bbab3a7dfeae318c9b915ee487861ab665a40bd6cda560152578e8579016c929df99fea05b4d64efca1d543850bc8164b40d71ed7f3fa4105df0fb9b9ad2a18ce182c8a4f4f975bea9aa0b9a1438a27a28e97ac8330ef37383414d1bd64607d6979ac050424fd17":"c6749cbb0db8c5a177672d4728a8b22392b2fc4d3b8361d5c0d5055a1b4e46d821f757c24eef2a51c561941b93b3ace7340074c058c9bb48e7e7414f42c41da4cccb5c2ba91deb30c586b7fb18af12a52995592ad139d3be429add6547e044becedaf31fa3b39421e24ee034fbf367d11f6b8f88ee483d163b431e1654ad3e89":"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":"3":"4E636AF98E40F3ADCFCCB698F4E80B9F":MBEDTLS_ERR_RSA_INVALID_PADDING
+pk_rsa_decrypt_test_vec:"28818cb14236ad18f4527e7f1f7633e96cef021bc3234475d7f61e88702b6335b42a352ed3f3267ac7c3e9ba4af17e45096c63eefd8d9a7cb42dfc52fffb2f5b8afb305b46312c2eb50634123b4437a2287ac57b7509d59a583fb741989a49f32625e9267b4641a6607b7303d35c68489db53c8d387b620d0d46a852e72ea43d":1024:MBEDTLS_RSA_PKCS_V15:MBEDTLS_MD_NONE:"eecfae81b1b9b3c908810b10a1b5600199eb9f44aef4fda493b81a9e3d84f632124ef0236e5d1e3b7e28fae7aa040a2d5b252176459d1f397541ba2a58fb6599":"c97fb1f027f453f6341233eaaad1d9353f6c42d08866b1d05a0f2035028b9d869840b41666b42e92ea0da3b43204b5cfce3352524d0416a5a441e700af461503":"bbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb":"11":"d436e99569fd32a7c8a05bbc90d32c49":MBEDTLS_ERR_RSA_INVALID_PADDING
+
+RSA decrypt test vector - PKCS1v2.1
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA1
+pk_rsa_decrypt_test_vec:"1253e04dc0a5397bb44a7ab87e9bf2a039a33d1e996fc82a94ccd30074c95df763722017069e5268da5d1c0b4f872cf653c11df82314a67968dfeae28def04bb6d84b1c31d654a1970e5783bd6eb96a024c2ca2f4a90fe9f2ef5c9c140e5bb48da9536ad8700c84fc9130adea74e558d51a74ddf85d8b50de96838d6063e0955":1024:MBEDTLS_RSA_PKCS_V21:MBEDTLS_MD_SHA1:"eecfae81b1b9b3c908810b10a1b5600199eb9f44aef4fda493b81a9e3d84f632124ef0236e5d1e3b7e28fae7aa040a2d5b252176459d1f397541ba2a58fb6599":"c97fb1f027f453f6341233eaaad1d9353f6c42d08866b1d05a0f2035028b9d869840b41666b42e92ea0da3b43204b5cfce3352524d0416a5a441e700af461503":"bbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb":"11":"d436e99569fd32a7c8a05bbc90d32c49":0
+
+RSA decrypt test vector - PKCS1v2.1, corrupted encrypted data
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA1
+pk_rsa_decrypt_test_vec:"1253e04dc0a5397bb44a7ab87e9bf2a039a33d1e996fc82a94ccd30074c95df763722017069e5268da5d1c0b4f872cf653c11df82314a67968dfeae28def04bb6d84b1c31d654a1970e5783bd6eb96a024c2ca2f4a90fe9f2ef5c9c140e5bb48da9536ad8700c84fc9130adea74e558d51a74ddf85d8b50de96838d6063e0956":1024:MBEDTLS_RSA_PKCS_V21:MBEDTLS_MD_SHA1:"eecfae81b1b9b3c908810b10a1b5600199eb9f44aef4fda493b81a9e3d84f632124ef0236e5d1e3b7e28fae7aa040a2d5b252176459d1f397541ba2a58fb6599":"c97fb1f027f453f6341233eaaad1d9353f6c42d08866b1d05a0f2035028b9d869840b41666b42e92ea0da3b43204b5cfce3352524d0416a5a441e700af461503":"bbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb":"11":"d436e99569fd32a7c8a05bbc90d32c49":MBEDTLS_ERR_RSA_INVALID_PADDING
+
+RSA decrypt test vector - PKCS1v1.5, but data is PKCS1v2.1 encrypted
+depends_on:MBEDTLS_PKCS1_V15
+pk_rsa_decrypt_test_vec:"1253e04dc0a5397bb44a7ab87e9bf2a039a33d1e996fc82a94ccd30074c95df763722017069e5268da5d1c0b4f872cf653c11df82314a67968dfeae28def04bb6d84b1c31d654a1970e5783bd6eb96a024c2ca2f4a90fe9f2ef5c9c140e5bb48da9536ad8700c84fc9130adea74e558d51a74ddf85d8b50de96838d6063e0955":1024:MBEDTLS_RSA_PKCS_V15:MBEDTLS_MD_NONE:"eecfae81b1b9b3c908810b10a1b5600199eb9f44aef4fda493b81a9e3d84f632124ef0236e5d1e3b7e28fae7aa040a2d5b252176459d1f397541ba2a58fb6599":"c97fb1f027f453f6341233eaaad1d9353f6c42d08866b1d05a0f2035028b9d869840b41666b42e92ea0da3b43204b5cfce3352524d0416a5a441e700af461503":"bbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb":"11":"d436e99569fd32a7c8a05bbc90d32c49":MBEDTLS_ERR_RSA_INVALID_PADDING
+
+RSA decrypt test vector - PKCS1v2.1, but data is PKCS1v1.5 encrypted
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA1
+pk_rsa_decrypt_test_vec:"28818cb14236ad18f4527e7f1f7633e96cef021bc3234475d7f61e88702b6335b42a352ed3f3267ac7c3e9ba4af17e45096c63eefd8d9a7cb42dfc52fffb2f5b8afb305b46312c2eb50634123b4437a2287ac57b7509d59a583fb741989a49f32625e9267b4641a6607b7303d35c68489db53c8d387b620d0d46a852e72ea43c":1024:MBEDTLS_RSA_PKCS_V21:MBEDTLS_MD_SHA1:"eecfae81b1b9b3c908810b10a1b5600199eb9f44aef4fda493b81a9e3d84f632124ef0236e5d1e3b7e28fae7aa040a2d5b252176459d1f397541ba2a58fb6599":"c97fb1f027f453f6341233eaaad1d9353f6c42d08866b1d05a0f2035028b9d869840b41666b42e92ea0da3b43204b5cfce3352524d0416a5a441e700af461503":"bbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb":"11":"d436e99569fd32a7c8a05bbc90d32c49":MBEDTLS_ERR_RSA_INVALID_PADDING
 
 RSA Opaque decrypt test vector #1
 depends_on:MBEDTLS_PKCS1_V15
@@ -696,311 +744,311 @@
 pk_psa_wrap_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA512
 
 PSA attributes for pk: NONE (bad)
-pk_get_psa_attributes_fail:MBEDTLS_PK_NONE:0:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_BAD_INPUT_DATA
+pk_get_psa_attributes_fail:MBEDTLS_PK_NONE:FROM_PUBLIC:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_BAD_INPUT_DATA
 
 # There is a (negative) test for pk_type=MBEDTLS_PK_RSA_ALT in pk_rsa_alt().
 
 # 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
-pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:1:0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+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
-pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:1:PSA_KEY_USAGE_EXPORT:MBEDTLS_ERR_PK_TYPE_MISMATCH
+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
-pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:1:PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:MBEDTLS_ERR_PK_TYPE_MISMATCH
+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
-pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:1:PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
+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
-pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
+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
-pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
+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
-pk_get_psa_attributes:MBEDTLS_PK_RSA:1:PSA_KEY_USAGE_DECRYPT:1:PSA_ALG_RSA_PKCS1V15_CRYPT
+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
-pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA256:1:PSA_KEY_USAGE_DECRYPT:1:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256)
+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
-pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA512:1:PSA_KEY_USAGE_DECRYPT:1:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_512)
+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
-pk_get_psa_attributes:MBEDTLS_PK_RSA:1:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_PKCS1V15_CRYPT
+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
-pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA256:1:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256)
+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
-pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA512:1:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_512)
+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
-pk_get_psa_attributes:MBEDTLS_PK_RSA:0:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_PKCS1V15_CRYPT
+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
-pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA256:0:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256)
+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
-pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA512:0:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_512)
+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
-pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:0:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
+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
-pk_get_psa_attributes:MBEDTLS_PK_RSA:1:PSA_KEY_USAGE_SIGN_MESSAGE:1:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
+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
-pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:1:PSA_KEY_USAGE_SIGN_MESSAGE:1:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
+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
-pk_get_psa_attributes:MBEDTLS_PK_RSA:1:PSA_KEY_USAGE_SIGN_HASH:1:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
+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
-pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:1:PSA_KEY_USAGE_SIGN_HASH:1:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
+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
-pk_get_psa_attributes:MBEDTLS_PK_RSA:1:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
+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
-pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:1:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
+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
-pk_get_psa_attributes:MBEDTLS_PK_RSA:1:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
+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
-pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:1:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
+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
-pk_get_psa_attributes:MBEDTLS_PK_RSA:0:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
+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
-pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:0:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
+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
-pk_get_psa_attributes:MBEDTLS_PK_RSA:0:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
+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
-pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:0:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
+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
-pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:0:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
+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
-pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:0:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
+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
-pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:1:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH
+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
-pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:0:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH
+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)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY:1:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY:FROM_PAIR:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY_DH pair DECRYPT (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:1:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:FROM_PAIR:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECDSA pair DECRYPT (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PK_CAN_ECDSA_SOME
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECDSA:1:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECDSA:FROM_PAIR:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY public DECRYPT (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY:0:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY:FROM_PUBLIC:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY_DH public DECRYPT (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:0:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:FROM_PUBLIC:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECDSA public DECRYPT (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PK_CAN_ECDSA_SOME
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECDSA:0:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECDSA:FROM_PUBLIC:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY pair ENCRYPT (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY:1:PSA_KEY_USAGE_ENCRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY:FROM_PAIR:PSA_KEY_USAGE_ENCRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY_DH pair ENCRYPT (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:1:PSA_KEY_USAGE_ENCRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:FROM_PAIR:PSA_KEY_USAGE_ENCRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECDSA pair ENCRYPT (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PK_CAN_ECDSA_SOME
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECDSA:1:PSA_KEY_USAGE_ENCRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECDSA:FROM_PAIR:PSA_KEY_USAGE_ENCRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY public ENCRYPT (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY:0:PSA_KEY_USAGE_ENCRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY:FROM_PUBLIC:PSA_KEY_USAGE_ENCRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY_DH public ENCRYPT (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:0:PSA_KEY_USAGE_ENCRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:FROM_PUBLIC:PSA_KEY_USAGE_ENCRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECDSA public ENCRYPT (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PK_CAN_ECDSA_SOME
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECDSA:0:PSA_KEY_USAGE_ENCRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECDSA:FROM_PUBLIC:PSA_KEY_USAGE_ENCRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY pair DERIVE
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes:MBEDTLS_PK_ECKEY:1:PSA_KEY_USAGE_DERIVE:1:PSA_ALG_ECDH
+pk_get_psa_attributes:MBEDTLS_PK_ECKEY:FROM_PAIR:PSA_KEY_USAGE_DERIVE:1:PSA_ALG_ECDH
 
 PSA attributes for pk: ECKEY_DH pair DERIVE
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes:MBEDTLS_PK_ECKEY_DH:1:PSA_KEY_USAGE_DERIVE:1:PSA_ALG_ECDH
+pk_get_psa_attributes:MBEDTLS_PK_ECKEY_DH:FROM_PAIR:PSA_KEY_USAGE_DERIVE:1:PSA_ALG_ECDH
 
 PSA attributes for pk: ECDSA pair DERIVE (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PK_CAN_ECDSA_SOME
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECDSA:1:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECDSA:FROM_PAIR:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY public DERIVE (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY:0:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY:FROM_PUBLIC:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY_DH public DERIVE (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:0:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:FROM_PUBLIC:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECDSA public DERIVE (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PK_CAN_ECDSA_SOME
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECDSA:0:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECDSA:FROM_PUBLIC:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY pair SIGN_MESSAGE
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes:MBEDTLS_PK_ECKEY:1:PSA_KEY_USAGE_SIGN_MESSAGE:1:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
+pk_get_psa_attributes:MBEDTLS_PK_ECKEY:FROM_PAIR:PSA_KEY_USAGE_SIGN_MESSAGE:1:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: ECDSA pair SIGN_MESSAGE
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PK_CAN_ECDSA_SOME
-pk_get_psa_attributes:MBEDTLS_PK_ECDSA:1:PSA_KEY_USAGE_SIGN_MESSAGE:1:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
+pk_get_psa_attributes:MBEDTLS_PK_ECDSA:FROM_PAIR:PSA_KEY_USAGE_SIGN_MESSAGE:1:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: ECKEY pair SIGN_HASH
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes:MBEDTLS_PK_ECKEY:1:PSA_KEY_USAGE_SIGN_HASH:1:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
+pk_get_psa_attributes:MBEDTLS_PK_ECKEY:FROM_PAIR:PSA_KEY_USAGE_SIGN_HASH:1:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: ECDSA pair SIGN_HASH
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PK_CAN_ECDSA_SOME
-pk_get_psa_attributes:MBEDTLS_PK_ECDSA:1:PSA_KEY_USAGE_SIGN_HASH:1:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
+pk_get_psa_attributes:MBEDTLS_PK_ECDSA:FROM_PAIR:PSA_KEY_USAGE_SIGN_HASH:1:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: ECKEY pair->public VERIFY_MESSAGE
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes:MBEDTLS_PK_ECKEY:1:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
+pk_get_psa_attributes:MBEDTLS_PK_ECKEY:FROM_PAIR:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: ECDSA pair->public VERIFY_MESSAGE
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PK_CAN_ECDSA_SOME
-pk_get_psa_attributes:MBEDTLS_PK_ECDSA:1:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
+pk_get_psa_attributes:MBEDTLS_PK_ECDSA:FROM_PAIR:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: ECKEY pair->public VERIFY_HASH
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes:MBEDTLS_PK_ECKEY:1:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
+pk_get_psa_attributes:MBEDTLS_PK_ECKEY:FROM_PAIR:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: ECDSA pair->public VERIFY_HASH
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PK_CAN_ECDSA_SOME
-pk_get_psa_attributes:MBEDTLS_PK_ECDSA:1:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
+pk_get_psa_attributes:MBEDTLS_PK_ECDSA:FROM_PAIR:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: ECKEY public VERIFY_MESSAGE
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes:MBEDTLS_PK_ECKEY:0:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
+pk_get_psa_attributes:MBEDTLS_PK_ECKEY:FROM_PUBLIC:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: ECDSA public VERIFY_MESSAGE
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PK_CAN_ECDSA_SOME
-pk_get_psa_attributes:MBEDTLS_PK_ECDSA:0:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
+pk_get_psa_attributes:MBEDTLS_PK_ECDSA:FROM_PUBLIC:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: ECKEY public VERIFY_HASH
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes:MBEDTLS_PK_ECKEY:0:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
+pk_get_psa_attributes:MBEDTLS_PK_ECKEY:FROM_PUBLIC:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: ECDSA public VERIFY_HASH
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PK_CAN_ECDSA_SOME
-pk_get_psa_attributes:MBEDTLS_PK_ECDSA:0:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
+pk_get_psa_attributes:MBEDTLS_PK_ECDSA:FROM_PUBLIC:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: ECKEY public SIGN_MESSAGE (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY:0:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY:FROM_PUBLIC:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECDSA public SIGN_MESSAGE (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PK_CAN_ECDSA_SOME
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECDSA:0:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECDSA:FROM_PUBLIC:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY public SIGN_HASH (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY:0:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY:FROM_PUBLIC:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECDSA public SIGN_HASH (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PK_CAN_ECDSA_SOME
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECDSA:0:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECDSA:FROM_PUBLIC:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY_DH pair SIGN_MESSAGE (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:1:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:FROM_PAIR:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY_DH pair SIGN_HASH (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:1:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:FROM_PAIR:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY_DH pair VERIFY_MESSAGE (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:1:PSA_KEY_USAGE_VERIFY_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:FROM_PAIR:PSA_KEY_USAGE_VERIFY_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY_DH pair VERIFY_HASH (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:1:PSA_KEY_USAGE_VERIFY_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:FROM_PAIR:PSA_KEY_USAGE_VERIFY_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY_DH public SIGN_MESSAGE (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:0:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:FROM_PUBLIC:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY_DH public SIGN_HASH (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:0:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:FROM_PUBLIC:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY_DH public VERIFY_MESSAGE (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:0:PSA_KEY_USAGE_VERIFY_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
+pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:FROM_PUBLIC:PSA_KEY_USAGE_VERIFY_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY_DH public VERIFY_HASH (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
-pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:0:PSA_KEY_USAGE_VERIFY_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
+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
@@ -1018,8 +1066,23 @@
 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
 
+# 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
+
+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
+
+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
+
+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
 
 PSA attributes for pk: opaque RSA pair, SIGN_MESSAGE & SIGN_HASH (bad policy)
@@ -1123,3 +1186,268 @@
 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
 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
+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
+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
+
+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
+
+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
+
+PSA import into PSA: ECKEY pair to RSA (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
+pk_import_into_psa_fail:MBEDTLS_PK_ECKEY:FROM_PAIR:PSA_KEY_TYPE_RSA_KEY_PAIR:0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECKEY_DH pair to RSA (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
+pk_import_into_psa_fail:MBEDTLS_PK_ECKEY_DH:FROM_PAIR:PSA_KEY_TYPE_RSA_KEY_PAIR:0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECDSA pair to RSA (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PK_CAN_ECDSA_SOME
+pk_import_into_psa_fail:MBEDTLS_PK_ECDSA:FROM_PAIR:PSA_KEY_TYPE_RSA_KEY_PAIR:0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECKEY pair to different curve (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES
+pk_import_into_psa_fail:MBEDTLS_PK_ECKEY:FROM_PAIR:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ANOTHER_FAMILY):0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECKEY_DH pair to different curve (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES
+pk_import_into_psa_fail:MBEDTLS_PK_ECKEY_DH:FROM_PAIR:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ANOTHER_FAMILY):0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECDSA pair to different curve (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES:MBEDTLS_PK_CAN_ECDSA_SOME
+pk_import_into_psa_fail:MBEDTLS_PK_ECDSA:FROM_PAIR:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ANOTHER_FAMILY):0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECKEY pair to public, different curve (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES
+pk_import_into_psa_fail:MBEDTLS_PK_ECKEY:FROM_PAIR:PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ANOTHER_FAMILY):0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECKEY_DH pair to public, different curve (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES
+pk_import_into_psa_fail:MBEDTLS_PK_ECKEY_DH:FROM_PAIR:PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ANOTHER_FAMILY):0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECDSA pair to public, different curve (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES:MBEDTLS_PK_CAN_ECDSA_SOME
+pk_import_into_psa_fail:MBEDTLS_PK_ECDSA:FROM_PAIR:PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ANOTHER_FAMILY):0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECKEY public to different curve (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES
+pk_import_into_psa_fail:MBEDTLS_PK_ECKEY:FROM_PUBLIC:PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ANOTHER_FAMILY):0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECKEY_DH public to different curve (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES
+pk_import_into_psa_fail:MBEDTLS_PK_ECKEY_DH:FROM_PUBLIC:PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ANOTHER_FAMILY):0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECDSA public to different curve (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES:MBEDTLS_PK_CAN_ECDSA_SOME
+pk_import_into_psa_fail:MBEDTLS_PK_ECDSA:FROM_PUBLIC:PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ANOTHER_FAMILY):0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECKEY pair to different bits (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_BITS
+pk_import_into_psa_fail:MBEDTLS_PK_ECKEY:FROM_PAIR:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS):MBEDTLS_TEST_PSA_ECC_ANOTHER_CURVE_BITS:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECKEY_DH pair to different bits (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_BITS
+pk_import_into_psa_fail:MBEDTLS_PK_ECKEY_DH:FROM_PAIR:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS):MBEDTLS_TEST_PSA_ECC_ANOTHER_CURVE_BITS:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECDSA pair to different bits (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_BITS:MBEDTLS_PK_CAN_ECDSA_SOME
+pk_import_into_psa_fail:MBEDTLS_PK_ECDSA:FROM_PAIR:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS):MBEDTLS_TEST_PSA_ECC_ANOTHER_CURVE_BITS:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECKEY public to different bits (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_BITS
+pk_import_into_psa_fail:MBEDTLS_PK_ECKEY:FROM_PUBLIC:PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS):MBEDTLS_TEST_PSA_ECC_ANOTHER_CURVE_BITS:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECKEY_DH public to different bits (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_BITS
+pk_import_into_psa_fail:MBEDTLS_PK_ECKEY_DH:FROM_PUBLIC:PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS):MBEDTLS_TEST_PSA_ECC_ANOTHER_CURVE_BITS:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECDSA public to different bits (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_BITS:MBEDTLS_PK_CAN_ECDSA_SOME
+pk_import_into_psa_fail:MBEDTLS_PK_ECDSA:FROM_PUBLIC:PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS):MBEDTLS_TEST_PSA_ECC_ANOTHER_CURVE_BITS:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECKEY private to public, different bits (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_BITS
+pk_import_into_psa_fail:MBEDTLS_PK_ECKEY:FROM_PAIR:PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS):MBEDTLS_TEST_PSA_ECC_ANOTHER_CURVE_BITS:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECKEY_DH private to public, different bits (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_BITS
+pk_import_into_psa_fail:MBEDTLS_PK_ECKEY_DH:FROM_PAIR:PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS):MBEDTLS_TEST_PSA_ECC_ANOTHER_CURVE_BITS:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECDSA private to public, different bits (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_BITS:MBEDTLS_PK_CAN_ECDSA_SOME
+pk_import_into_psa_fail:MBEDTLS_PK_ECDSA:FROM_PAIR:PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS):MBEDTLS_TEST_PSA_ECC_ANOTHER_CURVE_BITS:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECKEY public to pair (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
+pk_import_into_psa_fail:MBEDTLS_PK_ECKEY:FROM_PUBLIC:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECKEY_DH public to pair (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
+pk_import_into_psa_fail:MBEDTLS_PK_ECKEY_DH:FROM_PUBLIC:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+PSA import into PSA: ECDSA public to pair (bad)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PK_CAN_ECDSA_SOME
+pk_import_into_psa_fail:MBEDTLS_PK_ECDSA:FROM_PUBLIC:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+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
+
+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
+
+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
+
+# 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
+
+# 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
+
+# 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
+
+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
+
+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
+
+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
+
+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
+
+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
+
+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
+
+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
+
+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
+
+# 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
+
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index ff843cb..180cf76 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -19,12 +19,21 @@
 #include "psa/crypto.h"
 #include "mbedtls/psa_util.h"
 
+#include <test/psa_exercise_key.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) ||                                         \
+    defined(MBEDTLS_USE_PSA_CRYPTO)
+#define PK_CAN_SIGN_SOME
+#endif
+
 /* MBEDTLS_TEST_PK_PSA_SIGN is enabled when:
  * - The build has PK_[PARSE/WRITE]_C for RSA or ECDSA signature.
  * - The build has built-in ECC and ECDSA signature.
@@ -36,28 +45,126 @@
 #define MBEDTLS_TEST_PK_PSA_SIGN
 #endif
 
-/* MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE is enabled when PSA supports
- * at least one elliptic curve. This is distinct from
- * PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY because that symbol can be enabled even
- * when there are no curves. This happens in particular in a configuration
- * with MBEDTLS_PSA_CRYPTO_CONFIG disabled and where the only legacy curve
- * is secp224k1, which is not supported in PSA. */
 #if defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
-#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) || \
-    defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) || \
-    defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) || \
-    defined(PSA_WANT_ECC_MONTGOMERY_255) || \
-    defined(PSA_WANT_ECC_MONTGOMERY_448) || \
-    defined(PSA_WANT_ECC_SECP_K1_192) || \
-    defined(PSA_WANT_ECC_SECP_K1_224) || \
-    defined(PSA_WANT_ECC_SECP_K1_256) || \
-    defined(PSA_WANT_ECC_SECP_R1_192) || \
-    defined(PSA_WANT_ECC_SECP_R1_224) || \
-    defined(PSA_WANT_ECC_SECP_R1_256) || \
-    defined(PSA_WANT_ECC_SECP_R1_384) || \
-    defined(PSA_WANT_ECC_SECP_R1_521)
+/* Pick an elliptic curve that's supported by PSA. Note that the curve is
+ * not guaranteed to be supported by the ECP module.
+ *
+ * This should always find a curve if ECC is enabled in the build, except in
+ * one edge case: in a build with MBEDTLS_PSA_CRYPTO_CONFIG disabled and
+ * where the only legacy curve is secp224k1, which is not supported in PSA,
+ * PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY ends up enabled but PSA does not
+ * support any curve.
+ */
+
+/* First try all the curves that can do both ECDSA and ECDH, then try
+ * the ECDH-only curves. (There are no curves that can do ECDSA but not ECDH.)
+ * This way, if ECDSA is enabled then the curve that's selected here will
+ * be ECDSA-capable, and likewise for ECDH. */
+#if defined(PSA_WANT_ECC_SECP_R1_192)
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY PSA_ECC_FAMILY_SECP_R1
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 192
+#define MBEDTLS_TEST_ECP_DP_ONE_CURVE MBEDTLS_ECP_DP_SECP192R1
+#elif defined(PSA_WANT_ECC_SECP_R1_224)
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY PSA_ECC_FAMILY_SECP_R1
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 224
+#define MBEDTLS_TEST_ECP_DP_ONE_CURVE MBEDTLS_ECP_DP_SECP224R1
+#elif defined(PSA_WANT_ECC_SECP_R1_256)
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY PSA_ECC_FAMILY_SECP_R1
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 256
+#define MBEDTLS_TEST_ECP_DP_ONE_CURVE MBEDTLS_ECP_DP_SECP256R1
+#elif defined(PSA_WANT_ECC_SECP_R1_384)
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY PSA_ECC_FAMILY_SECP_R1
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 384
+#define MBEDTLS_TEST_ECP_DP_ONE_CURVE MBEDTLS_ECP_DP_SECP384R1
+#elif defined(PSA_WANT_ECC_SECP_R1_521)
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY PSA_ECC_FAMILY_SECP_R1
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 521
+#define MBEDTLS_TEST_ECP_DP_ONE_CURVE MBEDTLS_ECP_DP_SECP521R1
+#elif defined(PSA_WANT_ECC_SECP_K1_192)
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY PSA_ECC_FAMILY_SECP_K1
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 192
+#define MBEDTLS_TEST_ECP_DP_ONE_CURVE MBEDTLS_ECP_DP_SECP192K1
+#elif defined(PSA_WANT_ECC_SECP_K1_224)
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY PSA_ECC_FAMILY_SECP_K1
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 224
+#define MBEDTLS_TEST_ECP_DP_ONE_CURVE MBEDTLS_ECP_DP_SECP224K1
+#elif defined(PSA_WANT_ECC_SECP_K1_256)
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY PSA_ECC_FAMILY_SECP_K1
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 256
+#define MBEDTLS_TEST_ECP_DP_ONE_CURVE MBEDTLS_ECP_DP_SECP256K1
+#elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY PSA_ECC_FAMILY_BRAINPOOL_P_R1
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 256
+#define MBEDTLS_TEST_ECP_DP_ONE_CURVE MBEDTLS_ECP_DP_BP256R1
+#elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY PSA_ECC_FAMILY_BRAINPOOL_P_R1
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 384
+#define MBEDTLS_TEST_ECP_DP_ONE_CURVE MBEDTLS_ECP_DP_BP384R1
+#elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY PSA_ECC_FAMILY_BRAINPOOL_P_R1
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 512
+#define MBEDTLS_TEST_ECP_DP_ONE_CURVE MBEDTLS_ECP_DP_BP512R1
+#elif defined(PSA_WANT_ECC_MONTGOMERY_255)
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY PSA_ECC_FAMILY_MONTGOMERY
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 255
+#define MBEDTLS_TEST_ECP_DP_ONE_CURVE MBEDTLS_ECP_DP_CURVE25519
+#elif defined(PSA_WANT_ECC_MONTGOMERY_448)
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY PSA_ECC_FAMILY_MONTGOMERY
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 448
+#define MBEDTLS_TEST_ECP_DP_ONE_CURVE MBEDTLS_ECP_DP_CURVE448
+#endif /* curve selection */
+
+#if defined(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY)
 #define MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
 #endif
+
+/* Pick a second curve, for tests that need two supported curves of the
+ * same size. For simplicity, we only handle a subset of configurations,
+ * and both curves will support both ECDH and ECDSA. */
+#if defined(PSA_WANT_ECC_SECP_R1_192) && defined(PSA_WANT_ECC_SECP_K1_192)
+/* Identical redefinition of the ONE macros, to confirm that they have
+ * the values we expect here. */
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY PSA_ECC_FAMILY_SECP_R1
+#define MBEDTLS_TEST_PSA_ECC_ANOTHER_FAMILY PSA_ECC_FAMILY_SECP_K1
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 192
+#define MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES
+#elif defined(PSA_WANT_ECC_SECP_R1_256) && defined(PSA_WANT_ECC_SECP_K1_256)
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY PSA_ECC_FAMILY_SECP_R1
+#define MBEDTLS_TEST_PSA_ECC_ANOTHER_FAMILY PSA_ECC_FAMILY_SECP_K1
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 256
+#define MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES
+#endif
+
+/* Pick a second bit-size, for tests that need two supported curves of the
+ * same family. For simplicity, we only handle a subset of configurations,
+ * and both curves will support both ECDH and ECDSA. */
+#if defined(PSA_WANT_ECC_SECP_R1_192) && defined(PSA_WANT_ECC_SECP_R1_256)
+/* Identical redefinition of the ONE macros, to confirm that they have
+ * the values we expect here. */
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY PSA_ECC_FAMILY_SECP_R1
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 192
+#define MBEDTLS_TEST_PSA_ECC_ANOTHER_CURVE_BITS 256
+#define MBEDTLS_TEST_PSA_ECC_HAVE_TWO_BITS
+#elif defined(PSA_WANT_ECC_SECP_R1_256) && defined(PSA_WANT_ECC_SECP_R1_384)
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY PSA_ECC_FAMILY_SECP_R1
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 256
+#define MBEDTLS_TEST_PSA_ECC_ANOTHER_CURVE_BITS 384
+#define MBEDTLS_TEST_PSA_ECC_HAVE_TWO_BITS
+#endif
+
+#endif /* defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) */
+
+/* Always define the macros so that we can use them in test data. */
+#if !defined(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY)
+#define MBEDTLS_TEST_PSA_ECC_ONE_FAMILY 0
+#define MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS 0
+#define MBEDTLS_TEST_ECP_DP_ONE_CURVE 0
+#endif
+#if !defined(MBEDTLS_TEST_PSA_ECC_ANOTHER_FAMILY)
+#define MBEDTLS_TEST_PSA_ECC_ANOTHER_FAMILY 0
+#endif
+#if !defined(MBEDTLS_TEST_PSA_ECC_ANOTHER_CURVE_BITS)
+#define MBEDTLS_TEST_PSA_ECC_ANOTHER_CURVE_BITS 0
 #endif
 
 #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
@@ -75,14 +182,31 @@
 
     psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
     psa_set_key_bits(&key_attr, curve_bits);
-    psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT |
-                            PSA_KEY_USAGE_SIGN_HASH |
-                            PSA_KEY_USAGE_SIGN_MESSAGE);
+    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)
-    psa_set_key_algorithm(&key_attr, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH));
+        sign_alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH);
 #else
-    psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA(PSA_ALG_ANY_HASH));
+        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);
+        }
+    } 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) {
@@ -211,42 +335,11 @@
 }
 #endif /* MBEDTLS_RSA_C */
 
-#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_PK_HAVE_ECC_KEYS)
-static mbedtls_ecp_group_id ecc_pick_grp_id(void)
-{
-#if defined(MBEDTLS_ECP_LIGHT)
-    return mbedtls_ecp_grp_id_list()[0];
-#elif defined(PSA_WANT_ECC_SECP_R1_192)
-    return MBEDTLS_ECP_DP_SECP192R1;
-#elif defined(PSA_WANT_ECC_SECP_R1_224)
-    return MBEDTLS_ECP_DP_SECP224R1;
-#elif defined(PSA_WANT_ECC_SECP_R1_256)
-    return MBEDTLS_ECP_DP_SECP256R1;
-#elif defined(PSA_WANT_ECC_SECP_R1_384)
-    return MBEDTLS_ECP_DP_SECP384R1;
-#elif defined(PSA_WANT_ECC_SECP_R1_521)
-    return MBEDTLS_ECP_DP_SECP521R1;
-#elif defined(PSA_WANT_ECC_SECP_K1_192)
-    return MBEDTLS_ECP_DP_SECP192K1;
-#elif defined(PSA_WANT_ECC_SECP_K1_224)
-    return MBEDTLS_ECP_DP_SECP224K1;
-#elif defined(PSA_WANT_ECC_SECP_K1_256)
-    return MBEDTLS_ECP_DP_SECP256K1;
-#elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
-    return MBEDTLS_ECP_DP_BP256R1;
-#elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
-    return MBEDTLS_ECP_DP_BP384R1;
-#elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
-    return MBEDTLS_ECP_DP_BP512R1;
-#elif defined(PSA_WANT_ECC_MONTGOMERY_255)
-    return MBEDTLS_ECP_DP_CURVE25519;
-#elif defined(PSA_WANT_ECC_MONTGOMERY_448)
-    return MBEDTLS_ECP_DP_CURVE448;
-#else
-    return 0;
-#endif
-}
-#endif /* defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_PK_HAVE_ECC_KEYS) */
+typedef enum {
+    /* The values are compatible with thinking of "from pair" as a boolean. */
+    FROM_PUBLIC = 0,
+    FROM_PAIR = 1
+} from_pair_t;
 
 #if defined(MBEDTLS_PSA_CRYPTO_C)
 static int pk_setup_for_type(mbedtls_pk_type_t pk_type, int want_pair,
@@ -291,7 +384,7 @@
         case MBEDTLS_PK_ECKEY_DH:
         case MBEDTLS_PK_ECDSA:
         {
-            mbedtls_ecp_group_id grp_id = ecc_pick_grp_id();
+            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);
@@ -800,9 +893,9 @@
 /* END_CASE */
 
 /* BEGIN_CASE depends_on:MBEDTLS_RSA_C */
-void pk_rsa_verify_test_vec(data_t *message_str, int digest, int mod,
-                            char *input_N, char *input_E,
-                            data_t *result_str, int result)
+void pk_rsa_verify_test_vec(data_t *message_str, int padding, int digest,
+                            int mod, char *input_N, char *input_E,
+                            data_t *result_str, int expected_result)
 {
     mbedtls_rsa_context *rsa;
     mbedtls_pk_context pk;
@@ -817,28 +910,54 @@
 #endif
 
     mbedtls_pk_init(&pk);
-    USE_PSA_INIT();
+    MD_OR_USE_PSA_INIT();
 
     TEST_ASSERT(mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == 0);
     rsa = mbedtls_pk_rsa(pk);
 
     rsa->len = (mod + 7) / 8;
+    if (padding >= 0) {
+        TEST_EQUAL(mbedtls_rsa_set_padding(rsa, padding, MBEDTLS_MD_NONE), 0);
+    }
+
     TEST_ASSERT(mbedtls_test_read_mpi(&rsa->N, input_N) == 0);
     TEST_ASSERT(mbedtls_test_read_mpi(&rsa->E, input_E) == 0);
 
-    TEST_ASSERT(mbedtls_pk_verify(&pk, digest, message_str->x, 0,
-                                  result_str->x, mbedtls_pk_get_len(&pk)) == result);
+    int actual_result;
+    actual_result = mbedtls_pk_verify(&pk, digest, message_str->x, 0,
+                                      result_str->x, mbedtls_pk_get_len(&pk));
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (actual_result == MBEDTLS_ERR_RSA_INVALID_PADDING &&
+        expected_result == MBEDTLS_ERR_RSA_VERIFY_FAILED) {
+        /* Tolerate INVALID_PADDING error for an invalid signature with
+         * the legacy API (but not with PSA). */
+    } else
+#endif
+    {
+        TEST_EQUAL(actual_result, expected_result);
+    }
 
-    TEST_ASSERT(mbedtls_pk_verify_restartable(&pk, digest, message_str->x, 0,
-                                              result_str->x, mbedtls_pk_get_len(
-                                                  &pk), rs_ctx) == result);
+    actual_result = mbedtls_pk_verify_restartable(&pk, digest, message_str->x, 0,
+                                                  result_str->x,
+                                                  mbedtls_pk_get_len(&pk),
+                                                  rs_ctx);
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (actual_result == MBEDTLS_ERR_RSA_INVALID_PADDING &&
+        expected_result == MBEDTLS_ERR_RSA_VERIFY_FAILED) {
+        /* Tolerate INVALID_PADDING error for an invalid signature with
+         * the legacy API (but not with PSA). */
+    } else
+#endif
+    {
+        TEST_EQUAL(actual_result, expected_result);
+    }
 
 exit:
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
     mbedtls_pk_restart_free(rs_ctx);
 #endif
     mbedtls_pk_free(&pk);
-    USE_PSA_DONE();
+    MD_OR_USE_PSA_DONE();
 }
 /* END_CASE */
 
@@ -1026,8 +1145,9 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_MD_CAN_SHA256 */
-void pk_sign_verify(int type, int curve_or_keybits, int sign_ret, int verify_ret)
+/* BEGIN_CASE depends_on:MBEDTLS_MD_CAN_SHA256:PK_CAN_SIGN_SOME */
+void pk_sign_verify(int type, int curve_or_keybits, int rsa_padding, int rsa_md_alg,
+                    int sign_ret, int verify_ret)
 {
     mbedtls_pk_context pk;
     size_t sig_len;
@@ -1055,6 +1175,15 @@
     TEST_ASSERT(mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(type)) == 0);
     TEST_ASSERT(pk_genkey(&pk, curve_or_keybits) == 0);
 
+#if defined(MBEDTLS_RSA_C)
+    if (type == MBEDTLS_PK_RSA) {
+        TEST_ASSERT(mbedtls_rsa_set_padding(mbedtls_pk_rsa(pk), rsa_padding, rsa_md_alg) == 0);
+    }
+#else
+    (void) rsa_padding;
+    (void) rsa_md_alg;
+#endif /* MBEDTLS_RSA_C */
+
     TEST_ASSERT(mbedtls_pk_sign_restartable(&pk, MBEDTLS_MD_SHA256,
                                             hash, hash_len,
                                             sig, sizeof(sig), &sig_len,
@@ -1194,7 +1323,7 @@
 /* END_CASE */
 
 /* BEGIN_CASE depends_on:MBEDTLS_RSA_C */
-void pk_rsa_decrypt_test_vec(data_t *cipher, int mod,
+void pk_rsa_decrypt_test_vec(data_t *cipher, int mod, int padding, int md_alg,
                              char *input_P, char *input_Q,
                              char *input_N, char *input_E,
                              data_t *clear, int ret)
@@ -1209,7 +1338,7 @@
     mbedtls_pk_init(&pk);
     mbedtls_mpi_init(&N); mbedtls_mpi_init(&P);
     mbedtls_mpi_init(&Q); mbedtls_mpi_init(&E);
-    USE_PSA_INIT();
+    MD_OR_USE_PSA_INIT();
 
     memset(&rnd_info,  0, sizeof(mbedtls_test_rnd_pseudo_info));
 
@@ -1231,6 +1360,11 @@
     TEST_EQUAL(mbedtls_pk_get_bitlen(&pk), mod);
     TEST_EQUAL(mbedtls_pk_get_len(&pk), (mod + 7) / 8);
 
+    /* set padding mode */
+    if (padding >= 0) {
+        TEST_EQUAL(mbedtls_rsa_set_padding(rsa, padding, md_alg), 0);
+    }
+
     /* decryption test */
     memset(output, 0, sizeof(output));
     olen = 0;
@@ -1246,7 +1380,7 @@
     mbedtls_mpi_free(&N); mbedtls_mpi_free(&P);
     mbedtls_mpi_free(&Q); mbedtls_mpi_free(&E);
     mbedtls_pk_free(&pk);
-    USE_PSA_DONE();
+    MD_OR_USE_PSA_DONE();
 }
 /* END_CASE */
 
@@ -1447,6 +1581,9 @@
                                              PSA_KEY_USAGE_ENCRYPT,
                                              &attributes),
                MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE);
+    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    TEST_EQUAL(mbedtls_pk_import_into_psa(&alt, &attributes, &key_id),
+               MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE);
 #endif /* MBEDTLS_PSA_CRYPTO_C */
 
     /* Test signature */
@@ -1765,6 +1902,7 @@
     mbedtls_pk_init(&pk);
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_usage_t usage = usage_arg;
+    mbedtls_svc_key_id_t new_key_id = MBEDTLS_SVC_KEY_ID_INIT;
 
     PSA_INIT();
 
@@ -1805,9 +1943,15 @@
     TEST_EQUAL(psa_get_key_algorithm(&attributes), expected_alg);
     TEST_EQUAL(psa_get_key_enrollment_algorithm(&attributes), PSA_ALG_NONE);
 
+    TEST_EQUAL(mbedtls_pk_import_into_psa(&pk, &attributes, &new_key_id), 0);
+    if (!mbedtls_test_key_consistency_psa_pk(new_key_id, &pk)) {
+        goto exit;
+    }
+
 exit:
     mbedtls_pk_free(&pk);
     psa_reset_key_attributes(&attributes);
+    psa_destroy_key(new_key_id);
     PSA_DONE();
 }
 /* END_CASE */
@@ -1821,6 +1965,7 @@
     mbedtls_pk_init(&pk);
     psa_key_usage_t usage = usage_arg;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t new_key_id = MBEDTLS_SVC_KEY_ID_INIT;
 
     PSA_INIT();
 
@@ -1846,9 +1991,15 @@
     TEST_EQUAL(psa_get_key_algorithm(&attributes), expected_alg);
     TEST_EQUAL(psa_get_key_enrollment_algorithm(&attributes), PSA_ALG_NONE);
 
+    TEST_EQUAL(mbedtls_pk_import_into_psa(&pk, &attributes, &new_key_id), 0);
+    if (!mbedtls_test_key_consistency_psa_pk(new_key_id, &pk)) {
+        goto exit;
+    }
+
 exit:
     mbedtls_pk_free(&pk);
     psa_reset_key_attributes(&attributes);
+    psa_destroy_key(new_key_id);
     PSA_DONE();
 }
 /* END_CASE */
@@ -1889,13 +2040,14 @@
     mbedtls_pk_context pk;
     mbedtls_pk_init(&pk);
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    mbedtls_svc_key_id_t old_key_id = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_type_t from_type = from_type_arg;
     size_t bits = from_bits_arg;
     psa_key_usage_t from_usage = from_usage_arg;
     psa_algorithm_t alg = from_alg_arg;
     psa_key_usage_t usage = usage_arg;
     psa_key_usage_t expected_usage = expected_usage_arg;
+    mbedtls_svc_key_id_t new_key_id = MBEDTLS_SVC_KEY_ID_INIT;
 
     PSA_INIT();
 
@@ -1905,8 +2057,8 @@
     psa_set_key_algorithm(&attributes, alg);
     psa_set_key_enrollment_algorithm(&attributes, 42);
     //TODO: test with persistent key
-    PSA_ASSERT(psa_generate_key(&attributes, &key_id));
-    TEST_EQUAL(mbedtls_pk_setup_opaque(&pk, key_id), 0);
+    PSA_ASSERT(psa_generate_key(&attributes, &old_key_id));
+    TEST_EQUAL(mbedtls_pk_setup_opaque(&pk, old_key_id), 0);
 
     psa_key_type_t expected_psa_type =
         to_pair ? from_type : PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(from_type);
@@ -1923,12 +2075,124 @@
         TEST_EQUAL(psa_get_key_usage_flags(&attributes), expected_usage);
         TEST_EQUAL(psa_get_key_algorithm(&attributes), alg);
         TEST_EQUAL(psa_get_key_enrollment_algorithm(&attributes), PSA_ALG_NONE);
+
+        int expected_import_ret = 0;
+        if (to_pair &&
+            !(from_usage & (PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT))) {
+            expected_import_ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
+        }
+        TEST_EQUAL(mbedtls_pk_import_into_psa(&pk, &attributes, &new_key_id),
+                   expected_import_ret);
+        if (expected_import_ret == 0) {
+            if (!mbedtls_test_key_consistency_psa_pk(new_key_id, &pk)) {
+                goto exit;
+            }
+        }
     }
 
 exit:
     mbedtls_pk_free(&pk);
-    psa_destroy_key(key_id);
+    psa_destroy_key(old_key_id);
+    psa_destroy_key(new_key_id);
     psa_reset_key_attributes(&attributes);
     PSA_DONE();
 }
 /* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C */
+void pk_import_into_psa_fail(int pk_type, int from_pair,
+                             int type_arg, int bits_arg,
+                             int expected_ret)
+{
+    mbedtls_pk_context pk;
+    mbedtls_pk_init(&pk);
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_type_t type = type_arg;
+    size_t bits = bits_arg;
+    mbedtls_svc_key_id_t key_id = mbedtls_svc_key_id_make(0, 42);
+
+    PSA_INIT();
+
+    psa_key_type_t expected_psa_type;
+    TEST_EQUAL(pk_setup_for_type(pk_type, from_pair,
+                                 &pk, &expected_psa_type), 0);
+
+    psa_set_key_type(&attributes, type);
+    psa_set_key_bits(&attributes, bits);
+
+    TEST_EQUAL(mbedtls_pk_import_into_psa(&pk, &attributes, &key_id),
+               expected_ret);
+    TEST_ASSERT(mbedtls_svc_key_id_equal(key_id, MBEDTLS_SVC_KEY_ID_INIT));
+
+exit:
+    psa_destroy_key(key_id);
+    mbedtls_pk_free(&pk);
+    psa_reset_key_attributes(&attributes);
+    PSA_DONE();
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_USE_PSA_CRYPTO */
+void pk_import_into_psa_opaque(int from_type, int from_bits,
+                               int from_usage, int from_alg,
+                               int to_type, int to_bits,
+                               int to_usage, int to_alg,
+                               int expected_ret)
+{
+    mbedtls_pk_context pk;
+    mbedtls_pk_init(&pk);
+    psa_key_attributes_t from_attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t from_key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t to_attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t to_key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t actual_attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    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));
+    TEST_EQUAL(mbedtls_pk_setup_opaque(&pk, from_key_id), 0);
+
+    psa_set_key_type(&to_attributes, to_type);
+    psa_set_key_bits(&to_attributes, to_bits);
+    psa_set_key_usage_flags(&to_attributes, to_usage);
+    psa_set_key_algorithm(&to_attributes, to_alg);
+
+    TEST_EQUAL(mbedtls_pk_import_into_psa(&pk, &to_attributes, &to_key_id),
+               expected_ret);
+
+    if (expected_ret == 0) {
+        PSA_ASSERT(psa_get_key_attributes(to_key_id, &actual_attributes));
+        TEST_EQUAL(to_type, psa_get_key_type(&actual_attributes));
+        if (to_bits != 0) {
+            TEST_EQUAL(to_bits, psa_get_key_bits(&actual_attributes));
+        }
+        TEST_EQUAL(to_alg, psa_get_key_algorithm(&actual_attributes));
+        psa_key_usage_t expected_usage = to_usage;
+        if (expected_usage & PSA_KEY_USAGE_SIGN_HASH) {
+            expected_usage |= PSA_KEY_USAGE_SIGN_MESSAGE;
+        }
+        if (expected_usage & PSA_KEY_USAGE_VERIFY_HASH) {
+            expected_usage |= PSA_KEY_USAGE_VERIFY_MESSAGE;
+        }
+        TEST_EQUAL(expected_usage, psa_get_key_usage_flags(&actual_attributes));
+        if (!mbedtls_test_key_consistency_psa_pk(to_key_id, &pk)) {
+            goto exit;
+        }
+    } else {
+        TEST_ASSERT(mbedtls_svc_key_id_equal(to_key_id, MBEDTLS_SVC_KEY_ID_INIT));
+    }
+
+exit:
+    mbedtls_pk_free(&pk);
+    psa_destroy_key(from_key_id);
+    psa_destroy_key(to_key_id);
+    psa_reset_key_attributes(&from_attributes);
+    psa_reset_key_attributes(&to_attributes);
+    psa_reset_key_attributes(&actual_attributes);
+    PSA_DONE();
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_pkparse.function b/tests/suites/test_suite_pkparse.function
index 829e789..7dc8413 100644
--- a/tests/suites/test_suite_pkparse.function
+++ b/tests/suites/test_suite_pkparse.function
@@ -6,10 +6,91 @@
 #include "mbedtls/psa_util.h"
 #include "pk_internal.h"
 
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+#include "test/psa_exercise_key.h"
+#endif
+
 #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
 #define HAVE_mbedtls_pk_parse_key_pkcs8_encrypted_der
 #endif
 
+#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_FS_IO)
+static int test_psa_bridge(const mbedtls_pk_context *ctx,
+                           psa_key_usage_t usage_flag)
+{
+    switch (usage_flag) {
+        case PSA_KEY_USAGE_SIGN_HASH:
+            mbedtls_test_set_step(0);
+            break;
+        case PSA_KEY_USAGE_SIGN_MESSAGE:
+            mbedtls_test_set_step(1);
+            break;
+        case PSA_KEY_USAGE_DECRYPT:
+            mbedtls_test_set_step(2);
+            break;
+        case PSA_KEY_USAGE_DERIVE:
+            mbedtls_test_set_step(3);
+            break;
+        case PSA_KEY_USAGE_VERIFY_HASH:
+            mbedtls_test_set_step(4);
+            break;
+        case PSA_KEY_USAGE_VERIFY_MESSAGE:
+            mbedtls_test_set_step(5);
+            break;
+        case PSA_KEY_USAGE_ENCRYPT:
+            mbedtls_test_set_step(6);
+            break;
+    }
+
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t psa_key = MBEDTLS_SVC_KEY_ID_INIT;
+    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);
+    if (!mbedtls_test_key_consistency_psa_pk(psa_key, ctx)) {
+        goto exit;
+    }
+
+    psa_algorithm_t exercise_usage = psa_get_key_usage_flags(&attributes);
+    psa_algorithm_t exercise_alg = psa_get_key_algorithm(&attributes);
+    if (mbedtls_test_can_exercise_psa_algorithm(exercise_alg)) {
+        TEST_ASSERT(mbedtls_test_psa_exercise_key(psa_key,
+                                                  exercise_usage,
+                                                  exercise_alg));
+    }
+
+    mbedtls_test_set_step((unsigned long) -1);
+    ok = 1;
+
+exit:
+    psa_destroy_key(psa_key);
+    psa_reset_key_attributes(&attributes);
+    return ok;
+}
+
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+/* Whether a pk key can do ECDSA. Opaque keys are not supported since this
+ * test suite does not create opaque keys. */
+static int pk_can_ecdsa(const mbedtls_pk_context *ctx)
+{
+    /* Check whether we have an EC key. Unfortunately this also accepts
+     * keys on Montgomery curves, which can only do ECDH, so we'll have
+     * to dig further. */
+    if (!mbedtls_pk_can_do(ctx, MBEDTLS_PK_ECDSA)) {
+        return 0;
+    }
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+    return ctx->ec_family != PSA_ECC_FAMILY_MONTGOMERY;
+#elif defined(MBEDTLS_ECDSA_C)
+    return mbedtls_ecdsa_can_do(mbedtls_pk_ec_ro(*ctx)->grp.id);
+#else
+    return 0;
+#endif
+}
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+#endif /* MBEDTLS_PSA_CRYPTO_C &&  && MBEDTLS_FS_IO */
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -47,36 +128,19 @@
         TEST_EQUAL(mbedtls_pk_get_len(&ctx), (bitlen + 7) / 8);
 
 #if defined(MBEDTLS_PSA_CRYPTO_C)
-        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-        TEST_EQUAL(mbedtls_pk_get_psa_attributes(&ctx,
-                                                 PSA_KEY_USAGE_SIGN_HASH,
-                                                 &attributes), 0);
-        psa_reset_key_attributes(&attributes);
-        TEST_EQUAL(mbedtls_pk_get_psa_attributes(&ctx,
-                                                 PSA_KEY_USAGE_SIGN_MESSAGE,
-                                                 &attributes), 0);
-        psa_reset_key_attributes(&attributes);
-        TEST_EQUAL(mbedtls_pk_get_psa_attributes(&ctx,
-                                                 PSA_KEY_USAGE_DECRYPT,
-                                                 &attributes), 0);
-        psa_reset_key_attributes(&attributes);
-        TEST_EQUAL(mbedtls_pk_get_psa_attributes(&ctx,
-                                                 PSA_KEY_USAGE_VERIFY_HASH,
-                                                 &attributes), 0);
-        psa_reset_key_attributes(&attributes);
-        TEST_EQUAL(mbedtls_pk_get_psa_attributes(&ctx,
-                                                 PSA_KEY_USAGE_VERIFY_MESSAGE,
-                                                 &attributes), 0);
-        psa_reset_key_attributes(&attributes);
-        TEST_EQUAL(mbedtls_pk_get_psa_attributes(&ctx,
-                                                 PSA_KEY_USAGE_ENCRYPT,
-                                                 &attributes), 0);
+        PSA_INIT();
+        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_SIGN_HASH));
+        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_SIGN_MESSAGE));
+        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_DECRYPT));
+        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_HASH));
+        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_MESSAGE));
+        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_ENCRYPT));
 #endif
     }
 
 exit:
     mbedtls_pk_free(&ctx);
-    MD_PSA_DONE();
+    PSA_DONE();
 }
 
 /* END_CASE */
@@ -105,24 +169,16 @@
         TEST_EQUAL(mbedtls_pk_get_len(&ctx), (bitlen + 7) / 8);
 
 #if defined(MBEDTLS_PSA_CRYPTO_C)
-        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-        TEST_EQUAL(mbedtls_pk_get_psa_attributes(&ctx,
-                                                 PSA_KEY_USAGE_ENCRYPT,
-                                                 &attributes), 0);
-        psa_reset_key_attributes(&attributes);
-        TEST_EQUAL(mbedtls_pk_get_psa_attributes(&ctx,
-                                                 PSA_KEY_USAGE_VERIFY_HASH,
-                                                 &attributes), 0);
-        psa_reset_key_attributes(&attributes);
-        TEST_EQUAL(mbedtls_pk_get_psa_attributes(&ctx,
-                                                 PSA_KEY_USAGE_VERIFY_MESSAGE,
-                                                 &attributes), 0);
+        PSA_INIT();
+        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_HASH));
+        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_MESSAGE));
+        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_ENCRYPT));
 #endif
     }
 
 exit:
     mbedtls_pk_free(&ctx);
-    MD_PSA_DONE();
+    PSA_DONE();
 }
 /* END_CASE */
 
@@ -152,20 +208,17 @@
 #endif
 
 #if defined(MBEDTLS_PSA_CRYPTO_C)
-        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-        TEST_EQUAL(mbedtls_pk_get_psa_attributes(&ctx,
-                                                 PSA_KEY_USAGE_VERIFY_HASH,
-                                                 &attributes), 0);
-        psa_reset_key_attributes(&attributes);
-        TEST_EQUAL(mbedtls_pk_get_psa_attributes(&ctx,
-                                                 PSA_KEY_USAGE_VERIFY_MESSAGE,
-                                                 &attributes), 0);
+        PSA_INIT();
+        if (pk_can_ecdsa(&ctx)) {
+            TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_HASH));
+            TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_MESSAGE));
+        }
 #endif
     }
 
 exit:
     mbedtls_pk_free(&ctx);
-    MD_OR_USE_PSA_DONE();
+    PSA_DONE();
 }
 /* END_CASE */
 
@@ -193,32 +246,20 @@
 #endif
 
 #if defined(MBEDTLS_PSA_CRYPTO_C)
-        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-        TEST_EQUAL(mbedtls_pk_get_psa_attributes(&ctx,
-                                                 PSA_KEY_USAGE_SIGN_HASH,
-                                                 &attributes), 0);
-        psa_reset_key_attributes(&attributes);
-        TEST_EQUAL(mbedtls_pk_get_psa_attributes(&ctx,
-                                                 PSA_KEY_USAGE_SIGN_MESSAGE,
-                                                 &attributes), 0);
-        psa_reset_key_attributes(&attributes);
-        TEST_EQUAL(mbedtls_pk_get_psa_attributes(&ctx,
-                                                 PSA_KEY_USAGE_DERIVE,
-                                                 &attributes), 0);
-        psa_reset_key_attributes(&attributes);
-        TEST_EQUAL(mbedtls_pk_get_psa_attributes(&ctx,
-                                                 PSA_KEY_USAGE_VERIFY_HASH,
-                                                 &attributes), 0);
-        psa_reset_key_attributes(&attributes);
-        TEST_EQUAL(mbedtls_pk_get_psa_attributes(&ctx,
-                                                 PSA_KEY_USAGE_VERIFY_MESSAGE,
-                                                 &attributes), 0);
+        PSA_INIT();
+        TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_DERIVE));
+        if (pk_can_ecdsa(&ctx)) {
+            TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_SIGN_HASH));
+            TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_SIGN_MESSAGE));
+            TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_HASH));
+            TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_MESSAGE));
+        }
 #endif
     }
 
 exit:
     mbedtls_pk_free(&ctx);
-    MD_OR_USE_PSA_DONE();
+    PSA_DONE();
 }
 /* END_CASE */
 
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index 34af94a..c55af03 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -104,9 +104,9 @@
 depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT
 import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0:1024:-1:PSA_ERROR_BUFFER_TOO_SMALL:1
 
-PSA import/export RSA keypair: trailing garbage ignored
+PSA import/export RSA keypair: trailing garbage rejected
 depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT
-import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b2400":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0:1024:-1:PSA_SUCCESS:0
+import_with_data:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b2400":PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import/export RSA public key: good, 1024-bit, opaque
 depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:PSA_CRYPTO_DRIVER_TEST
@@ -156,9 +156,9 @@
 depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT:PSA_CRYPTO_DRIVER_TEST
 import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( PSA_KEY_PERSISTENCE_VOLATILE, TEST_DRIVER_LOCATION ):1024:-1:PSA_ERROR_BUFFER_TOO_SMALL:1
 
-PSA import/export RSA keypair: trailing garbage ignored, opaque
+PSA import/export RSA keypair: trailing garbage rejected, opaque
 depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT:PSA_CRYPTO_DRIVER_TEST
-import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b2400":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( PSA_KEY_PERSISTENCE_VOLATILE, TEST_DRIVER_LOCATION ):1024:-1:PSA_SUCCESS:0
+import_with_data:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b2400":PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import RSA keypair: truncated
 depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT
@@ -6870,6 +6870,18 @@
 depends_on:PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128:PSA_WANT_ALG_CMAC:PSA_WANT_KEY_TYPE_AES:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH
 derive_key_type:PSA_ALG_PBKDF2_AES_CMAC_PRF_128:"706173737764":"01":"73616c74":PSA_KEY_TYPE_AES:256:"28e288c6345bb5ecf7ca70274208a3ba0f1148b5868537d5e09d3ee6813b1f52"
 
+PSA key derivation: default params -> AES-128
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_AES
+derive_key_ext:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_AES:128:0:"":PSA_SUCCESS:"3cb25f25faacd57a90434f64d0362f2a"
+
+PSA key derivation: params.flags=1 -> AES-128
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_AES
+derive_key_ext:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_AES:128:1:"":PSA_ERROR_INVALID_ARGUMENT:""
+
+PSA key derivation: params.data non-empty -> AES-128
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_AES
+derive_key_ext:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_AES:128:0:"2a":PSA_ERROR_INVALID_ARGUMENT:""
+
 PSA key derivation: invalid type (0)
 depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
 derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_NONE:128:PSA_ERROR_NOT_SUPPORTED:0
@@ -7419,24 +7431,6 @@
 depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_MONTGOMERY_448
 generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):448:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_SUCCESS:0
 
-PSA generate key: RSA, default e
-generate_key_rsa:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:"":PSA_SUCCESS
-
-PSA generate key: RSA, e=3
-generate_key_rsa:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:"03":PSA_SUCCESS
-
-PSA generate key: RSA, e=65537
-generate_key_rsa:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:"010001":PSA_SUCCESS
-
-PSA generate key: RSA, e=513
-generate_key_rsa:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:"0201":PSA_SUCCESS
-
-PSA generate key: RSA, e=1
-generate_key_rsa:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:"01":PSA_ERROR_INVALID_ARGUMENT
-
-PSA generate key: RSA, e=2
-generate_key_rsa:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:"02":PSA_ERROR_INVALID_ARGUMENT
-
 PSA generate key: FFDH, 2048 bits, good
 depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE:PSA_WANT_DH_RFC7919_2048
 generate_key:PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919):2048:PSA_KEY_USAGE_EXPORT:PSA_ALG_FFDH:PSA_SUCCESS:0
@@ -7461,6 +7455,86 @@
 depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE
 generate_key:PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919):1024:PSA_KEY_USAGE_EXPORT:PSA_ALG_FFDH:PSA_ERROR_NOT_SUPPORTED:0
 
+PSA generate key ext: RSA, params.flags=1
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:1:"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA generate key ext: RSA, empty e
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:0:"":PSA_SUCCESS
+
+PSA generate key ext: RSA, e=3
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:0:"03":PSA_SUCCESS
+
+PSA generate key ext: RSA, e=3 with leading zeros
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:0:"000003":PSA_SUCCESS
+
+# TODO: currently errors with NOT_SUPPORTED because e is converted to an int
+# and the conversion errors out if there are too many digits without checking
+# for leading zeros. This is a very minor bug. Re-enable this test when this
+# bug is fixed.
+#PSA generate key ext: RSA, e=3 with many leading zeros
+#depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
+#generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:0:"0000000000000000000000000000000003":PSA_SUCCESS
+
+PSA generate key ext: RSA, e=513
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:0:"0201":PSA_SUCCESS
+
+PSA generate key ext: RSA, e=65537
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:0:"010001":PSA_SUCCESS
+
+PSA generate key ext: RSA, e=2^31-1
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:INT_MAX>=0x7fffffff
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:0:"7fffffff":PSA_SUCCESS
+
+PSA generate key ext: RSA, e=2^31+3 (too large for built-in RSA)
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE:!MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE:INT_MAX<=0x7fffffff
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:0:"80000003":PSA_ERROR_NOT_SUPPORTED
+
+PSA generate key ext: RSA, e=2^64+3 (too large for built-in RSA)
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE:!MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE:INT_MAX<=0xffffffffffffffff
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:0:"010000000000000003":PSA_ERROR_NOT_SUPPORTED
+
+PSA generate key ext: RSA, e=1
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:0:"01":PSA_ERROR_INVALID_ARGUMENT
+
+PSA generate key ext: RSA, e=0
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:0:"00":PSA_ERROR_INVALID_ARGUMENT
+
+PSA generate key ext: RSA, e=2
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:0:"02":PSA_ERROR_INVALID_ARGUMENT
+
+# Check that with a driver, we reject a custom e as unsupported,
+# as opposed to silently using the default e.
+# When we add proper driver support, remove this test case and remove
+# the dependency on MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE from
+# the positive/invalid_argument test cases.
+PSA generate key ext: RSA, e=3 with driver and no fallback (not yet supported)
+depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:!MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE
+generate_key_ext:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:0:0:"03":PSA_ERROR_NOT_SUPPORTED
+
+PSA generate key ext: ECC, flags=0
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_ECDH
+generate_key_ext:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:0:"":PSA_SUCCESS
+
+PSA generate key ext: ECC, flags=1
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_ECDH
+generate_key_ext:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:1:"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA generate key ext: ECC, params.data non-empty
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_ECDH
+generate_key_ext:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:0:"2a":PSA_ERROR_INVALID_ARGUMENT
+
+Key production parameters initializers
+key_production_parameters_init:
+
 PSA import persistent key: raw data, 8 bits
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
 persistent_key_load_key_from_storage:"2a":PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:IMPORT_KEY
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 95e7a2d..09874a1 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -1255,6 +1255,84 @@
 }
 #endif /* MBEDTLS_ECP_RESTARTABLE */
 
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+static int rsa_test_e(mbedtls_svc_key_id_t key,
+                      size_t bits,
+                      const data_t *e_arg)
+{
+    uint8_t *exported = NULL;
+    size_t exported_size =
+        PSA_EXPORT_KEY_OUTPUT_SIZE(PSA_KEY_TYPE_RSA_PUBLIC_KEY, bits);
+    size_t exported_length = SIZE_MAX;
+    int ok = 0;
+
+    TEST_CALLOC(exported, exported_size);
+    PSA_ASSERT(psa_export_public_key(key,
+                                     exported, exported_size,
+                                     &exported_length));
+    uint8_t *p = exported;
+    uint8_t *end = exported + exported_length;
+    size_t len;
+    /*   RSAPublicKey ::= SEQUENCE {
+     *      modulus            INTEGER,    -- n
+     *      publicExponent     INTEGER  }  -- e
+     */
+    TEST_EQUAL(0, mbedtls_asn1_get_tag(&p, end, &len,
+                                       MBEDTLS_ASN1_SEQUENCE |
+                                       MBEDTLS_ASN1_CONSTRUCTED));
+    TEST_ASSERT(mbedtls_test_asn1_skip_integer(&p, end, bits, bits, 1));
+    TEST_EQUAL(0, mbedtls_asn1_get_tag(&p, end, &len,
+                                       MBEDTLS_ASN1_INTEGER));
+    if (len >= 1 && p[0] == 0) {
+        ++p;
+        --len;
+    }
+    if (e_arg->len == 0) {
+        TEST_EQUAL(len, 3);
+        TEST_EQUAL(p[0], 1);
+        TEST_EQUAL(p[1], 0);
+        TEST_EQUAL(p[2], 1);
+    } else {
+        const uint8_t *expected = e_arg->x;
+        size_t expected_len = e_arg->len;
+        while (expected_len > 0 && *expected == 0) {
+            ++expected;
+            --expected_len;
+        }
+        TEST_MEMORY_COMPARE(p, len, expected, expected_len);
+    }
+    ok = 1;
+
+exit:
+    mbedtls_free(exported);
+    return ok;
+}
+#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE */
+
+static int setup_key_production_parameters(
+    psa_key_production_parameters_t **params, size_t *params_data_length,
+    int flags_arg, const data_t *params_data)
+{
+    *params_data_length = params_data->len;
+    /* If there are N bytes of padding at the end of
+     * psa_key_production_parameters_t, then it's enough to allocate
+     * MIN(sizeof(psa_key_production_parameters_t),
+     *     offsetof(psa_key_production_parameters_t, data) + params_data_length).
+     *
+     * For simplicity, here, we allocate up to N more bytes than necessary.
+     * In practice, the current layout of psa_key_production_parameters_t
+     * makes padding extremely unlikely, so we don't worry about testing
+     * that the library code doesn't try to access these extra N bytes.
+     */
+    *params = mbedtls_calloc(1, sizeof(**params) + *params_data_length);
+    TEST_ASSERT(*params != NULL);
+    (*params)->flags = (uint32_t) flags_arg;
+    memcpy((*params)->data, params_data->x, params_data->len);
+    return 1;
+exit:
+    return 0;
+}
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -9255,6 +9333,81 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void derive_key_ext(int alg_arg,
+                    data_t *key_data,
+                    data_t *input1,
+                    data_t *input2,
+                    int key_type_arg, int bits_arg,
+                    int flags_arg,
+                    data_t *params_data,
+                    psa_status_t expected_status,
+                    data_t *expected_export)
+{
+    mbedtls_svc_key_id_t base_key = MBEDTLS_SVC_KEY_ID_INIT;
+    mbedtls_svc_key_id_t derived_key = MBEDTLS_SVC_KEY_ID_INIT;
+    const psa_algorithm_t alg = alg_arg;
+    const psa_key_type_t key_type = key_type_arg;
+    const size_t bits = bits_arg;
+    psa_key_production_parameters_t *params = NULL;
+    size_t params_data_length = 0;
+    psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
+    const size_t export_buffer_size =
+        PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, bits);
+    uint8_t *export_buffer = NULL;
+    psa_key_attributes_t base_attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_attributes_t derived_attributes = PSA_KEY_ATTRIBUTES_INIT;
+    size_t export_length;
+
+    TEST_CALLOC(export_buffer, export_buffer_size);
+    PSA_ASSERT(psa_crypto_init());
+
+    psa_set_key_usage_flags(&base_attributes, PSA_KEY_USAGE_DERIVE);
+    psa_set_key_algorithm(&base_attributes, alg);
+    psa_set_key_type(&base_attributes, PSA_KEY_TYPE_DERIVE);
+    PSA_ASSERT(psa_import_key(&base_attributes, key_data->x, key_data->len,
+                              &base_key));
+
+    if (mbedtls_test_psa_setup_key_derivation_wrap(
+            &operation, base_key, alg,
+            input1->x, input1->len,
+            input2->x, input2->len,
+            PSA_KEY_DERIVATION_UNLIMITED_CAPACITY) == 0) {
+        goto exit;
+    }
+
+    psa_set_key_usage_flags(&derived_attributes, PSA_KEY_USAGE_EXPORT);
+    psa_set_key_algorithm(&derived_attributes, 0);
+    psa_set_key_type(&derived_attributes, key_type);
+    psa_set_key_bits(&derived_attributes, bits);
+    if (!setup_key_production_parameters(&params, &params_data_length,
+                                         flags_arg, params_data)) {
+        goto exit;
+    }
+
+    TEST_EQUAL(psa_key_derivation_output_key_ext(&derived_attributes, &operation,
+                                                 params, params_data_length,
+                                                 &derived_key),
+               expected_status);
+
+    if (expected_status == PSA_SUCCESS) {
+        PSA_ASSERT(psa_export_key(derived_key,
+                                  export_buffer, export_buffer_size,
+                                  &export_length));
+        TEST_MEMORY_COMPARE(export_buffer, export_length,
+                            expected_export->x, expected_export->len);
+    }
+
+exit:
+    mbedtls_free(export_buffer);
+    mbedtls_free(params);
+    psa_key_derivation_abort(&operation);
+    psa_destroy_key(base_key);
+    psa_destroy_key(derived_key);
+    PSA_DONE();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void derive_key(int alg_arg,
                 data_t *key_data, data_t *input1, data_t *input2,
                 int type_arg, int bits_arg,
@@ -9687,71 +9840,57 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_ALG_RSA_PKCS1V15_SIGN */
-void generate_key_rsa(int bits_arg,
-                      data_t *e_arg,
+/* BEGIN_CASE */
+void generate_key_ext(int type_arg,
+                      int bits_arg,
+                      int usage_arg,
+                      int alg_arg,
+                      int flags_arg,
+                      data_t *params_data,
                       int expected_status_arg)
 {
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
-    psa_key_type_t type = PSA_KEY_TYPE_RSA_KEY_PAIR;
+    psa_key_type_t type = type_arg;
+    psa_key_usage_t usage = usage_arg;
     size_t bits = bits_arg;
-    psa_key_usage_t usage = PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT;
-    psa_algorithm_t alg = PSA_ALG_RSA_PKCS1V15_SIGN_RAW;
+    psa_algorithm_t alg = alg_arg;
     psa_status_t expected_status = expected_status_arg;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    uint8_t *exported = NULL;
-    size_t exported_size =
-        PSA_EXPORT_KEY_OUTPUT_SIZE(PSA_KEY_TYPE_RSA_PUBLIC_KEY, bits);
-    size_t exported_length = SIZE_MAX;
-    uint8_t *e_read_buffer = NULL;
-    int is_default_public_exponent = 0;
-    size_t e_read_size = PSA_KEY_DOMAIN_PARAMETERS_SIZE(type, bits);
-    size_t e_read_length = SIZE_MAX;
-
-    if (e_arg->len == 0 ||
-        (e_arg->len == 3 &&
-         e_arg->x[0] == 1 && e_arg->x[1] == 0 && e_arg->x[2] == 1)) {
-        is_default_public_exponent = 1;
-        e_read_size = 0;
-    }
-    TEST_CALLOC(e_read_buffer, e_read_size);
-    TEST_CALLOC(exported, exported_size);
+    psa_key_production_parameters_t *params = NULL;
+    size_t params_data_length = 0;
+    psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT(psa_crypto_init());
 
     psa_set_key_usage_flags(&attributes, usage);
     psa_set_key_algorithm(&attributes, alg);
-    PSA_ASSERT(psa_set_key_domain_parameters(&attributes, type,
-                                             e_arg->x, e_arg->len));
+    psa_set_key_type(&attributes, type);
     psa_set_key_bits(&attributes, bits);
 
+    if (!setup_key_production_parameters(&params, &params_data_length,
+                                         flags_arg, params_data)) {
+        goto exit;
+    }
+
     /* Generate a key */
-    TEST_EQUAL(psa_generate_key(&attributes, &key), expected_status);
+    psa_status_t status = psa_generate_key_ext(&attributes,
+                                               params, params_data_length,
+                                               &key);
+
+    TEST_EQUAL(status, expected_status);
     if (expected_status != PSA_SUCCESS) {
         goto exit;
     }
 
     /* Test the key information */
-    PSA_ASSERT(psa_get_key_attributes(key, &attributes));
-    TEST_EQUAL(psa_get_key_type(&attributes), type);
-    TEST_EQUAL(psa_get_key_bits(&attributes), bits);
-    psa_status_t status = psa_get_key_domain_parameters(&attributes,
-                                                        e_read_buffer, e_read_size,
-                                                        &e_read_length);
+    PSA_ASSERT(psa_get_key_attributes(key, &got_attributes));
+    TEST_EQUAL(psa_get_key_type(&got_attributes), type);
+    TEST_EQUAL(psa_get_key_bits(&got_attributes), bits);
 
-
-#if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \
-    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \
-    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
-    if (is_default_public_exponent) {
-        TEST_EQUAL(e_read_length, 0);
-    } else {
-        TEST_EQUAL(status, PSA_SUCCESS);
-        TEST_MEMORY_COMPARE(e_read_buffer, e_read_length, e_arg->x, e_arg->len);
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+    if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
+        TEST_ASSERT(rsa_test_e(key, bits, params_data));
     }
-#else
-    (void) is_default_public_exponent;
-    TEST_EQUAL(status, PSA_ERROR_NOT_SUPPORTED);
 #endif
 
     /* Do something with the key according to its type and permitted usage. */
@@ -9759,49 +9898,27 @@
         goto exit;
     }
 
-    /* Export the key and check the public exponent. */
-    PSA_ASSERT(psa_export_public_key(key,
-                                     exported, exported_size,
-                                     &exported_length));
-    {
-        uint8_t *p = exported;
-        uint8_t *end = exported + exported_length;
-        size_t len;
-        /*   RSAPublicKey ::= SEQUENCE {
-         *      modulus            INTEGER,    -- n
-         *      publicExponent     INTEGER  }  -- e
-         */
-        TEST_EQUAL(0, mbedtls_asn1_get_tag(&p, end, &len,
-                                           MBEDTLS_ASN1_SEQUENCE |
-                                           MBEDTLS_ASN1_CONSTRUCTED));
-        TEST_ASSERT(mbedtls_test_asn1_skip_integer(&p, end, bits, bits, 1));
-        TEST_EQUAL(0, mbedtls_asn1_get_tag(&p, end, &len,
-                                           MBEDTLS_ASN1_INTEGER));
-        if (len >= 1 && p[0] == 0) {
-            ++p;
-            --len;
-        }
-        if (e_arg->len == 0) {
-            TEST_EQUAL(len, 3);
-            TEST_EQUAL(p[0], 1);
-            TEST_EQUAL(p[1], 0);
-            TEST_EQUAL(p[2], 1);
-        } else {
-            TEST_MEMORY_COMPARE(p, len, e_arg->x, e_arg->len);
-        }
-    }
-
 exit:
     /*
-     * Key attributes may have been returned by psa_get_key_attributes() or
-     * set by psa_set_key_domain_parameters() thus reset them as required.
+     * Key attributes may have been returned by psa_get_key_attributes()
+     * thus reset them as required.
      */
-    psa_reset_key_attributes(&attributes);
-
+    psa_reset_key_attributes(&got_attributes);
+    mbedtls_free(params);
     psa_destroy_key(key);
     PSA_DONE();
-    mbedtls_free(e_read_buffer);
-    mbedtls_free(exported);
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void key_production_parameters_init()
+{
+    psa_key_production_parameters_t init = PSA_KEY_PRODUCTION_PARAMETERS_INIT;
+    psa_key_production_parameters_t zero;
+    memset(&zero, 0, sizeof(zero));
+
+    TEST_EQUAL(init.flags, 0);
+    TEST_EQUAL(zero.flags, 0);
 }
 /* END_CASE */
 
diff --git a/tests/suites/test_suite_rsa.data b/tests/suites/test_suite_rsa.data
index 778ec67..b52c7dc 100644
--- a/tests/suites/test_suite_rsa.data
+++ b/tests/suites/test_suite_rsa.data
@@ -764,7 +764,7 @@
 rsa_parse_pkcs1_key:0:"3066020100021100cc8ab070369ede72920e5a51523c857102030100010211009a6318982a7231de1894c54aa4909201020900f3058fd8dc484d61020900d7770dbd8b78a2110209009471f14c26428401020813425f060c4b72210208052b93d01747a87c020100":MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
 
 RSA parse private key - correct values, extra integer outside the SEQUENCE
-rsa_parse_pkcs1_key:0:"3063020100021100cc8ab070369ede72920e5a51523c857102030100010211009a6318982a7231de1894c54aa4909201020900f3058fd8dc484d61020900d7770dbd8b78a2110209009471f14c26428401020813425f060c4b72210208052b93d01747a87c020100":0
+rsa_parse_pkcs1_key:0:"3063020100021100cc8ab070369ede72920e5a51523c857102030100010211009a6318982a7231de1894c54aa4909201020900f3058fd8dc484d61020900d7770dbd8b78a2110209009471f14c26428401020813425f060c4b72210208052b93d01747a87c020100":MBEDTLS_ERR_RSA_BAD_INPUT_DATA
 
 RSA parse private key - correct values, n wrong tag
 rsa_parse_pkcs1_key:0:"3063020100FF1100cc8ab070369ede72920e5a51523c857102030100010211009a6318982a7231de1894c54aa4909201020900f3058fd8dc484d61020900d7770dbd8b78a2110209009471f14c26428401020813425f060c4b72210208052b93d01747a87c":MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
@@ -809,7 +809,7 @@
 rsa_parse_pkcs1_key:1:"308189028181009f091e6968b474f76f0e9c237c1d895996ae704b4f6d706acec8d2daac6209bf524aa3f658d0283adba1077f6cbe92e425dcde52290b239cade91be86c88425434986806e85734e159768f3dfea932baaa9409d25bace8ee9dce0cdde0903207299de575ae60feccf0daf82334ab83638539b0da74072f253acea8afc8e66bb70203000000":MBEDTLS_ERR_RSA_BAD_INPUT_DATA
 
 RSA parse public key - wrong sequence length
-rsa_parse_pkcs1_key:1:"308188028181009f091e6968b474f76f0e9c237c1d895996ae704b4f6d706acec8d2daac6209bf524aa3f658d0283adba1077f6cbe92e425dcde52290b239cade91be86c88425434986806e85734e159768f3dfea932baaa9409d25bace8ee9dce0cdde0903207299de575ae60feccf0daf82334ab83638539b0da74072f253acea8afc8e66bb70203010001":MBEDTLS_ERR_ASN1_OUT_OF_DATA
+rsa_parse_pkcs1_key:1:"308188028181009f091e6968b474f76f0e9c237c1d895996ae704b4f6d706acec8d2daac6209bf524aa3f658d0283adba1077f6cbe92e425dcde52290b239cade91be86c88425434986806e85734e159768f3dfea932baaa9409d25bace8ee9dce0cdde0903207299de575ae60feccf0daf82334ab83638539b0da74072f253acea8afc8e66bb70203010001":MBEDTLS_ERR_RSA_BAD_INPUT_DATA
 
 RSA parse public key - wrong modulus length
 rsa_parse_pkcs1_key:1:"308189028180009f091e6968b474f76f0e9c237c1d895996ae704b4f6d706acec8d2daac6209bf524aa3f658d0283adba1077f6cbe92e425dcde52290b239cade91be86c88425434986806e85734e159768f3dfea932baaa9409d25bace8ee9dce0cdde0903207299de575ae60feccf0daf82334ab83638539b0da74072f253acea8afc8e66bb70203010001":MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
@@ -827,7 +827,7 @@
 rsa_parse_pkcs1_key:1:"30818c028181009f091e6968b474f76f0e9c237c1d895996ae704b4f6d706acec8d2daac6209bf524aa3f658d0283adba1077f6cbe92e425dcde52290b239cade91be86c88425434986806e85734e159768f3dfea932baaa9409d25bace8ee9dce0cdde0903207299de575ae60feccf0daf82334ab83638539b0da74072f253acea8afc8e66bb70203010001020100":MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
 
 RSA parse public key - correct values, extra integer outside the SEQUENCE
-rsa_parse_pkcs1_key:1:"308189028181009f091e6968b474f76f0e9c237c1d895996ae704b4f6d706acec8d2daac6209bf524aa3f658d0283adba1077f6cbe92e425dcde52290b239cade91be86c88425434986806e85734e159768f3dfea932baaa9409d25bace8ee9dce0cdde0903207299de575ae60feccf0daf82334ab83638539b0da74072f253acea8afc8e66bb70203010001020100":0
+rsa_parse_pkcs1_key:1:"308189028181009f091e6968b474f76f0e9c237c1d895996ae704b4f6d706acec8d2daac6209bf524aa3f658d0283adba1077f6cbe92e425dcde52290b239cade91be86c88425434986806e85734e159768f3dfea932baaa9409d25bace8ee9dce0cdde0903207299de575ae60feccf0daf82334ab83638539b0da74072f253acea8afc8e66bb70203010001020100":MBEDTLS_ERR_RSA_BAD_INPUT_DATA
 
 RSA priv key write - incremental output buffer size
 rsa_key_write_incremental:0:"3063020100021100cc8ab070369ede72920e5a51523c857102030100010211009a6318982a7231de1894c54aa4909201020900f3058fd8dc484d61020900d7770dbd8b78a2110209009471f14c26428401020813425f060c4b72210208052b93d01747a87c"
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index 2751e58..0e798f4 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -1990,7 +1990,6 @@
     USE_PSA_INIT();
 
     /* Prepare a dummy session to work on */
-    ((void) endpoint_type);
     ((void) tls_version);
     ((void) ticket_len);
     ((void) crt_file);
@@ -2004,7 +2003,7 @@
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
     if (tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {
         TEST_ASSERT(mbedtls_test_ssl_tls12_populate_session(
-                        &original, ticket_len, crt_file) == 0);
+                        &original, ticket_len, endpoint_type, crt_file) == 0);
     }
 #endif
 
@@ -2022,28 +2021,16 @@
      * Make sure both session structures are identical
      */
 #if defined(MBEDTLS_HAVE_TIME)
-    switch (tls_version) {
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SRV_C)
-        case MBEDTLS_SSL_VERSION_TLS1_3:
-            TEST_ASSERT(original.ticket_creation_time == restored.ticket_creation_time);
-            break;
-#endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        case MBEDTLS_SSL_VERSION_TLS1_2:
-            TEST_ASSERT(original.start == restored.start);
-            break;
-#endif
-
-        default:
-            /* should never happen */
-            TEST_ASSERT(0);
-            break;
+    if (tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {
+        TEST_ASSERT(original.start == restored.start);
     }
-
-
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C)
+    TEST_ASSERT(original.ticket_creation_time == restored.ticket_creation_time);
 #endif
+#endif /* MBEDTLS_HAVE_TIME */
 
     TEST_ASSERT(original.tls_version == restored.tls_version);
+    TEST_ASSERT(original.endpoint == restored.endpoint);
     TEST_ASSERT(original.ciphersuite == restored.ciphersuite);
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
     if (tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {
@@ -2102,7 +2089,6 @@
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
     if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
-        TEST_ASSERT(original.endpoint == restored.endpoint);
         TEST_ASSERT(original.ciphersuite == restored.ciphersuite);
         TEST_ASSERT(original.ticket_age_add == restored.ticket_age_add);
         TEST_ASSERT(original.ticket_flags == restored.ticket_flags);
@@ -2120,11 +2106,6 @@
             original.max_early_data_size == restored.max_early_data_size);
 #endif
 
-#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
-        if (endpoint_type == MBEDTLS_SSL_IS_SERVER) {
-            TEST_ASSERT(original.ticket_creation_time == restored.ticket_creation_time);
-        }
-#endif
 #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
         if (endpoint_type == MBEDTLS_SSL_IS_CLIENT) {
 #if defined(MBEDTLS_HAVE_TIME)
@@ -2172,7 +2153,6 @@
     USE_PSA_INIT();
 
     /* Prepare a dummy session to work on */
-    ((void) endpoint_type);
     ((void) ticket_len);
     ((void) crt_file);
 
@@ -2187,7 +2167,7 @@
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
         case MBEDTLS_SSL_VERSION_TLS1_2:
             TEST_ASSERT(mbedtls_test_ssl_tls12_populate_session(
-                            &session, ticket_len, crt_file) == 0);
+                            &session, ticket_len, endpoint_type, crt_file) == 0);
             break;
 #endif
         default:
@@ -2246,7 +2226,6 @@
     USE_PSA_INIT();
 
     /* Prepare dummy session and get serialized size */
-    ((void) endpoint_type);
     ((void) ticket_len);
     ((void) crt_file);
 
@@ -2260,7 +2239,7 @@
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
         case MBEDTLS_SSL_VERSION_TLS1_2:
             TEST_ASSERT(mbedtls_test_ssl_tls12_populate_session(
-                            &session, ticket_len, crt_file) == 0);
+                            &session, ticket_len, endpoint_type, crt_file) == 0);
             break;
 #endif
         default:
@@ -2306,7 +2285,6 @@
     USE_PSA_INIT();
 
     /* Prepare serialized session data */
-    ((void) endpoint_type);
     ((void) ticket_len);
     ((void) crt_file);
 
@@ -2321,7 +2299,7 @@
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
         case MBEDTLS_SSL_VERSION_TLS1_2:
             TEST_ASSERT(mbedtls_test_ssl_tls12_populate_session(
-                            &session, ticket_len, crt_file) == 0);
+                            &session, ticket_len, endpoint_type, crt_file) == 0);
             break;
 #endif
 
@@ -2378,7 +2356,6 @@
 
     mbedtls_ssl_session_init(&session);
     USE_PSA_INIT();
-    ((void) endpoint_type);
 
     switch (tls_version) {
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
@@ -2390,7 +2367,7 @@
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
         case MBEDTLS_SSL_VERSION_TLS1_2:
             TEST_ASSERT(mbedtls_test_ssl_tls12_populate_session(
-                            &session, 0, NULL) == 0);
+                            &session, 0, endpoint_type, NULL) == 0);
 
             break;
 #endif
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index b9ae20c..2b0920d 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -1774,7 +1774,7 @@
 
 X509 CRT ASN1 (TBS, inv SubPubKeyInfo, inv internal bitstring length)
 depends_on:MBEDTLS_RSA_C:MBEDTLS_MD_CAN_SHA256
-x509parse_crt:"308180306ba0030201008204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743015300d06092A864886F70D0101010500030400300000300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_OUT_OF_DATA
+x509parse_crt:"308180306ba0030201008204deadbeef300d06092a864886f70d01010b0500300c310a30080600130454657374301c170c303930313031303030303030170c303931323331323335393539300c310a300806001304546573743015300d06092A864886F70D0101010500030400300000300d06092a864886f70d01010b0500030200ff":"":MBEDTLS_ERR_PK_INVALID_PUBKEY
 
 X509 CRT ASN1 (TBS, inv SubPubKeyInfo, inv internal bitstring tag)
 depends_on:MBEDTLS_RSA_C:MBEDTLS_MD_CAN_SHA256