diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 99c4b523d0..b54585a7e3 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -1343,23 +1343,11 @@ psa_status_t psa_get_key_information(psa_key_slot_t key, * } * ``` * - For elliptic curve key pairs (key types for which - * #PSA_KEY_TYPE_IS_ECC_KEYPAIR is true), the format is the - * non-encrypted DER encoding of the representation defined by RFC 5915 as - * `ECPrivateKey`, version 1. The `ECParameters` field must be a - * `namedCurve` OID as specified in RFC 5480 §2.1.1.1. The public key - * must be present and must be an `ECPoint` in the same format - * (uncompressed variant) an ECC public key of the - * corresponding type exported with psa_export_public_key(). - * ``` - * ECPrivateKey ::= SEQUENCE { - * version INTEGER, -- must be 1 - * privateKey OCTET STRING, - * -- `ceiling(log2(n)/8)`-byte string, big endian, - * -- where n is the order of the curve. - * parameters [0] IMPLICIT ECParameters {{ namedCurve }}, -- mandatory - * publicKey [1] IMPLICIT BIT STRING -- mandatory - * } - * ``` + * #PSA_KEY_TYPE_IS_ECC_KEYPAIR is true), the format is + * a big-endian representation of the private point as a + * `ceiling(log2(n)/8)`-byte string where `n` is the order of the curve. + * This is the content of the `privateKey` field of the `ECPrivateKey` + * format defined by RFC 5915. * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is * true), the format is the same as for psa_export_public_key(). * diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 6b01c13f0b..f77df30516 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -262,6 +262,23 @@ static psa_status_t mbedtls_to_psa_error( int ret ) case MBEDTLS_ERR_MD_HW_ACCEL_FAILED: return( PSA_ERROR_HARDWARE_FAILURE ); + case MBEDTLS_ERR_MPI_FILE_IO_ERROR: + return( PSA_ERROR_STORAGE_FAILURE ); + case MBEDTLS_ERR_MPI_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_INVALID_CHARACTER: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL: + return( PSA_ERROR_BUFFER_TOO_SMALL ); + case MBEDTLS_ERR_MPI_NEGATIVE_VALUE: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_DIVISION_BY_ZERO: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_PK_ALLOC_FAILED: return( PSA_ERROR_INSUFFICIENT_MEMORY ); case MBEDTLS_ERR_PK_TYPE_MISMATCH: @@ -572,6 +589,7 @@ static psa_status_t psa_import_rsa_key( mbedtls_pk_context *pk, #endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) */ #if defined(MBEDTLS_ECP_C) && defined(MBEDTLS_PK_PARSE_C) +/* Import an elliptic curve parsed by the mbedtls pk module. */ static psa_status_t psa_import_ecp_key( psa_ecc_curve_t expected_curve, mbedtls_pk_context *pk, mbedtls_ecp_keypair **p_ecp ) @@ -590,6 +608,58 @@ static psa_status_t psa_import_ecp_key( psa_ecc_curve_t expected_curve, } #endif /* defined(MBEDTLS_ECP_C) && defined(MBEDTLS_PK_PARSE_C) */ +#if defined(MBEDTLS_ECP_C) +/* Import a private key given as a byte string which is the private value + * in big-endian order. */ +static psa_status_t psa_import_ec_private_key( psa_ecc_curve_t curve, + const uint8_t *data, + size_t data_length, + mbedtls_ecp_keypair **p_ecp ) +{ + psa_status_t status = PSA_ERROR_TAMPERING_DETECTED; + mbedtls_ecp_keypair *ecp = NULL; + mbedtls_ecp_group_id grp_id = mbedtls_ecc_group_of_psa( curve ); + + *p_ecp = NULL; + ecp = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); + if( ecp == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + /* Load the group. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_group_load( &ecp->grp, grp_id ) ); + if( status != PSA_SUCCESS ) + goto exit; + /* Load the secret value. */ + status = mbedtls_to_psa_error( + mbedtls_mpi_read_binary( &ecp->d, data, data_length ) ); + if( status != PSA_SUCCESS ) + goto exit; + /* Validate the private key. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_check_privkey( &ecp->grp, &ecp->d ) ); + if( status != PSA_SUCCESS ) + goto exit; + /* Calculate the public key from the private key. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G, + mbedtls_ctr_drbg_random, &global_data.ctr_drbg ) ); + if( status != PSA_SUCCESS ) + goto exit; + + *p_ecp = ecp; + return( PSA_SUCCESS ); + +exit: + if( ecp != NULL ) + { + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + } + return( status ); +} +#endif /* defined(MBEDTLS_ECP_C) */ + psa_status_t psa_import_key( psa_key_slot_t key, psa_key_type_t type, const uint8_t *data, @@ -615,6 +685,17 @@ psa_status_t psa_import_key( psa_key_slot_t key, memcpy( slot->data.raw.data, data, data_length ); } else +#if defined(MBEDTLS_ECP_C) + if( PSA_KEY_TYPE_IS_ECC_KEYPAIR( type ) ) + { + status = psa_import_ec_private_key( PSA_KEY_TYPE_GET_CURVE( type ), + data, data_length, + &slot->data.ecp ); + if( status != PSA_SUCCESS ) + return( status ); + } + else +#endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_PK_PARSE_C) if( PSA_KEY_TYPE_IS_RSA( type ) || PSA_KEY_TYPE_IS_ECC( type ) ) {