Skip to content

Commit acb6960

Browse files
committed
psa: 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 77057f4 commit acb6960

File tree

4 files changed

+116
-153
lines changed

4 files changed

+116
-153
lines changed

include/psa/crypto.h

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,19 @@ psa_status_t psa_export_key(psa_key_handle_t handle,
482482
* modulus INTEGER, -- n
483483
* publicExponent INTEGER } -- e
484484
* ```
485+
* - For elliptic curve public keys (key types for which
486+
* #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true),
487+
* the format is defined by RFC 3279 §2.3.5 as
488+
* `ECPoint`, which contains the uncompressed
489+
* representation defined by SEC1 §2.3.3.
490+
* ```
491+
* ECPoint ::= ...
492+
* -- first 8 bits: 0x04;
493+
* -- then x_P as a `ceiling(m/8)`-byte string, big endian;
494+
* -- then y_P as a `ceiling(m/8)`-byte string, big endian;
495+
* -- where `m` is the bit size associated with the curve,
496+
* -- i.e. the bit size of `q` for a curve over `F_q`.
497+
* ```
485498
*
486499
* For other public key types, the format is the DER representation defined by
487500
* RFC 5280 as `SubjectPublicKeyInfo`, with the `subjectPublicKey` format
@@ -509,30 +522,6 @@ psa_status_t psa_export_key(psa_key_handle_t handle,
509522
* g INTEGER }
510523
* DSAPublicKey ::= INTEGER -- public key, Y
511524
* ```
512-
* - For elliptic curve public keys (key types for which
513-
* #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true),
514-
* the `subjectPublicKey` format is defined by RFC 3279 §2.3.5 as
515-
* `ECPoint`, which contains the uncompressed
516-
* representation defined by SEC1 §2.3.3.
517-
* The OID is `id-ecPublicKey`,
518-
* and the parameters must be given as a `namedCurve` OID as specified in
519-
* RFC 5480 §2.1.1.1 or other applicable standards.
520-
* ```
521-
* ansi-X9-62 OBJECT IDENTIFIER ::=
522-
* { iso(1) member-body(2) us(840) 10045 }
523-
* id-public-key-type OBJECT IDENTIFIER ::= { ansi-X9.62 2 }
524-
* id-ecPublicKey OBJECT IDENTIFIER ::= { id-publicKeyType 1 }
525-
*
526-
* ECPoint ::= ...
527-
* -- first 8 bits: 0x04;
528-
* -- then x_P as a `ceiling(m/8)`-byte string, big endian;
529-
* -- then y_P as a `ceiling(m/8)`-byte string, big endian;
530-
* -- where `m` is the bit size associated with the curve,
531-
* -- i.e. the bit size of `q` for a curve over `F_q`.
532-
*
533-
* EcpkParameters ::= CHOICE { -- other choices are not allowed
534-
* namedCurve OBJECT IDENTIFIER }
535-
* ```
536525
*
537526
* \param handle Handle to the key to export.
538527
* \param[out] data Buffer where the key data is to be written.
@@ -2160,7 +2149,9 @@ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator,
21602149
* in the same format that psa_import_key()
21612150
* accepts. The standard formats for public
21622151
* keys are documented in the documentation
2163-
* of psa_export_public_key().
2152+
* of psa_export_public_key(). For EC keys, it
2153+
* must also be of the same group as the private
2154+
* key.
21642155
* \param peer_key_length Size of \p peer_key in bytes.
21652156
* \param alg The key agreement algorithm to compute
21662157
* (\c PSA_ALG_XXX value such that

library/psa_crypto.c

Lines changed: 66 additions & 63 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
@@ -642,11 +670,20 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
642670
if( status != PSA_SUCCESS )
643671
return( status );
644672
}
673+
else if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( slot->type ) )
674+
{
675+
status = psa_import_ec_public_key(
676+
PSA_KEY_TYPE_GET_CURVE( slot->type ),
677+
data, data_length,
678+
&slot->data.ecp );
679+
680+
if( status != PSA_SUCCESS )
681+
return( status );
682+
}
645683
else
646684
#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 ) )
685+
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C)
686+
if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
650687
{
651688
int ret;
652689
mbedtls_pk_context pk;
@@ -663,20 +700,7 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
663700
/* We have something that the pkparse module recognizes.
664701
* If it has the expected type and passes any type-specific
665702
* 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-
}
703+
status = psa_import_rsa_key( &pk, &slot->data.rsa );
680704

681705
/* Free the content of the pk object only on error. On success,
682706
* the content of the object has been stored in the slot. */
@@ -687,7 +711,7 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
687711
}
688712
}
689713
else
690-
#endif /* defined(MBEDTLS_PK_PARSE_C) */
714+
#endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) */
691715
{
692716
return( PSA_ERROR_NOT_SUPPORTED );
693717
}
@@ -900,7 +924,7 @@ psa_status_t psa_get_key_information( psa_key_handle_t handle,
900924
return( PSA_SUCCESS );
901925
}
902926

903-
#if defined(MBEDTLS_RSA_C)
927+
#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C)
904928
static int pk_write_pubkey_simple( mbedtls_pk_context *key,
905929
unsigned char *buf, size_t size )
906930
{
@@ -914,7 +938,7 @@ static int pk_write_pubkey_simple( mbedtls_pk_context *key,
914938

915939
return( (int) len );
916940
}
917-
#endif /* defined(MBEDTLS_RSA_C) */
941+
#endif /* defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C) */
918942

919943
static psa_status_t psa_internal_export_key( psa_key_slot_t *slot,
920944
uint8_t *data,
@@ -987,14 +1011,7 @@ static psa_status_t psa_internal_export_key( psa_key_slot_t *slot,
9871011
}
9881012
if( export_public_key || PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->type ) )
9891013
{
990-
if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
991-
{
992-
ret = pk_write_pubkey_simple( &pk, data, data_size );
993-
}
994-
else
995-
{
996-
ret = mbedtls_pk_write_pubkey_der( &pk, data, data_size );
997-
}
1014+
ret = pk_write_pubkey_simple( &pk, data, data_size );
9981015
}
9991016
else
10001017
{
@@ -4041,32 +4058,17 @@ static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key,
40414058
size_t shared_secret_size,
40424059
size_t *shared_secret_length )
40434060
{
4044-
mbedtls_pk_context pk;
40454061
mbedtls_ecp_keypair *their_key = NULL;
40464062
mbedtls_ecdh_context ecdh;
40474063
psa_status_t status;
40484064
mbedtls_ecdh_init( &ecdh );
4049-
mbedtls_pk_init( &pk );
40504065

4051-
status = mbedtls_to_psa_error(
4052-
mbedtls_pk_parse_public_key( &pk, peer_key, peer_key_length ) );
4066+
status = psa_import_ec_public_key(
4067+
mbedtls_ecc_group_to_psa( our_key->grp.id ),
4068+
peer_key, peer_key_length,
4069+
&their_key );
40534070
if( status != PSA_SUCCESS )
40544071
goto exit;
4055-
switch( mbedtls_pk_get_type( &pk ) )
4056-
{
4057-
case MBEDTLS_PK_ECKEY:
4058-
case MBEDTLS_PK_ECKEY_DH:
4059-
break;
4060-
default:
4061-
status = PSA_ERROR_INVALID_ARGUMENT;
4062-
goto exit;
4063-
}
4064-
their_key = mbedtls_pk_ec( pk );
4065-
if( their_key->grp.id != our_key->grp.id )
4066-
{
4067-
status = PSA_ERROR_INVALID_ARGUMENT;
4068-
goto exit;
4069-
}
40704072

40714073
status = mbedtls_to_psa_error(
40724074
mbedtls_ecdh_get_params( &ecdh, their_key, MBEDTLS_ECDH_THEIRS ) );
@@ -4084,8 +4086,9 @@ static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key,
40844086
&global_data.ctr_drbg ) );
40854087

40864088
exit:
4087-
mbedtls_pk_free( &pk );
40884089
mbedtls_ecdh_free( &ecdh );
4090+
mbedtls_ecp_keypair_free( their_key );
4091+
mbedtls_free( their_key );
40894092
return( status );
40904093
}
40914094
#endif /* MBEDTLS_ECDH_C */

0 commit comments

Comments
 (0)