Merge remote-tracking branch 'origin/pr/2386' into development-psa
diff --git a/crypto b/crypto
index 2169a5e..acdf07c 160000
--- a/crypto
+++ b/crypto
@@ -1 +1 @@
-Subproject commit 2169a5e54ded734f7844af1a16c39b993c2a992c
+Subproject commit acdf07c033bb7ce11f595ddbe0c66d438b46597c
diff --git a/include/mbedtls/psa_util.h b/include/mbedtls/psa_util.h
index a78c1a9..3684e98 100644
--- a/include/mbedtls/psa_util.h
+++ b/include/mbedtls/psa_util.h
@@ -41,6 +41,7 @@
 #include "ecp.h"
 #include "md.h"
 #include "pk.h"
+#include "oid.h"
 
 /* Translations for symmetric crypto. */
 
@@ -155,6 +156,82 @@
 
 /* Translations for ECC. */
 
+static inline int mbedtls_psa_get_ecc_oid_from_id(
+    psa_ecc_curve_t curve, char const **oid, size_t *oid_len )
+{
+    switch( curve )
+    {
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
+        case PSA_ECC_CURVE_SECP192R1:
+            *oid = MBEDTLS_OID_EC_GRP_SECP192R1;
+            *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192R1 );
+            return( 0 );
+#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+        case PSA_ECC_CURVE_SECP224R1:
+            *oid = MBEDTLS_OID_EC_GRP_SECP224R1;
+            *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224R1 );
+            return( 0 );
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+        case PSA_ECC_CURVE_SECP256R1:
+            *oid = MBEDTLS_OID_EC_GRP_SECP256R1;
+            *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256R1 );
+            return( 0 );
+#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+        case PSA_ECC_CURVE_SECP384R1:
+            *oid = MBEDTLS_OID_EC_GRP_SECP384R1;
+            *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP384R1 );
+            return( 0 );
+#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+        case PSA_ECC_CURVE_SECP521R1:
+            *oid = MBEDTLS_OID_EC_GRP_SECP521R1;
+            *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP521R1 );
+            return( 0 );
+#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
+#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
+        case PSA_ECC_CURVE_SECP192K1:
+            *oid = MBEDTLS_OID_EC_GRP_SECP192K1;
+            *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192K1 );
+            return( 0 );
+#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
+#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
+        case PSA_ECC_CURVE_SECP224K1:
+            *oid = MBEDTLS_OID_EC_GRP_SECP224K1;
+            *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224K1 );
+            return( 0 );
+#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
+#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+        case PSA_ECC_CURVE_SECP256K1:
+            *oid = MBEDTLS_OID_EC_GRP_SECP256K1;
+            *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256K1 );
+            return( 0 );
+#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
+#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
+        case PSA_ECC_CURVE_BRAINPOOL_P256R1:
+            *oid = MBEDTLS_OID_EC_GRP_BP256R1;
+            *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP256R1 );
+            return( 0 );
+#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */
+#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
+        case PSA_ECC_CURVE_BRAINPOOL_P384R1:
+            *oid = MBEDTLS_OID_EC_GRP_BP384R1;
+            *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP384R1 );
+            return( 0 );
+#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */
+#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
+        case PSA_ECC_CURVE_BRAINPOOL_P512R1:
+            *oid = MBEDTLS_OID_EC_GRP_BP512R1;
+            *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP512R1 );
+            return( 0 );
+#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
+    }
+
+     return( -1 );
+}
+
 static inline psa_ecc_curve_t mbedtls_psa_translate_ecc_group( mbedtls_ecp_group_id grpid )
 {
     switch( grpid )
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index d9f9802..8a29869 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -777,6 +777,7 @@
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
     defined(MBEDTLS_SSL_PROTO_TLS1_2)
+/* The hash buffer must have at least MBEDTLS_MD_MAX_SIZE bytes of length. */
 int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
                                             unsigned char *hash, size_t *hashlen,
                                             unsigned char *data, size_t data_len,
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index 7f8abd4..c7f879a 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -553,7 +553,7 @@
     int key_len;
     /* see ECP_PUB_DER_MAX_BYTES in pkwrite.c */
     unsigned char buf[30 + 2 * MBEDTLS_ECP_MAX_BYTES];
-    unsigned char *p = (unsigned char*) sig;
+    unsigned char *p;
     mbedtls_pk_info_t pk_info = mbedtls_eckey_info;
     psa_algorithm_t psa_sig_md, psa_md;
     psa_ecc_curve_t curve = mbedtls_psa_translate_ecc_group(
@@ -563,11 +563,12 @@
     if( curve == 0 )
         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
 
-    /* mbedlts_pk_write_pubkey_der() expects a full PK context,
+    /* mbedtls_pk_write_pubkey() expects a full PK context;
      * re-construct one to make it happy */
     key.pk_info = &pk_info;
     key.pk_ctx = ctx;
-    key_len = mbedtls_pk_write_pubkey_der( &key, buf, sizeof( buf ) );
+    p = buf + sizeof( buf );
+    key_len = mbedtls_pk_write_pubkey( &p, buf, &key );
     if( key_len <= 0 )
         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
 
@@ -603,6 +604,7 @@
         goto cleanup;
     }
 
+    p = (unsigned char*) sig;
     if( ( ret = extract_ecdsa_sig( &p, sig + sig_len, buf,
                                    signature_part_size ) ) != 0 )
     {
diff --git a/library/pkwrite.c b/library/pkwrite.c
index 11a2a61..ab4f7f5 100644
--- a/library/pkwrite.c
+++ b/library/pkwrite.c
@@ -48,6 +48,7 @@
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 #include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
 #endif
 #if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
@@ -181,7 +182,8 @@
         }
         else
         {
-            memmove( *p - len, start, len );
+            *p -= len;
+            memmove( *p, start, len );
         }
     }
     else
@@ -196,16 +198,13 @@
     int ret;
     unsigned char *c;
     size_t len = 0, par_len = 0, oid_len;
+    mbedtls_pk_type_t pk_type;
     const char *oid;
 
     c = buf + size;
 
     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) );
 
-    if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_OPAQUE )
-    {
-        return( (int) len );
-    }
     if( c - buf < 1 )
         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
 
@@ -220,18 +219,51 @@
     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) );
 
-    if( ( ret = mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_get_type( key ),
-                                       &oid, &oid_len ) ) != 0 )
-    {
-        return( ret );
-    }
-
+    pk_type = mbedtls_pk_get_type( key );
 #if defined(MBEDTLS_ECP_C)
-    if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
+    if( pk_type == MBEDTLS_PK_ECKEY )
     {
         MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) );
     }
 #endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if( pk_type == MBEDTLS_PK_OPAQUE )
+    {
+        psa_status_t status;
+        psa_key_type_t key_type;
+        psa_key_handle_t handle;
+        psa_ecc_curve_t curve;
+
+        handle = *((psa_key_handle_t*) key->pk_ctx );
+
+        status = psa_get_key_information( handle, &key_type,
+                                          NULL /* bitsize not needed */ );
+        if( status != PSA_SUCCESS )
+            return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
+
+        curve = PSA_KEY_TYPE_GET_CURVE( key_type );
+        if( curve == 0 )
+            return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
+
+        ret = mbedtls_psa_get_ecc_oid_from_id( curve, &oid, &oid_len );
+        if( ret != 0 )
+            return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
+
+        /* Write EC algorithm parameters; that's akin
+         * to pk_write_ec_param() above. */
+        MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_oid( &c, buf,
+                                                               oid, oid_len ) );
+
+        /* The rest of the function works as for legacy EC contexts. */
+        pk_type = MBEDTLS_PK_ECKEY;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    if( ( ret = mbedtls_oid_get_oid_by_pk_alg( pk_type, &oid,
+                                               &oid_len ) ) != 0 )
+    {
+        return( ret );
+    }
 
     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len,
                                                         par_len ) );
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 0cfeb09..1fbf086 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -50,10 +50,19 @@
 
 #include <string.h>
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "mbedtls/psa_util.h"
+#include "psa/crypto.h"
+#endif
+
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 #include "mbedtls/oid.h"
 #endif
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "mbedtls/psa_util.h"
+#endif
+
 static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl );
 static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl );
 
@@ -490,6 +499,76 @@
 #endif /* MBEDTLS_SSL_PROTO_TLS1) || MBEDTLS_SSL_PROTO_TLS1_1 */
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+static int tls_prf_generic( mbedtls_md_type_t md_type,
+                            const unsigned char *secret, size_t slen,
+                            const char *label,
+                            const unsigned char *random, size_t rlen,
+                            unsigned char *dstbuf, size_t dlen )
+{
+    psa_status_t status;
+    psa_algorithm_t alg;
+    psa_key_policy_t policy;
+    psa_key_handle_t master_slot;
+    psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
+
+    if( ( status = psa_allocate_key( &master_slot ) ) != PSA_SUCCESS )
+        return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+
+    if( md_type == MBEDTLS_MD_SHA384 )
+        alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384);
+    else
+        alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256);
+
+    policy = psa_key_policy_init();
+    psa_key_policy_set_usage( &policy,
+                              PSA_KEY_USAGE_DERIVE,
+                              alg );
+    status = psa_set_key_policy( master_slot, &policy );
+    if( status != PSA_SUCCESS )
+        return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+
+    status = psa_import_key( master_slot, PSA_KEY_TYPE_DERIVE, secret, slen );
+    if( status != PSA_SUCCESS )
+        return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+
+    status = psa_key_derivation( &generator,
+                                 master_slot, alg,
+                                 random, rlen,
+                                 (unsigned char const *) label,
+                                 (size_t) strlen( label ),
+                                 dlen );
+    if( status != PSA_SUCCESS )
+    {
+        psa_generator_abort( &generator );
+        psa_destroy_key( master_slot );
+        return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+    }
+
+    status = psa_generator_read( &generator, dstbuf, dlen );
+    if( status != PSA_SUCCESS )
+    {
+        psa_generator_abort( &generator );
+        psa_destroy_key( master_slot );
+        return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+    }
+
+    status = psa_generator_abort( &generator );
+    if( status != PSA_SUCCESS )
+    {
+        psa_destroy_key( master_slot );
+        return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+    }
+
+    status = psa_destroy_key( master_slot );
+    if( status != PSA_SUCCESS )
+        return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+
+    return( 0 );
+}
+
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+
 static int tls_prf_generic( mbedtls_md_type_t md_type,
                             const unsigned char *secret, size_t slen,
                             const char *label,
@@ -552,7 +631,7 @@
 
     return( 0 );
 }
-
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 #if defined(MBEDTLS_SHA256_C)
 static int tls_prf_sha256( const unsigned char *secret, size_t slen,
                            const char *label,
@@ -10113,6 +10192,70 @@
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
     defined(MBEDTLS_SSL_PROTO_TLS1_2)
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
+                                            unsigned char *hash, size_t *hashlen,
+                                            unsigned char *data, size_t data_len,
+                                            mbedtls_md_type_t md_alg )
+{
+    psa_status_t status;
+    psa_hash_operation_t hash_operation;
+    psa_algorithm_t hash_alg = mbedtls_psa_translate_md( md_alg );
+
+    MBEDTLS_SSL_DEBUG_MSG( 1, ( "Perform PSA-based computation of digest of ServerKeyExchange" ) );
+
+    if( ( status = psa_hash_setup( &hash_operation,
+                                   hash_alg ) ) != PSA_SUCCESS )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_setup", status );
+        goto exit;
+    }
+
+    if( ( status = psa_hash_update( &hash_operation, ssl->handshake->randbytes,
+                                    64 ) ) != PSA_SUCCESS )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_update", status );
+        goto exit;
+    }
+
+    if( ( status = psa_hash_update( &hash_operation,
+                                    data, data_len ) ) != PSA_SUCCESS )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_update", status );
+        goto exit;
+    }
+
+    if( ( status = psa_hash_finish( &hash_operation, hash, MBEDTLS_MD_MAX_SIZE,
+                                    hashlen ) ) != PSA_SUCCESS )
+    {
+         MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_finish", status );
+         goto exit;
+    }
+
+exit:
+    if( status != PSA_SUCCESS )
+    {
+        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                        MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
+        switch( status )
+        {
+            case PSA_ERROR_NOT_SUPPORTED:
+                return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE );
+            case PSA_ERROR_BAD_STATE: /* Intentional fallthrough */
+            case PSA_ERROR_BUFFER_TOO_SMALL:
+                return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
+            case PSA_ERROR_INSUFFICIENT_MEMORY:
+                return( MBEDTLS_ERR_MD_ALLOC_FAILED );
+            default:
+                return( MBEDTLS_ERR_MD_HW_ACCEL_FAILED );
+        }
+    }
+    return( 0 );
+}
+
+#else
+
 int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
                                             unsigned char *hash, size_t *hashlen,
                                             unsigned char *data, size_t data_len,
@@ -10123,6 +10266,8 @@
     const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
     *hashlen = mbedtls_md_get_size( md_info );
 
+    MBEDTLS_SSL_DEBUG_MSG( 1, ( "Perform mbedtls-based computation of digest of ServerKeyExchange" ) );
+
     mbedtls_md_init( &ctx );
 
     /*
@@ -10167,6 +10312,8 @@
 
     return( ret );
 }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
 #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
           MBEDTLS_SSL_PROTO_TLS1_2 */
 
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 42ffa10..bcf3c14 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -769,6 +769,7 @@
                 -C "Failed to setup PSA-based cipher context"\
                 -S "Failed to setup PSA-based cipher context"\
                 -s "Protocol is TLSv1.2" \
+                -c "Perform PSA-based computation of digest of ServerKeyExchange" \
                 -S "error" \
                 -C "error"
 }
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index 120c171..e469318 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -778,44 +778,65 @@
 void pk_psa_sign(  )
 {
     mbedtls_pk_context pk;
-    psa_key_handle_t key;
-    unsigned char hash[50], sig[100], pkey[100];
-    size_t sig_len, klen = 0;
+    unsigned char hash[50], sig[100], pkey_legacy[100], pkey_psa[100];
+    unsigned char *pkey_legacy_start, *pkey_psa_start;
+    size_t sig_len, klen_legacy, klen_psa;
+    int ret;
+    psa_key_handle_t handle;
 
     /*
      * This tests making signatures with a wrapped PSA key:
-     * - generate a fresh PSA key
+     * - generate a fresh ECP legacy PK context
      * - wrap it in a PK context and make a signature this way
      * - extract the public key
      * - parse it to a PK context and verify the signature this way
      */
 
+    /* Create legacy EC public/private key in PK context. */
     mbedtls_pk_init( &pk );
+    TEST_ASSERT( mbedtls_pk_setup( &pk,
+                      mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == 0 );
+    TEST_ASSERT( mbedtls_ecp_gen_key( MBEDTLS_ECP_DP_SECP256R1,
+                                      (mbedtls_ecp_keypair*) pk.pk_ctx,
+                                      rnd_std_rand, NULL ) == 0 );
+
+    /* Export underlying public key for re-importing in a legacy context. */
+    ret = mbedtls_pk_write_pubkey_der( &pk, pkey_legacy,
+                                       sizeof( pkey_legacy ) );
+    TEST_ASSERT( ret >= 0 );
+    klen_legacy = (size_t) ret;
+    /* mbedtls_pk_write_pubkey_der() writes backwards in the data buffer. */
+    pkey_legacy_start = pkey_legacy + sizeof( pkey_legacy ) - klen_legacy;
+
+    /* Turn PK context into an opaque one. */
+    TEST_ASSERT( psa_allocate_key( &handle ) == PSA_SUCCESS );
+    TEST_ASSERT( mbedtls_pk_wrap_as_opaque( &pk, &handle,
+                                            PSA_ALG_SHA_256 ) == 0 );
 
     memset( hash, 0x2a, sizeof hash );
     memset( sig, 0, sizeof sig );
-    memset( pkey, 0, sizeof pkey );
-
-    key = pk_psa_genkey();
-    TEST_ASSERT( key != 0 );
-
-    TEST_ASSERT( mbedtls_pk_setup_opaque( &pk, key ) == 0 );
 
     TEST_ASSERT( mbedtls_pk_sign( &pk, MBEDTLS_MD_SHA256,
                  hash, sizeof hash, sig, &sig_len,
                  NULL, NULL ) == 0 );
 
-    mbedtls_pk_free( &pk );
+    /* Export underlying public key for re-importing in a psa context. */
+    ret = mbedtls_pk_write_pubkey_der( &pk, pkey_psa,
+                                       sizeof( pkey_psa ) );
+    TEST_ASSERT( ret >= 0 );
+    klen_psa = (size_t) ret;
+    /* mbedtls_pk_write_pubkey_der() writes backwards in the data buffer. */
+    pkey_psa_start = pkey_psa + sizeof( pkey_psa ) - klen_psa;
 
-    TEST_ASSERT( PSA_SUCCESS == psa_export_public_key(
-                                key, pkey, sizeof( pkey ), &klen ) );
-    TEST_ASSERT( PSA_SUCCESS == psa_destroy_key( key ) );
+    TEST_ASSERT( klen_psa == klen_legacy );
+    TEST_ASSERT( memcmp( pkey_psa_start, pkey_legacy_start, klen_psa ) == 0 );
+
+    mbedtls_pk_free( &pk );
+    TEST_ASSERT( PSA_SUCCESS == psa_destroy_key( handle ) );
 
     mbedtls_pk_init( &pk );
-
-    TEST_ASSERT( mbedtls_pk_parse_public_key( &pk, pkey, klen ) == 0 );
-
-
+    TEST_ASSERT( mbedtls_pk_parse_public_key( &pk, pkey_legacy_start,
+                                              klen_legacy ) == 0 );
     TEST_ASSERT( mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256,
                             hash, sizeof hash, sig, sig_len ) == 0 );