Skip to content

Commit ccdce90

Browse files
committed
psa: Simplify EC public key format
Remove front matter from our EC key format, to make it just the contents of an 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 97271b3 commit ccdce90

File tree

5 files changed

+128
-179
lines changed

5 files changed

+128
-179
lines changed

include/psa/crypto.h

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,14 @@ 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), the format is the uncompressed
487+
* representation defined by SEC1 §2.3.3 as the content of an ECPoint:
488+
* Let `m` be the bit size associated with the curve, i.e. the bit size of
489+
* `q` for a curve over `F_q`. The representation consists of:
490+
* - The byte 0x04;
491+
* - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
492+
* - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
485493
*
486494
* For other public key types, the format is the DER representation defined by
487495
* RFC 5280 as `SubjectPublicKeyInfo`, with the `subjectPublicKey` format
@@ -509,30 +517,6 @@ psa_status_t psa_export_key(psa_key_handle_t handle,
509517
* g INTEGER }
510518
* DSAPublicKey ::= INTEGER -- public key, Y
511519
* ```
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-
* ```
536520
*
537521
* \param handle Handle to the key to export.
538522
* \param[out] data Buffer where the key data is to be written.
@@ -2160,7 +2144,9 @@ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator,
21602144
* in the same format that psa_import_key()
21612145
* accepts. The standard formats for public
21622146
* keys are documented in the documentation
2163-
* of psa_export_public_key().
2147+
* of psa_export_public_key(). For EC keys, it
2148+
* must also be of the same group as the private
2149+
* key.
21642150
* \param peer_key_length Size of \p peer_key in bytes.
21652151
* \param alg The key agreement algorithm to compute
21662152
* (\c PSA_ALG_XXX value such that

include/psa/crypto_sizes.h

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -493,26 +493,16 @@
493493

494494
/* Maximum size of the export encoding of an ECC public key.
495495
*
496-
* SubjectPublicKeyInfo ::= SEQUENCE {
497-
* algorithm AlgorithmIdentifier,
498-
* subjectPublicKey BIT STRING } -- contains ECPoint
499-
* AlgorithmIdentifier ::= SEQUENCE {
500-
* algorithm OBJECT IDENTIFIER,
501-
* parameters OBJECT IDENTIFIER } -- namedCurve
502-
* ECPoint ::= ...
503-
* -- first 8 bits: 0x04;
504-
* -- then x_P as a `ceiling(m/8)`-byte string, big endian;
505-
* -- then y_P as a `ceiling(m/8)`-byte string, big endian;
506-
* -- where `m` is the bit size associated with the curve.
507-
*
508-
* - 2 * 4 bytes of SEQUENCE overhead;
509-
* - 1 + 1 + 7 bytes of algorithm (id-ecPublicKey OID);
510-
* - 1 + 1 + 12 bytes of namedCurve OID;
511-
* - 4 bytes of BIT STRING overhead;
512-
* - 1 byte + 2 * point size in ECPoint.
496+
* The representation of an ECC public key is:
497+
* - The byte 0x04;
498+
* - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
499+
* - `y_P` as a `ceiling(m/8)`-byte string, big-endian;
500+
* - where m is the bit size associated with the curve.
501+
*
502+
* - 1 byte + 2 * point size.
513503
*/
514504
#define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \
515-
(2 * PSA_BITS_TO_BYTES(key_bits) + 36)
505+
(2 * PSA_BITS_TO_BYTES(key_bits) + 1)
516506

517507
/* Maximum size of the export encoding of an ECC key pair.
518508
*

library/psa_crypto.c

Lines changed: 70 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -537,25 +537,55 @@ 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+
542+
/* Import a public key given as the uncompressed representation defined by SEC1
543+
* 2.3.3 as the content of an ECPoint. */
544+
static psa_status_t psa_import_ec_public_key( psa_ecc_curve_t curve,
545+
const uint8_t *data,
546+
size_t data_length,
547+
mbedtls_ecp_keypair **p_ecp )
545548
{
546-
if( mbedtls_pk_get_type( pk ) != MBEDTLS_PK_ECKEY )
547-
return( PSA_ERROR_INVALID_ARGUMENT );
548-
else
549+
psa_status_t status = PSA_ERROR_TAMPERING_DETECTED;
550+
mbedtls_ecp_keypair *ecp = NULL;
551+
mbedtls_ecp_group_id grp_id = mbedtls_ecc_group_of_psa( curve );
552+
553+
*p_ecp = NULL;
554+
ecp = mbedtls_calloc( 1, sizeof( *ecp ) );
555+
if( ecp == NULL )
556+
return( PSA_ERROR_INSUFFICIENT_MEMORY );
557+
mbedtls_ecp_keypair_init( ecp );
558+
559+
/* Load the group. */
560+
status = mbedtls_to_psa_error(
561+
mbedtls_ecp_group_load( &ecp->grp, grp_id ) );
562+
if( status != PSA_SUCCESS )
563+
goto exit;
564+
/* Load the public value. */
565+
status = mbedtls_to_psa_error(
566+
mbedtls_ecp_point_read_binary( &ecp->grp, &ecp->Q,
567+
data, data_length ) );
568+
if( status != PSA_SUCCESS )
569+
goto exit;
570+
571+
/* Check that the point is on the curve. */
572+
status = mbedtls_to_psa_error(
573+
mbedtls_ecp_check_pubkey( &ecp->grp, &ecp->Q ) );
574+
if( status != PSA_SUCCESS )
575+
goto exit;
576+
577+
*p_ecp = ecp;
578+
return( PSA_SUCCESS );
579+
580+
exit:
581+
if( ecp != NULL )
549582
{
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 );
583+
mbedtls_ecp_keypair_free( ecp );
584+
mbedtls_free( ecp );
556585
}
586+
return( status );
557587
}
558-
#endif /* defined(MBEDTLS_ECP_C) && defined(MBEDTLS_PK_PARSE_C) */
588+
#endif /* defined(MBEDTLS_ECP_C) */
559589

560590
#if defined(MBEDTLS_ECP_C)
561591
/* Import a private key given as a byte string which is the private value
@@ -642,11 +672,20 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
642672
if( status != PSA_SUCCESS )
643673
return( status );
644674
}
675+
else if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( slot->type ) )
676+
{
677+
status = psa_import_ec_public_key(
678+
PSA_KEY_TYPE_GET_CURVE( slot->type ),
679+
data, data_length,
680+
&slot->data.ecp );
681+
682+
if( status != PSA_SUCCESS )
683+
return( status );
684+
}
645685
else
646686
#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 ) )
687+
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C)
688+
if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
650689
{
651690
int ret;
652691
mbedtls_pk_context pk;
@@ -660,23 +699,9 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
660699
if( ret != 0 )
661700
return( mbedtls_to_psa_error( ret ) );
662701

663-
/* We have something that the pkparse module recognizes.
664-
* If it has the expected type and passes any type-specific
665-
* 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-
}
702+
/* We have something that the pkparse module recognizes. If it is a
703+
* valid RSA key, store it. */
704+
status = psa_import_rsa_key( &pk, &slot->data.rsa );
680705

681706
/* Free the content of the pk object only on error. On success,
682707
* the content of the object has been stored in the slot. */
@@ -687,7 +712,7 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
687712
}
688713
}
689714
else
690-
#endif /* defined(MBEDTLS_PK_PARSE_C) */
715+
#endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) */
691716
{
692717
return( PSA_ERROR_NOT_SUPPORTED );
693718
}
@@ -900,7 +925,7 @@ psa_status_t psa_get_key_information( psa_key_handle_t handle,
900925
return( PSA_SUCCESS );
901926
}
902927

903-
#if defined(MBEDTLS_RSA_C)
928+
#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C)
904929
static int pk_write_pubkey_simple( mbedtls_pk_context *key,
905930
unsigned char *buf, size_t size )
906931
{
@@ -914,7 +939,7 @@ static int pk_write_pubkey_simple( mbedtls_pk_context *key,
914939

915940
return( (int) len );
916941
}
917-
#endif /* defined(MBEDTLS_RSA_C) */
942+
#endif /* defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C) */
918943

919944
static psa_status_t psa_internal_export_key( psa_key_slot_t *slot,
920945
uint8_t *data,
@@ -987,14 +1012,7 @@ static psa_status_t psa_internal_export_key( psa_key_slot_t *slot,
9871012
}
9881013
if( export_public_key || PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->type ) )
9891014
{
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-
}
1015+
ret = pk_write_pubkey_simple( &pk, data, data_size );
9981016
}
9991017
else
10001018
{
@@ -4041,32 +4059,17 @@ static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key,
40414059
size_t shared_secret_size,
40424060
size_t *shared_secret_length )
40434061
{
4044-
mbedtls_pk_context pk;
40454062
mbedtls_ecp_keypair *their_key = NULL;
40464063
mbedtls_ecdh_context ecdh;
40474064
psa_status_t status;
40484065
mbedtls_ecdh_init( &ecdh );
4049-
mbedtls_pk_init( &pk );
40504066

4051-
status = mbedtls_to_psa_error(
4052-
mbedtls_pk_parse_public_key( &pk, peer_key, peer_key_length ) );
4067+
status = psa_import_ec_public_key(
4068+
mbedtls_ecc_group_to_psa( our_key->grp.id ),
4069+
peer_key, peer_key_length,
4070+
&their_key );
40534071
if( status != PSA_SUCCESS )
40544072
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-
}
40704073

40714074
status = mbedtls_to_psa_error(
40724075
mbedtls_ecdh_get_params( &ecdh, their_key, MBEDTLS_ECDH_THEIRS ) );
@@ -4085,8 +4088,9 @@ static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key,
40854088
&global_data.ctr_drbg ) );
40864089

40874090
exit:
4088-
mbedtls_pk_free( &pk );
40894091
mbedtls_ecdh_free( &ecdh );
4092+
mbedtls_ecp_keypair_free( their_key );
4093+
mbedtls_free( their_key );
40904094
return( status );
40914095
}
40924096
#endif /* MBEDTLS_ECDH_C */

0 commit comments

Comments
 (0)