diff --git a/include/mbedtls/psa_util.h b/include/mbedtls/psa_util.h index a78c1a96c..3684e9835 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 @@ static inline psa_algorithm_t mbedtls_psa_translate_md( mbedtls_md_type_t md_alg /* 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/library/pkwrite.c b/library/pkwrite.c index 11a2a6145..ab4f7f537 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 @@ int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, } else { - memmove( *p - len, start, len ); + *p -= len; + memmove( *p, start, len ); } } else @@ -196,16 +198,13 @@ int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, si 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 @@ int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, si 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/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function index 120c1716b..e469318bd 100644 --- a/tests/suites/test_suite_pk.function +++ b/tests/suites/test_suite_pk.function @@ -778,44 +778,65 @@ exit: 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 );