mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-07-29 11:41:15 +03:00
ECC import: more useful choice of INVALID_ARGUMENT vs NOT_SUPPORTED
Attempting to create an ECC key with a curve specification that is not valid can plausibly fail with PSA_ERROR_INVALID_ARGUMENT ("this is not a curve specification at all") or PSA_ERROR_NOT_SUPPORTED ("this may be a curve specification, but not one I support"). The choice of error is somewhat subjective. Before this commit, due to happenstance in the implementation, an attempt to use a curve that is declared in the PSA API but not implemented in Mbed TLS returned PSA_ERROR_INVALID_ARGUMENT, whereas an attempt to use a curve that Mbed TLS supports but for which support was disabled at compile-time returned PSA_ERROR_NOT_SUPPORTED. This inconsistency made it difficult to write negative tests that could work whether the curve is implemented via Mbed TLS code or via a driver. After this commit, any attempt to use parameters that are not recognized fails with NOT_SUPPORTED, whether a curve with the specified size might plausibly exist or not, because "might plausibly exist" is not something Mbed TLS can determine. To keep returning INVALID_ARGUMENT when importing an ECC key with an explicit "bits" attribute that is inconsistent with the size of the key material, this commit changes the way mbedtls_ecc_group_of_psa() works: it now works on a size in bits rather than bytes, with an extra flag indicating whether the bit-size must be exact or not. Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
@ -413,71 +413,71 @@ static inline int psa_key_slot_is_external( const psa_key_slot_t *slot )
|
||||
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \
|
||||
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
|
||||
mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_family_t curve,
|
||||
size_t byte_length )
|
||||
size_t bits,
|
||||
int bits_is_sloppy )
|
||||
{
|
||||
switch( curve )
|
||||
{
|
||||
case PSA_ECC_FAMILY_SECP_R1:
|
||||
switch( byte_length )
|
||||
switch( bits )
|
||||
{
|
||||
case PSA_BITS_TO_BYTES( 192 ):
|
||||
case 192:
|
||||
return( MBEDTLS_ECP_DP_SECP192R1 );
|
||||
case PSA_BITS_TO_BYTES( 224 ):
|
||||
case 224:
|
||||
return( MBEDTLS_ECP_DP_SECP224R1 );
|
||||
case PSA_BITS_TO_BYTES( 256 ):
|
||||
case 256:
|
||||
return( MBEDTLS_ECP_DP_SECP256R1 );
|
||||
case PSA_BITS_TO_BYTES( 384 ):
|
||||
case 384:
|
||||
return( MBEDTLS_ECP_DP_SECP384R1 );
|
||||
case PSA_BITS_TO_BYTES( 521 ):
|
||||
case 521:
|
||||
return( MBEDTLS_ECP_DP_SECP521R1 );
|
||||
default:
|
||||
return( MBEDTLS_ECP_DP_NONE );
|
||||
case 528:
|
||||
if( bits_is_sloppy )
|
||||
return( MBEDTLS_ECP_DP_SECP521R1 );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case PSA_ECC_FAMILY_BRAINPOOL_P_R1:
|
||||
switch( byte_length )
|
||||
switch( bits )
|
||||
{
|
||||
case PSA_BITS_TO_BYTES( 256 ):
|
||||
case 256:
|
||||
return( MBEDTLS_ECP_DP_BP256R1 );
|
||||
case PSA_BITS_TO_BYTES( 384 ):
|
||||
case 384:
|
||||
return( MBEDTLS_ECP_DP_BP384R1 );
|
||||
case PSA_BITS_TO_BYTES( 512 ):
|
||||
case 512:
|
||||
return( MBEDTLS_ECP_DP_BP512R1 );
|
||||
default:
|
||||
return( MBEDTLS_ECP_DP_NONE );
|
||||
}
|
||||
break;
|
||||
|
||||
case PSA_ECC_FAMILY_MONTGOMERY:
|
||||
switch( byte_length )
|
||||
switch( bits )
|
||||
{
|
||||
case PSA_BITS_TO_BYTES( 255 ):
|
||||
case 255:
|
||||
return( MBEDTLS_ECP_DP_CURVE25519 );
|
||||
case PSA_BITS_TO_BYTES( 448 ):
|
||||
case 256:
|
||||
if( bits_is_sloppy )
|
||||
return( MBEDTLS_ECP_DP_CURVE25519 );
|
||||
break;
|
||||
case 448:
|
||||
return( MBEDTLS_ECP_DP_CURVE448 );
|
||||
default:
|
||||
return( MBEDTLS_ECP_DP_NONE );
|
||||
}
|
||||
break;
|
||||
|
||||
case PSA_ECC_FAMILY_SECP_K1:
|
||||
switch( byte_length )
|
||||
switch( bits )
|
||||
{
|
||||
case PSA_BITS_TO_BYTES( 192 ):
|
||||
case 192:
|
||||
return( MBEDTLS_ECP_DP_SECP192K1 );
|
||||
case PSA_BITS_TO_BYTES( 224 ):
|
||||
case 224:
|
||||
return( MBEDTLS_ECP_DP_SECP224K1 );
|
||||
case PSA_BITS_TO_BYTES( 256 ):
|
||||
case 256:
|
||||
return( MBEDTLS_ECP_DP_SECP256K1 );
|
||||
default:
|
||||
return( MBEDTLS_ECP_DP_NONE );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return( MBEDTLS_ECP_DP_NONE );
|
||||
}
|
||||
|
||||
return( MBEDTLS_ECP_DP_NONE );
|
||||
}
|
||||
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
|
||||
* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) ||
|
||||
@ -3472,6 +3472,7 @@ psa_status_t psa_sign_hash( mbedtls_svc_key_id_t key,
|
||||
{
|
||||
mbedtls_ecp_keypair *ecp = NULL;
|
||||
status = mbedtls_psa_ecp_load_representation( slot->attr.type,
|
||||
slot->attr.bits,
|
||||
slot->key.data,
|
||||
slot->key.bytes,
|
||||
&ecp );
|
||||
@ -3575,6 +3576,7 @@ psa_status_t psa_verify_hash( mbedtls_svc_key_id_t key,
|
||||
{
|
||||
mbedtls_ecp_keypair *ecp = NULL;
|
||||
status = mbedtls_psa_ecp_load_representation( slot->attr.type,
|
||||
slot->attr.bits,
|
||||
slot->key.data,
|
||||
slot->key.bytes,
|
||||
&ecp );
|
||||
@ -5647,6 +5649,7 @@ static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key,
|
||||
|
||||
status = mbedtls_psa_ecp_load_representation(
|
||||
PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve),
|
||||
bits,
|
||||
peer_key,
|
||||
peer_key_length,
|
||||
&their_key );
|
||||
@ -5703,6 +5706,7 @@ static psa_status_t psa_key_agreement_raw_internal( psa_algorithm_t alg,
|
||||
mbedtls_ecp_keypair *ecp = NULL;
|
||||
psa_status_t status = mbedtls_psa_ecp_load_representation(
|
||||
private_key->attr.type,
|
||||
private_key->attr.bits,
|
||||
private_key->key.data,
|
||||
private_key->key.bytes,
|
||||
&ecp );
|
||||
@ -6115,7 +6119,7 @@ static psa_status_t psa_generate_key_internal(
|
||||
{
|
||||
psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( type );
|
||||
mbedtls_ecp_group_id grp_id =
|
||||
mbedtls_ecc_group_of_psa( curve, PSA_BITS_TO_BYTES( bits ) );
|
||||
mbedtls_ecc_group_of_psa( curve, bits, 0 );
|
||||
const mbedtls_ecp_curve_info *curve_info =
|
||||
mbedtls_ecp_curve_info_from_grp_id( grp_id );
|
||||
mbedtls_ecp_keypair ecp;
|
||||
|
@ -56,13 +56,15 @@
|
||||
defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) || \
|
||||
defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
|
||||
psa_status_t mbedtls_psa_ecp_load_representation(
|
||||
psa_key_type_t type, const uint8_t *data, size_t data_length,
|
||||
psa_key_type_t type, size_t curve_bits,
|
||||
const uint8_t *data, size_t data_length,
|
||||
mbedtls_ecp_keypair **p_ecp )
|
||||
{
|
||||
mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
|
||||
psa_status_t status;
|
||||
mbedtls_ecp_keypair *ecp = NULL;
|
||||
size_t curve_size = data_length;
|
||||
size_t curve_bytes = data_length;
|
||||
int explicit_bits = ( curve_bits != 0 );
|
||||
|
||||
if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) &&
|
||||
PSA_KEY_TYPE_ECC_GET_FAMILY( type ) != PSA_ECC_FAMILY_MONTGOMERY )
|
||||
@ -75,7 +77,7 @@ psa_status_t mbedtls_psa_ecp_load_representation(
|
||||
*/
|
||||
if( ( data_length & 1 ) == 0 )
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
curve_size = data_length / 2;
|
||||
curve_bytes = data_length / 2;
|
||||
|
||||
/* Montgomery public keys are represented in compressed format, meaning
|
||||
* their curve_size is equal to the amount of input. */
|
||||
@ -84,6 +86,20 @@ psa_status_t mbedtls_psa_ecp_load_representation(
|
||||
* format, meaning their curve_size is equal to the amount of input. */
|
||||
}
|
||||
|
||||
if( explicit_bits )
|
||||
{
|
||||
/* With an explicit bit-size, the data must have the matching length. */
|
||||
if( curve_bytes != PSA_BITS_TO_BYTES( curve_bits ) )
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We need to infer the bit-size from the data. Since the only
|
||||
* information we have is the length in bytes, the value of curve_bits
|
||||
* at this stage is rounded up to the nearest multiple of 8. */
|
||||
curve_bits = PSA_BYTES_TO_BITS( curve_bytes );
|
||||
}
|
||||
|
||||
/* Allocate and initialize a key representation. */
|
||||
ecp = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) );
|
||||
if( ecp == NULL )
|
||||
@ -92,10 +108,16 @@ psa_status_t mbedtls_psa_ecp_load_representation(
|
||||
|
||||
/* Load the group. */
|
||||
grp_id = mbedtls_ecc_group_of_psa( PSA_KEY_TYPE_ECC_GET_FAMILY( type ),
|
||||
curve_size );
|
||||
curve_bits, !explicit_bits );
|
||||
if( grp_id == MBEDTLS_ECP_DP_NONE )
|
||||
{
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
/* We can't distinguish between a nonsensical family/size combination
|
||||
* (which would warrant PSA_ERROR_INVALID_ARGUMENT) and a
|
||||
* well-regarded curve that Mbed TLS just doesn't know about (which
|
||||
* would warrant PSA_ERROR_NOT_SUPPORTED). For uniformity with how
|
||||
* curves that Mbed TLS knows about but for which support is disabled
|
||||
* at build time, return NOT_SUPPORTED. */
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@ -163,6 +185,7 @@ static psa_status_t ecp_import_key(
|
||||
|
||||
/* Parse input */
|
||||
status = mbedtls_psa_ecp_load_representation( attributes->core.type,
|
||||
attributes->core.bits,
|
||||
data,
|
||||
data_length,
|
||||
&ecp );
|
||||
@ -251,7 +274,8 @@ static psa_status_t ecp_export_public_key(
|
||||
mbedtls_ecp_keypair *ecp = NULL;
|
||||
|
||||
status = mbedtls_psa_ecp_load_representation(
|
||||
attributes->core.type, key_buffer, key_buffer_size, &ecp );
|
||||
attributes->core.type, attributes->core.bits,
|
||||
key_buffer, key_buffer_size, &ecp );
|
||||
if( status != PSA_SUCCESS )
|
||||
return( status );
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
* when done.
|
||||
*/
|
||||
psa_status_t mbedtls_psa_ecp_load_representation( psa_key_type_t type,
|
||||
size_t curve_bits,
|
||||
const uint8_t *data,
|
||||
size_t data_length,
|
||||
mbedtls_ecp_keypair **p_ecp );
|
||||
|
Reference in New Issue
Block a user