Skip to content

Commit 0ca50fb

Browse files
committed
Simplify EC public key format
Remove front matter from our EC key format, to make it just ECPoint as defined by SEC1 section 2.3.3. As a consequence of the simplification, remove the restriction on not being able to use an ECDH key with ECDSA. There is no longer any OID specified when importing a key, so we can't reject importing of an ECDH key for the purpose of ECDSA based on the OID.
1 parent 0c72f83 commit 0ca50fb

File tree

4 files changed

+117
-133
lines changed

4 files changed

+117
-133
lines changed

include/psa/crypto.h

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -503,27 +503,16 @@ psa_status_t psa_export_key(psa_key_handle_t handle,
503503
* ```
504504
* - For elliptic curve public keys (key types for which
505505
* #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true),
506-
* the `subjectPublicKey` format is defined by RFC 3279 §2.3.5 as
506+
* the format is defined by RFC 3279 §2.3.5 as
507507
* `ECPoint`, which contains the uncompressed
508508
* representation defined by SEC1 §2.3.3.
509-
* The OID is `id-ecPublicKey`,
510-
* and the parameters must be given as a `namedCurve` OID as specified in
511-
* RFC 5480 §2.1.1.1 or other applicable standards.
512509
* ```
513-
* ansi-X9-62 OBJECT IDENTIFIER ::=
514-
* { iso(1) member-body(2) us(840) 10045 }
515-
* id-public-key-type OBJECT IDENTIFIER ::= { ansi-X9.62 2 }
516-
* id-ecPublicKey OBJECT IDENTIFIER ::= { id-publicKeyType 1 }
517-
*
518510
* ECPoint ::= ...
519511
* -- first 8 bits: 0x04;
520512
* -- then x_P as a `ceiling(m/8)`-byte string, big endian;
521513
* -- then y_P as a `ceiling(m/8)`-byte string, big endian;
522514
* -- where `m` is the bit size associated with the curve,
523515
* -- i.e. the bit size of `q` for a curve over `F_q`.
524-
*
525-
* EcpkParameters ::= CHOICE { -- other choices are not allowed
526-
* namedCurve OBJECT IDENTIFIER }
527516
* ```
528517
*
529518
* \param handle Handle to the key to export.
@@ -2152,7 +2141,9 @@ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator,
21522141
* in the same format that psa_import_key()
21532142
* accepts. The standard formats for public
21542143
* keys are documented in the documentation
2155-
* of psa_export_public_key().
2144+
* of psa_export_public_key(). For EC keys, it
2145+
* must also be of the same group as the private
2146+
* key. XXX check this with crypto know-hower
21562147
* \param peer_key_length Size of \p peer_key in bytes.
21572148
* \param alg The key agreement algorithm to compute
21582149
* (\c PSA_ALG_XXX value such that

library/psa_crypto.c

Lines changed: 78 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -537,25 +537,53 @@ static psa_status_t psa_import_rsa_key( mbedtls_pk_context *pk,
537537
}
538538
#endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) */
539539

540-
#if defined(MBEDTLS_ECP_C) && defined(MBEDTLS_PK_PARSE_C)
541-
/* Import an elliptic curve parsed by the mbedtls pk module. */
542-
static psa_status_t psa_import_ecp_key( psa_ecc_curve_t expected_curve,
543-
mbedtls_pk_context *pk,
544-
mbedtls_ecp_keypair **p_ecp )
540+
#if defined(MBEDTLS_ECP_C)
541+
/* Import a public key given as a byte string which is a SEC1 2.3.3 ECPoint. */
542+
static psa_status_t psa_import_ec_public_key( psa_ecc_curve_t curve,
543+
const uint8_t *data,
544+
size_t data_length,
545+
mbedtls_ecp_keypair **p_ecp )
545546
{
546-
if( mbedtls_pk_get_type( pk ) != MBEDTLS_PK_ECKEY )
547-
return( PSA_ERROR_INVALID_ARGUMENT );
548-
else
547+
psa_status_t status = PSA_ERROR_TAMPERING_DETECTED;
548+
mbedtls_ecp_keypair *ecp = NULL;
549+
mbedtls_ecp_group_id grp_id = mbedtls_ecc_group_of_psa( curve );
550+
551+
*p_ecp = NULL;
552+
ecp = mbedtls_calloc( 1, sizeof( *ecp ) );
553+
if( ecp == NULL )
554+
return( PSA_ERROR_INSUFFICIENT_MEMORY );
555+
mbedtls_ecp_keypair_init( ecp );
556+
557+
/* Load the group. */
558+
status = mbedtls_to_psa_error(
559+
mbedtls_ecp_group_load( &ecp->grp, grp_id ) );
560+
if( status != PSA_SUCCESS )
561+
goto exit;
562+
/* Load the public value. */
563+
status = mbedtls_to_psa_error(
564+
mbedtls_ecp_point_read_binary( &ecp->grp, &ecp->Q,
565+
data, data_length ) );
566+
if( status != PSA_SUCCESS )
567+
goto exit;
568+
569+
/* Check that the point belongs to the group. */
570+
status = mbedtls_to_psa_error(
571+
mbedtls_ecp_check_pubkey( &ecp->grp, &ecp->Q ) );
572+
if( status != PSA_SUCCESS )
573+
goto exit;
574+
575+
*p_ecp = ecp;
576+
return( PSA_SUCCESS );
577+
578+
exit:
579+
if( ecp != NULL )
549580
{
550-
mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( *pk );
551-
psa_ecc_curve_t actual_curve = mbedtls_ecc_group_to_psa( ecp->grp.id );
552-
if( actual_curve != expected_curve )
553-
return( PSA_ERROR_INVALID_ARGUMENT );
554-
*p_ecp = ecp;
555-
return( PSA_SUCCESS );
581+
mbedtls_ecp_keypair_free( ecp );
582+
mbedtls_free( ecp );
556583
}
584+
return( status );
557585
}
558-
#endif /* defined(MBEDTLS_ECP_C) && defined(MBEDTLS_PK_PARSE_C) */
586+
#endif /* defined(MBEDTLS_ECP_C) */
559587

560588
#if defined(MBEDTLS_ECP_C)
561589
/* Import a private key given as a byte string which is the private value
@@ -644,9 +672,8 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
644672
}
645673
else
646674
#endif /* MBEDTLS_ECP_C */
647-
#if defined(MBEDTLS_PK_PARSE_C)
648-
if( PSA_KEY_TYPE_IS_RSA( slot->type ) ||
649-
PSA_KEY_TYPE_IS_ECC( slot->type ) )
675+
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C)
676+
if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
650677
{
651678
int ret;
652679
mbedtls_pk_context pk;
@@ -663,20 +690,7 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
663690
/* We have something that the pkparse module recognizes.
664691
* If it has the expected type and passes any type-specific
665692
* checks, store it. */
666-
#if defined(MBEDTLS_RSA_C)
667-
if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
668-
status = psa_import_rsa_key( &pk, &slot->data.rsa );
669-
else
670-
#endif /* MBEDTLS_RSA_C */
671-
#if defined(MBEDTLS_ECP_C)
672-
if( PSA_KEY_TYPE_IS_ECC( slot->type ) )
673-
status = psa_import_ecp_key( PSA_KEY_TYPE_GET_CURVE( slot->type ),
674-
&pk, &slot->data.ecp );
675-
else
676-
#endif /* MBEDTLS_ECP_C */
677-
{
678-
status = PSA_ERROR_NOT_SUPPORTED;
679-
}
693+
status = psa_import_rsa_key( &pk, &slot->data.rsa );
680694

681695
/* Free the content of the pk object only on error. On success,
682696
* the content of the object has been stored in the slot. */
@@ -687,7 +701,20 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
687701
}
688702
}
689703
else
690-
#endif /* defined(MBEDTLS_PK_PARSE_C) */
704+
#endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) */
705+
#if defined(MBEDTLS_ECP_C)
706+
if( PSA_KEY_TYPE_IS_ECC( slot->type ) )
707+
{
708+
status = psa_import_ec_public_key(
709+
PSA_KEY_TYPE_GET_CURVE( slot->type ),
710+
data, data_length,
711+
&slot->data.ecp );
712+
713+
if( status != PSA_SUCCESS )
714+
return( status );
715+
}
716+
else
717+
#endif /* MBEDTLS_ECP_C */
691718
{
692719
return( PSA_ERROR_NOT_SUPPORTED );
693720
}
@@ -915,6 +942,19 @@ static int pk_write_pubkey_rsa( mbedtls_pk_context *key, unsigned char *buf, siz
915942
return( (int) len );
916943
}
917944

945+
static int pk_write_pubkey_ecp( mbedtls_pk_context *key, unsigned char *buf, size_t size )
946+
{
947+
int ret;
948+
unsigned char *c;
949+
size_t len = 0;
950+
951+
c = buf + size;
952+
953+
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) );
954+
955+
return( (int) len );
956+
}
957+
918958
static psa_status_t psa_internal_export_key( psa_key_slot_t *slot,
919959
uint8_t *data,
920960
size_t data_size,
@@ -992,7 +1032,7 @@ static psa_status_t psa_internal_export_key( psa_key_slot_t *slot,
9921032
}
9931033
else
9941034
{
995-
ret = mbedtls_pk_write_pubkey_der( &pk, data, data_size );
1035+
ret = pk_write_pubkey_ecp( &pk, data, data_size );
9961036
}
9971037
}
9981038
else
@@ -4040,32 +4080,17 @@ static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key,
40404080
size_t shared_secret_size,
40414081
size_t *shared_secret_length )
40424082
{
4043-
mbedtls_pk_context pk;
40444083
mbedtls_ecp_keypair *their_key = NULL;
40454084
mbedtls_ecdh_context ecdh;
40464085
psa_status_t status;
40474086
mbedtls_ecdh_init( &ecdh );
4048-
mbedtls_pk_init( &pk );
40494087

4050-
status = mbedtls_to_psa_error(
4051-
mbedtls_pk_parse_public_key( &pk, peer_key, peer_key_length ) );
4088+
status = psa_import_ec_public_key(
4089+
mbedtls_ecc_group_to_psa( our_key->grp.id ),
4090+
peer_key, peer_key_length,
4091+
&their_key );
40524092
if( status != PSA_SUCCESS )
40534093
goto exit;
4054-
switch( mbedtls_pk_get_type( &pk ) )
4055-
{
4056-
case MBEDTLS_PK_ECKEY:
4057-
case MBEDTLS_PK_ECKEY_DH:
4058-
break;
4059-
default:
4060-
status = PSA_ERROR_INVALID_ARGUMENT;
4061-
goto exit;
4062-
}
4063-
their_key = mbedtls_pk_ec( pk );
4064-
if( their_key->grp.id != our_key->grp.id )
4065-
{
4066-
status = PSA_ERROR_INVALID_ARGUMENT;
4067-
goto exit;
4068-
}
40694094

40704095
status = mbedtls_to_psa_error(
40714096
mbedtls_ecdh_get_params( &ecdh, their_key, MBEDTLS_ECDH_THEIRS ) );
@@ -4083,7 +4108,6 @@ static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key,
40834108
&global_data.ctr_drbg ) );
40844109

40854110
exit:
4086-
mbedtls_pk_free( &pk );
40874111
mbedtls_ecdh_free( &ecdh );
40884112
return( status );
40894113
}

0 commit comments

Comments
 (0)