Merge pull request #8833 from Ryan-Everett-arm/threadsafe-multiparts

Make multi-part operations thread-safe
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/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/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/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/pk.h b/include/mbedtls/pk.h
index df11de6..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 */
 
 /**
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/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/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/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_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_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/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/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/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/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/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data
index 11dc319..989235d 100644
--- a/tests/suites/test_suite_pk.data
+++ b/tests/suites/test_suite_pk.data
@@ -744,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
@@ -1066,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)
@@ -1171,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 1aca4bd..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);
@@ -1052,7 +1145,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_MD_CAN_SHA256 */
+/* 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)
 {
@@ -1488,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 */
@@ -1806,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();
 
@@ -1846,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 */
@@ -1862,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();
 
@@ -1887,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 */
@@ -1930,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();
 
@@ -1946,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);
@@ -1964,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 */