Merge pull request #4626 from SiliconLabs/arch_silabs_3399

Enable Curve448 support via the PSA API
diff --git a/ChangeLog.d/psa_curve448_key_support.txt b/ChangeLog.d/psa_curve448_key_support.txt
new file mode 100644
index 0000000..d1870ed
--- /dev/null
+++ b/ChangeLog.d/psa_curve448_key_support.txt
@@ -0,0 +1,3 @@
+Features
+   * Enable support for Curve448 via the PSA API. Contributed by
+     Archana Madhavan in #4626. Fixes #3399 and #4249.
diff --git a/include/mbedtls/config_psa.h b/include/mbedtls/config_psa.h
index f182c52..9080cd1 100644
--- a/include/mbedtls/config_psa.h
+++ b/include/mbedtls/config_psa.h
@@ -433,11 +433,6 @@
 
 #if defined(PSA_WANT_ECC_MONTGOMERY_448)
 #if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448)
-/*
- * Curve448 is not yet supported via the PSA API in Mbed TLS
- * (https://github.com/ARMmbed/mbedtls/issues/4249).
- */
-#error "Curve448 is not yet supported via the PSA API in Mbed TLS."
 #define MBEDTLS_ECP_DP_CURVE448_ENABLED
 #define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1
 #endif /* !MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448 */
@@ -710,8 +705,7 @@
 #define PSA_WANT_ECC_MONTGOMERY_255
 #endif
 
-/* Curve448 is not yet supported via the PSA API (https://github.com/ARMmbed/mbedtls/issues/4249) */
-#if 0 && defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
 #define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1
 #define PSA_WANT_ECC_MONTGOMERY_448
 #endif
diff --git a/include/psa/crypto_config.h b/include/psa/crypto_config.h
index 3f95d0e..64d8c58 100644
--- a/include/psa/crypto_config.h
+++ b/include/psa/crypto_config.h
@@ -93,12 +93,7 @@
 #define PSA_WANT_ECC_BRAINPOOL_P_R1_384         1
 #define PSA_WANT_ECC_BRAINPOOL_P_R1_512         1
 #define PSA_WANT_ECC_MONTGOMERY_255             1
-/*
- * Curve448 is not yet supported via the PSA API in Mbed TLS
- * (https://github.com/ARMmbed/mbedtls/issues/4249). Thus, do not enable it by
- * default.
- */
-//#define PSA_WANT_ECC_MONTGOMERY_448             1
+#define PSA_WANT_ECC_MONTGOMERY_448             1
 #define PSA_WANT_ECC_SECP_K1_192                1
 /*
  * SECP224K1 is buggy via the PSA API in Mbed TLS
diff --git a/library/ecp.c b/library/ecp.c
index e8df7ff..b608ff1 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -3054,6 +3054,7 @@
 }
 
 #define ECP_CURVE25519_KEY_SIZE 32
+#define ECP_CURVE448_KEY_SIZE   56
 /*
  * Read a private key.
  */
@@ -3074,12 +3075,12 @@
     if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
     {
         /*
-         * If it is Curve25519 curve then mask the key as mandated by RFC7748
+         * Mask the key as mandated by RFC7748 for Curve25519 and Curve448.
          */
         if( grp_id == MBEDTLS_ECP_DP_CURVE25519 )
         {
             if( buflen != ECP_CURVE25519_KEY_SIZE )
-                return MBEDTLS_ERR_ECP_INVALID_KEY;
+                return( MBEDTLS_ERR_ECP_INVALID_KEY );
 
             MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary_le( &key->d, buf, buflen ) );
 
@@ -3100,8 +3101,23 @@
                                          ECP_CURVE25519_KEY_SIZE * 8 - 2, 1 )
                     );
         }
-        else
-            ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+        else if( grp_id == MBEDTLS_ECP_DP_CURVE448 )
+        {
+            if( buflen != ECP_CURVE448_KEY_SIZE )
+                return( MBEDTLS_ERR_ECP_INVALID_KEY );
+
+            MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary_le( &key->d, buf, buflen ) );
+
+            /* Set the two least significant bits to 0 */
+            MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 0, 0 ) );
+            MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 1, 0 ) );
+
+            /* Set the most significant bit to 1 */
+            MBEDTLS_MPI_CHK(
+                    mbedtls_mpi_set_bit( &key->d,
+                                         ECP_CURVE448_KEY_SIZE * 8 - 1, 1 )
+                    );
+        }
     }
 
 #endif
@@ -3139,14 +3155,16 @@
         if( key->grp.id == MBEDTLS_ECP_DP_CURVE25519 )
         {
             if( buflen < ECP_CURVE25519_KEY_SIZE )
-                return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+                return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
 
-            MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary_le( &key->d, buf, buflen ) );
         }
-        else
-            ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+        else if( key->grp.id == MBEDTLS_ECP_DP_CURVE448 )
+        {
+            if( buflen < ECP_CURVE448_KEY_SIZE )
+                return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
+        }
+        MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary_le( &key->d, buf, buflen ) );
     }
-
 #endif
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
     if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS )
diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data
index ceafc79..0c30e4a 100644
--- a/tests/suites/test_suite_ecp.data
+++ b/tests/suites/test_suite_ecp.data
@@ -205,14 +205,22 @@
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 ecp_write_binary:MBEDTLS_ECP_DP_SECP192R1:"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"93112b28345b7d1d7799611e49bea9d8290cb2d7afe1f9f3":"01":MBEDTLS_ECP_PF_COMPRESSED:"0348d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":25:0
 
-ECP write binary #10 (Montgomery, buffer just fits)
+ECP write binary #10 (Montgomery curve25519, buffer just fits)
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
 ecp_write_binary:MBEDTLS_ECP_DP_CURVE25519:"11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff":"0":"1":MBEDTLS_ECP_PF_COMPRESSED:"ffeeddccbbaa00998877665544332211ffeeddccbbaa00998877665544332211":32:0
 
-ECP write binary #11 (Montgomery, buffer too small)
+ECP write binary #11 (Montgomery curve25519, buffer too small)
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
 ecp_write_binary:MBEDTLS_ECP_DP_CURVE25519:"11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff":"0":"1":MBEDTLS_ECP_PF_COMPRESSED:"ffeeddccbbaa00998877665544332211ffeeddccbbaa00998877665544332211":31:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
 
+ECP write binary #12 (Montgomery curve448, buffer just fits)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_write_binary:MBEDTLS_ECP_DP_CURVE448:"3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609":"0":"1":MBEDTLS_ECP_PF_COMPRESSED:"0936f37bc6c1bd07ae3dec7ab5dc06a73ca13242fb343efc72b9d82730b445f3d4b0bd077162a46dcfec6f9b590bfcbcf520cdb029a8b73e":56:0
+
+ECP write binary #13 (Montgomery curve448, buffer too small)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_write_binary:MBEDTLS_ECP_DP_CURVE448:"3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609":"0":"1":MBEDTLS_ECP_PF_COMPRESSED:"0936f37bc6c1bd07ae3dec7ab5dc06a73ca13242fb343efc72b9d82730b445f3d4b0bd077162a46dcfec6f9b590bfcbcf520cdb029a8b73e":55:MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL
+
 ECP read binary #1 (zero, invalid ilen)
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"0000":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -261,6 +269,22 @@
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
 ecp_read_binary:MBEDTLS_ECP_DP_CURVE25519:"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a00":"6a4e9baa8ea9a4ebf41a38260d3abf0d5af73eb4dc7d8b7454a7308909f02085":"0":"1":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
+ECP read binary #13 (Curve448, OK)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_CURVE448:"9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b":"6b7298a5c0d8c29a1dab27f1a6826300917389449741a974f5bac9d98dc298d46555bce8bae89eeed400584bb046cf75579f51d125498f9a":"0":"1":0
+
+ECP read binary #14 (Curve448, too long)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_CURVE448:"9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b00":"6b7298a5c0d8c29a1dab27f1a6826300917389449741a974f5bac9d98dc298d46555bce8bae89eeed400584bb046cf75579f51d125498f9a":"0":"1":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #15 (Curve448, too short)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_CURVE448:"8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b":"6b7298a5c0d8c29a1dab27f1a6826300917389449741a974f5bac9d98dc298d46555bce8bae89eeed400584bb046cf75579f51d125498f9a":"0":"1":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #16 (Curve448, non-canonical)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_CURVE448:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":"0":"1":0
+
 ECP tls read point #1 (zero, invalid length byte)
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 mbedtls_ecp_tls_read_point:MBEDTLS_ECP_DP_SECP192R1:"0200":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -326,34 +350,66 @@
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 mbedtls_ecp_check_privkey:MBEDTLS_ECP_DP_SECP192R1:"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831":MBEDTLS_ERR_ECP_INVALID_KEY
 
-ECP check privkey #5 (montgomery, too big)
+ECP check privkey #5 (montgomery curve25519, too big)
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
 mbedtls_ecp_check_privkey:MBEDTLS_ECP_DP_CURVE25519:"C000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_ECP_INVALID_KEY
 
-ECP check privkey #6 (montgomery, not big enough)
+ECP check privkey #6 (montgomery curve25519, not big enough)
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
 mbedtls_ecp_check_privkey:MBEDTLS_ECP_DP_CURVE25519:"3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0":MBEDTLS_ERR_ECP_INVALID_KEY
 
-ECP check privkey #7 (montgomery, msb OK)
+ECP check privkey #7 (montgomery curve25519, msb OK)
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
 mbedtls_ecp_check_privkey:MBEDTLS_ECP_DP_CURVE25519:"4000000000000000000000000000000000000000000000000000000000000000":0
 
-ECP check privkey #8 (montgomery, bit 0 set)
+ECP check privkey #8 (montgomery curve25519, msb not OK)
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+mbedtls_ecp_check_privkey:MBEDTLS_ECP_DP_CURVE25519:"0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8":MBEDTLS_ERR_ECP_INVALID_KEY
+
+ECP check privkey #9 (montgomery curve25519, bit 0 set)
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
 mbedtls_ecp_check_privkey:MBEDTLS_ECP_DP_CURVE25519:"4000000000000000000000000000000000000000000000000000000000000001":MBEDTLS_ERR_ECP_INVALID_KEY
 
-ECP check privkey #9 (montgomery, bit 1 set)
+ECP check privkey #10 (montgomery curve25519, bit 1 set)
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
 mbedtls_ecp_check_privkey:MBEDTLS_ECP_DP_CURVE25519:"4000000000000000000000000000000000000000000000000000000000000002":MBEDTLS_ERR_ECP_INVALID_KEY
 
-ECP check privkey #10 (montgomery, bit 2 set)
+ECP check privkey #11 (montgomery curve25519, bit 2 set)
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
 mbedtls_ecp_check_privkey:MBEDTLS_ECP_DP_CURVE25519:"4000000000000000000000000000000000000000000000000000000000000004":MBEDTLS_ERR_ECP_INVALID_KEY
 
-ECP check privkey #11 (montgomery, OK)
+ECP check privkey #12 (montgomery curve25519, OK)
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
 mbedtls_ecp_check_privkey:MBEDTLS_ECP_DP_CURVE25519:"7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8":0
 
+ECP check privkey #13 (montgomery curve448, too big)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+mbedtls_ecp_check_privkey:MBEDTLS_ECP_DP_CURVE448:"800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_ECP_INVALID_KEY
+
+ECP check privkey #14 (montgomery curve448, not big enough)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+mbedtls_ecp_check_privkey:MBEDTLS_ECP_DP_CURVE448:"80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_ECP_INVALID_KEY
+
+ECP check privkey #15 (montgomery curve448, msb OK)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+mbedtls_ecp_check_privkey:MBEDTLS_ECP_DP_CURVE448:"8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":0
+
+ECP check privkey #15 (montgomery curve448, msb not OK)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+mbedtls_ecp_check_privkey:MBEDTLS_ECP_DP_CURVE448:"0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC":MBEDTLS_ERR_ECP_INVALID_KEY
+
+ECP check privkey #17 (montgomery curve448, bit 0 set)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+mbedtls_ecp_check_privkey:MBEDTLS_ECP_DP_CURVE448:"8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001":MBEDTLS_ERR_ECP_INVALID_KEY
+
+ECP check privkey #18 (montgomery curve448, bit 1 set)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+mbedtls_ecp_check_privkey:MBEDTLS_ECP_DP_CURVE448:"8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002":MBEDTLS_ERR_ECP_INVALID_KEY
+
+ECP check privkey #19 (montgomery curve448, OK)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+mbedtls_ecp_check_privkey:MBEDTLS_ECP_DP_CURVE448:"8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC":0
+
 ECP check public-private #1 (OK)
 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
 mbedtls_ecp_check_pub_priv:MBEDTLS_ECP_DP_SECP256R1:"37cc56d976091e5a723ec7592dff206eee7cf9069174d0ad14b5f76822596292":"4ee500d82311ffea2fd2345d5d16bd8a88c26b770d55cd8a2a0efa01c8b4edff":MBEDTLS_ECP_DP_SECP256R1:"00f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":"37cc56d976091e5a723ec7592dff206eee7cf9069174d0ad14b5f76822596292":"4ee500d82311ffea2fd2345d5d16bd8a88c26b770d55cd8a2a0efa01c8b4edff":0
@@ -389,6 +445,10 @@
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
 mbedtls_ecp_gen_keypair:MBEDTLS_ECP_DP_CURVE25519
 
+ECP gen keypair [#3]
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+mbedtls_ecp_gen_keypair:MBEDTLS_ECP_DP_CURVE448
+
 ECP gen keypair wrapper
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 mbedtls_ecp_gen_key:MBEDTLS_ECP_DP_SECP192R1
@@ -481,17 +541,46 @@
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
 mbedtls_ecp_read_key:MBEDTLS_ECP_DP_CURVE25519:"F0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F":MBEDTLS_ERR_ECP_INVALID_KEY:0
 
-ECP read key #14 (Curve448, not supported)
+ECP read key #14 (Curve448, most significant bit unset)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+mbedtls_ecp_read_key:MBEDTLS_ECP_DP_CURVE448:"FCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F":0:0
+
+ECP read key #15 (Curve448, msb OK)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+mbedtls_ecp_read_key:MBEDTLS_ECP_DP_CURVE448:"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080":0:1
+
+ECP read key #16 (Curve448, bit 0 set)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+mbedtls_ecp_read_key:MBEDTLS_ECP_DP_CURVE448:"0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080":0:0
+
+ECP read key #17 (Curve448, bit 1 set)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+mbedtls_ecp_read_key:MBEDTLS_ECP_DP_CURVE448:"0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080":0:0
+
+ECP read key #18 (Curve448, OK)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+mbedtls_ecp_read_key:MBEDTLS_ECP_DP_CURVE448:"FCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F":0:1
+
+ECP read key #19 (Curve448, too long)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+mbedtls_ecp_read_key:MBEDTLS_ECP_DP_CURVE448:"FCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F":MBEDTLS_ERR_ECP_INVALID_KEY:0
+
+ECP read key #20 (Curve448, not long enough)
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+mbedtls_ecp_read_key:MBEDTLS_ECP_DP_CURVE448:"FCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F":MBEDTLS_ERR_ECP_INVALID_KEY:0
+
+ECP read key #21 (Curve448, not supported)
+depends_on:!MBEDTLS_ECP_DP_CURVE448_ENABLED
 mbedtls_ecp_read_key:MBEDTLS_ECP_DP_CURVE448:"FCFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE:0
 
-ECP read key #15 (Curve25519, not supported)
+ECP read key #22 (Curve25519, not supported)
 depends_on:!MBEDTLS_ECP_DP_CURVE25519_ENABLED
 mbedtls_ecp_read_key:MBEDTLS_ECP_DP_CURVE25519:"F8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE:0
 
-ECP read key #15 (invalid curve)
+ECP read key #23 (invalid curve)
 mbedtls_ecp_read_key:INT_MAX:"F8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE:0
 
-ECP read key #16 (Curve25519 RFC, OK)
+ECP read key #24 (Curve25519 RFC, OK)
 depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
 mbedtls_ecp_read_key:MBEDTLS_ECP_DP_CURVE25519:"70076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c6a":0:1
 
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index 8671e37..6eca2f7 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -209,6 +209,22 @@
 depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_MONTGOMERY_255
 import_export_public_key:"70076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c6a":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):PSA_ALG_ECDH:0:PSA_SUCCESS:"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"
 
+PSA import/export EC curve448 key pair: good (already properly masked, key from RFC 7748 6.2 Alice))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_MONTGOMERY_448
+import_export:"988f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a59872eb":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDH:448:0:PSA_SUCCESS:1
+
+PSA import/export EC curve448 key pair: unmasked input (check export-import-export yields properly masked output, key from RFC 7748 6.2 Alice))
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_MONTGOMERY_448
+import_export:"9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDH:448:0:PSA_SUCCESS:0
+
+PSA import/export-public EC curve448: accept masked input (key from RFC 7748 6.2 Alice)
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_MONTGOMERY_448
+import_export_public_key:"988f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a59872eb":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):PSA_ALG_ECDH:0:PSA_SUCCESS:"9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0"
+
+PSA import/export-public EC curve448: accept unmasked input (key from RFC 7748 6.2 Alice)
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_MONTGOMERY_448
+import_export_public_key:"9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):PSA_ALG_ECDH:0:PSA_SUCCESS:"9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0"
+
 PSA import/export-public: cannot export-public a symmetric key
 depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C
 import_export_public_key:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:PSA_ALG_CBC_NO_PADDING:0:PSA_ERROR_INVALID_ARGUMENT:"2b7e151628aed2a6abf7158809cf4f3c"
@@ -229,6 +245,10 @@
 depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_MONTGOMERY_255
 import_export:"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_MONTGOMERY):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDH:255:0:PSA_SUCCESS:1
 
+PSA import/export curve448 Public Key: good (key from RFC 7748 6.2 Alice)
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_MONTGOMERY_448
+import_export:"9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_MONTGOMERY):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDH:448:0:PSA_SUCCESS:0
+
 PSA import/export AES key: policy forbids export
 depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 import_export:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:128:0:PSA_ERROR_NOT_PERMITTED:1
@@ -3596,6 +3616,14 @@
 depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_MONTGOMERY_255
 raw_key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):"5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb":"8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a":"4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742"
 
+PSA raw key agreement: X448 (RFC 7748: Alice)
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_MONTGOMERY_448
+raw_key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):"9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b":"3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609":"07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d"
+
+PSA raw key agreement: X448 (RFC 7748: Bob)
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_MONTGOMERY_448
+raw_key_agreement:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):"1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d":"9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0":"07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d"
+
 PSA key agreement: ECDH SECP256R1 (RFC 5903) + HKDF-SHA-256: capacity=8160
 depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 key_agreement_capacity:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":8160
@@ -3755,6 +3783,10 @@
 depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_MONTGOMERY_255
 generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):255:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_SUCCESS:0
 
+PSA generate key: ECC, Curve448, good
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_MONTGOMERY_448
+generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):448:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_SUCCESS:0
+
 PSA generate key: RSA, default e
 generate_key_rsa:512:"":PSA_SUCCESS