diff --git a/ChangeLog.d/psa_curve25519_public_key_import.txt b/ChangeLog.d/psa_curve25519_public_key_import.txt new file mode 100644 index 000000000..2ea11e2c8 --- /dev/null +++ b/ChangeLog.d/psa_curve25519_public_key_import.txt @@ -0,0 +1,3 @@ +Bugfix + * PSA key import will now correctly import a Curve25519/Curve448 public key + instead of erroring out. Contributed by Steven Cooreman in #3492. diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 6e9d25961..056e67796 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -732,19 +732,34 @@ static psa_status_t psa_load_ecp_representation( const uint8_t *buffer, mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE; psa_status_t status; mbedtls_ecp_keypair *ecp = NULL; - size_t curve_size = size; + size_t curve_size; if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ) { - /* A public key is represented as: - * - The byte 0x04; - * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; - * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. - * So its data length is 2m+1 where n is the key size in bits. - */ - if( ( size & 1 ) == 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - curve_size = size / 2; + if( PSA_KEY_TYPE_ECC_GET_FAMILY( type ) == PSA_ECC_FAMILY_MONTGOMERY ) + { + /* A Montgomery public key is represented as its raw + * compressed public point. + */ + curve_size = size; + } + else + { + /* A Weierstrass public key is represented as: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. + * So its data length is 2m+1 where n is the key size in bits. + */ + if( ( size & 1 ) == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + curve_size = size / 2; + } + } + else + { + /* Private keys are represented as the raw private value */ + curve_size = size; } /* Allocate and initialize a key representation. */ diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 6a2859124..d1855fdb5 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -252,6 +252,10 @@ PSA import/export EC brainpoolP256r1 public key: good depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP256R1_ENABLED import_export:"04768c8cae4abca6306db0ed81b0c4a6215c378066ec6d616c146e13f1c7df809b96ab6911c27d8a02339f0926840e55236d3d1efbe2669d090e4c4c660fada91d":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_BRAINPOOL_P_R1):PSA_KEY_USAGE_EXPORT:PSA_ALG_ECDSA_ANY:256:0:PSA_SUCCESS:1 +PSA import/export curve25519 public key: good +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_CURVE25519_ENABLED +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 AES key: policy forbids export depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR 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 diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 4576b8bb4..f4b9a8f67 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -961,14 +961,23 @@ static int exported_key_sanity_check( psa_key_type_t type, size_t bits, #if defined(MBEDTLS_ECP_C) if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( type ) ) { - /* The representation of an ECC public key is: - * - The byte 0x04; - * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; - * - `y_P` as a `ceiling(m/8)`-byte string, big-endian; - * - where m is the bit size associated with the curve. - */ - TEST_EQUAL( p + 1 + 2 * PSA_BITS_TO_BYTES( bits ), end ); - TEST_EQUAL( p[0], 4 ); + if( PSA_KEY_TYPE_ECC_GET_FAMILY( type ) == PSA_ECC_FAMILY_MONTGOMERY ) + { + /* The representation of an ECC Montgomery public key is + * the raw compressed point */ + TEST_EQUAL( p + PSA_BITS_TO_BYTES( bits ), end ); + } + else + { + /* The representation of an ECC Weierstrass public key is: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian; + * - where m is the bit size associated with the curve. + */ + TEST_EQUAL( p + 1 + 2 * PSA_BITS_TO_BYTES( bits ), end ); + TEST_EQUAL( p[0], 4 ); + } } else #endif /* MBEDTLS_ECP_C */