Merge pull request #3744 from ronald-cron-arm/psa-generate-key-internal
Rework psa_generate_key
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index e3ba1d3..f304950 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -34,6 +34,7 @@
#include "psa_crypto_driver_wrappers.h"
#include "psa_crypto_ecp.h"
#include "psa_crypto_rsa.h"
+#include "psa_crypto_ecp.h"
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
#include "psa_crypto_se.h"
#endif
@@ -5956,66 +5957,80 @@
}
#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
-#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR)
-static psa_status_t psa_read_rsa_exponent( const uint8_t *domain_parameters,
- size_t domain_parameters_size,
- int *exponent )
+/** Validate the key type and size for key generation
+ *
+ * \param type The key type
+ * \param bits The number of bits of the key
+ *
+ * \retval #PSA_SUCCESS
+ * The key type and size are valid.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The size in bits of the key is not valid.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * The type and/or the size in bits of the key or the combination of
+ * the two is not supported.
+ */
+static psa_status_t psa_validate_key_type_and_size_for_key_generation(
+ psa_key_type_t type, size_t bits )
{
- size_t i;
- uint32_t acc = 0;
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
- if( domain_parameters_size == 0 )
+ if( key_type_is_raw_bytes( type ) )
{
- *exponent = 65537;
+ status = validate_unstructured_key_bit_size( type, bits );
+ if( status != PSA_SUCCESS )
+ return( status );
+ }
+ else
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
+ if( PSA_KEY_TYPE_IS_RSA( type ) && PSA_KEY_TYPE_IS_KEY_PAIR( type ) )
+ {
+ if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS )
+ return( PSA_ERROR_NOT_SUPPORTED );
+
+ /* Accept only byte-aligned keys, for the same reasons as
+ * in psa_import_rsa_key(). */
+ if( bits % 8 != 0 )
+ return( PSA_ERROR_NOT_SUPPORTED );
+ }
+ else
+#endif /* defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) */
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR)
+ if( PSA_KEY_TYPE_IS_ECC( type ) && PSA_KEY_TYPE_IS_KEY_PAIR( type ) )
+ {
+ /* To avoid empty block, return successfully here. */
return( PSA_SUCCESS );
}
+ else
+#endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) */
+ {
+ return( PSA_ERROR_NOT_SUPPORTED );
+ }
- /* Mbed TLS encodes the public exponent as an int. For simplicity, only
- * support values that fit in a 32-bit integer, which is larger than
- * int on just about every platform anyway. */
- if( domain_parameters_size > sizeof( acc ) )
- return( PSA_ERROR_NOT_SUPPORTED );
- for( i = 0; i < domain_parameters_size; i++ )
- acc = ( acc << 8 ) | domain_parameters[i];
- if( acc > INT_MAX )
- return( PSA_ERROR_NOT_SUPPORTED );
- *exponent = acc;
return( PSA_SUCCESS );
}
-#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) */
-static psa_status_t psa_generate_key_internal(
- psa_key_slot_t *slot, size_t bits,
- const uint8_t *domain_parameters, size_t domain_parameters_size )
+psa_status_t psa_generate_key_internal(
+ const psa_key_attributes_t *attributes,
+ uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
{
- psa_key_type_t type = slot->attr.type;
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+ psa_key_type_t type = attributes->core.type;
- if( domain_parameters == NULL && domain_parameters_size != 0 )
+ if( ( attributes->domain_parameters == NULL ) &&
+ ( attributes->domain_parameters_size != 0 ) )
return( PSA_ERROR_INVALID_ARGUMENT );
if( key_type_is_raw_bytes( type ) )
{
- psa_status_t status;
-
- status = validate_unstructured_key_bit_size( slot->attr.type, bits );
+ status = psa_generate_random( key_buffer, key_buffer_size );
if( status != PSA_SUCCESS )
return( status );
- /* Allocate memory for the key */
- status = psa_allocate_buffer_to_slot( slot, PSA_BITS_TO_BYTES( bits ) );
- if( status != PSA_SUCCESS )
- return( status );
-
- status = psa_generate_random( slot->key.data,
- slot->key.bytes );
- if( status != PSA_SUCCESS )
- return( status );
-
- slot->attr.bits = (psa_key_bits_t) bits;
#if defined(MBEDTLS_DES_C)
if( type == PSA_KEY_TYPE_DES )
- psa_des_set_key_parity( slot->key.data,
- slot->key.bytes );
+ psa_des_set_key_parity( key_buffer, key_buffer_size );
#endif /* MBEDTLS_DES_C */
}
else
@@ -6023,49 +6038,10 @@
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR)
if ( type == PSA_KEY_TYPE_RSA_KEY_PAIR )
{
- mbedtls_rsa_context rsa;
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- int exponent;
- psa_status_t status;
- if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS )
- return( PSA_ERROR_NOT_SUPPORTED );
- /* Accept only byte-aligned keys, for the same reasons as
- * in mbedtls_psa_rsa_import_key(). */
- if( bits % 8 != 0 )
- return( PSA_ERROR_NOT_SUPPORTED );
- status = psa_read_rsa_exponent( domain_parameters,
- domain_parameters_size,
- &exponent );
- if( status != PSA_SUCCESS )
- return( status );
- mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE );
- ret = mbedtls_rsa_gen_key( &rsa,
- mbedtls_psa_get_random,
- MBEDTLS_PSA_RANDOM_STATE,
- (unsigned int) bits,
- exponent );
- if( ret != 0 )
- return( mbedtls_to_psa_error( ret ) );
-
- /* Make sure to always have an export representation available */
- size_t bytes = PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE( bits );
-
- status = psa_allocate_buffer_to_slot( slot, bytes );
- if( status != PSA_SUCCESS )
- {
- mbedtls_rsa_free( &rsa );
- return( status );
- }
-
- status = mbedtls_psa_rsa_export_key( type,
- &rsa,
- slot->key.data,
- bytes,
- &slot->key.bytes );
- mbedtls_rsa_free( &rsa );
- if( status != PSA_SUCCESS )
- psa_remove_key_data_from_memory( slot );
- return( status );
+ return( mbedtls_psa_rsa_generate_key( attributes,
+ key_buffer,
+ key_buffer_size,
+ key_buffer_length ) );
}
else
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) */
@@ -6073,50 +6049,15 @@
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR)
if ( PSA_KEY_TYPE_IS_ECC( type ) && PSA_KEY_TYPE_IS_KEY_PAIR( type ) )
{
- psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( type );
- mbedtls_ecp_group_id grp_id =
- 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;
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- if( domain_parameters_size != 0 )
- return( PSA_ERROR_NOT_SUPPORTED );
- if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL )
- return( PSA_ERROR_NOT_SUPPORTED );
- mbedtls_ecp_keypair_init( &ecp );
- ret = mbedtls_ecp_gen_key( grp_id, &ecp,
- mbedtls_psa_get_random,
- MBEDTLS_PSA_RANDOM_STATE );
- if( ret != 0 )
- {
- mbedtls_ecp_keypair_free( &ecp );
- return( mbedtls_to_psa_error( ret ) );
- }
-
-
- /* Make sure to always have an export representation available */
- size_t bytes = PSA_BITS_TO_BYTES( bits );
- psa_status_t status = psa_allocate_buffer_to_slot( slot, bytes );
- if( status != PSA_SUCCESS )
- {
- mbedtls_ecp_keypair_free( &ecp );
- return( status );
- }
-
- status = mbedtls_to_psa_error(
- mbedtls_ecp_write_key( &ecp, slot->key.data, bytes ) );
-
- mbedtls_ecp_keypair_free( &ecp );
- if( status != PSA_SUCCESS ) {
- memset( slot->key.data, 0, bytes );
- psa_remove_key_data_from_memory( slot );
- }
- return( status );
+ return( mbedtls_psa_ecp_generate_key( attributes,
+ key_buffer,
+ key_buffer_size,
+ key_buffer_length ) );
}
else
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */
{
+ (void)key_buffer_length;
return( PSA_ERROR_NOT_SUPPORTED );
}
@@ -6129,6 +6070,7 @@
psa_status_t status;
psa_key_slot_t *slot = NULL;
psa_se_drv_table_entry_t *driver = NULL;
+ size_t key_buffer_size;
*key = MBEDTLS_SVC_KEY_ID_INIT;
@@ -6142,15 +6084,42 @@
if( status != PSA_SUCCESS )
goto exit;
- status = psa_driver_wrapper_generate_key( attributes,
- slot );
- if( status != PSA_ERROR_NOT_SUPPORTED ||
- psa_key_lifetime_is_external( attributes->core.lifetime ) )
- goto exit;
+ /* In the case of a transparent key or an opaque key stored in local
+ * storage (thus not in the case of generating a key in a secure element
+ * or cryptoprocessor with storage), we have to allocate a buffer to
+ * hold the generated key material. */
+ if( slot->key.data == NULL )
+ {
+ if ( PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ) ==
+ PSA_KEY_LOCATION_LOCAL_STORAGE )
+ {
+ status = psa_validate_key_type_and_size_for_key_generation(
+ attributes->core.type, attributes->core.bits );
+ if( status != PSA_SUCCESS )
+ goto exit;
- status = psa_generate_key_internal(
- slot, attributes->core.bits,
- attributes->domain_parameters, attributes->domain_parameters_size );
+ key_buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
+ attributes->core.type,
+ attributes->core.bits );
+ }
+ else
+ {
+ status = psa_driver_wrapper_get_key_buffer_size(
+ attributes, &key_buffer_size );
+ if( status != PSA_SUCCESS )
+ goto exit;
+ }
+
+ status = psa_allocate_buffer_to_slot( slot, key_buffer_size );
+ if( status != PSA_SUCCESS )
+ goto exit;
+ }
+
+ status = psa_driver_wrapper_generate_key( attributes,
+ slot->key.data, slot->key.bytes, &slot->key.bytes );
+
+ if( status != PSA_SUCCESS )
+ psa_remove_key_data_from_memory( slot );
exit:
if( status == PSA_SUCCESS )
@@ -6161,8 +6130,6 @@
return( status );
}
-
-
/****************************************************************/
/* Module setup */
/****************************************************************/
diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h
index cf9d6d0..9f10868 100644
--- a/library/psa_crypto_core.h
+++ b/library/psa_crypto_core.h
@@ -299,4 +299,29 @@
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length );
+/**
+ * \brief Generate a key.
+ *
+ * \note The signature of the function is that of a PSA driver generate_key
+ * entry point.
+ *
+ * \param[in] attributes The attributes for the key to generate.
+ * \param[out] key_buffer Buffer where the key data is to be written.
+ * \param[in] key_buffer_size Size of \p key_buffer in bytes.
+ * \param[out] key_buffer_length On success, the number of bytes written in
+ * \p key_buffer.
+ *
+ * \retval #PSA_SUCCESS
+ * The key was generated successfully.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * Key size in bits or type not supported.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * The size of \p key_buffer is too small.
+ */
+psa_status_t psa_generate_key_internal( const psa_key_attributes_t *attributes,
+ uint8_t *key_buffer,
+ size_t key_buffer_size,
+ size_t *key_buffer_length );
+
#endif /* PSA_CRYPTO_CORE_H */
diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c
index 1eb9ebe..3cb7557 100644
--- a/library/psa_crypto_driver_wrappers.c
+++ b/library/psa_crypto_driver_wrappers.c
@@ -238,62 +238,56 @@
#endif /* PSA_CRYPTO_DRIVER_PRESENT */
}
-#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
-/** Calculate the size to allocate for buffering a key with given attributes.
+/** Get the key buffer size for the key material of a generated key in the
+ * case of an opaque driver without storage.
*
- * This function provides a way to get the expected size for storing a key with
- * the given attributes. This will be the size of the export representation for
- * cleartext keys, and a driver-defined size for keys stored by opaque drivers.
- *
- * \param[in] attributes The key attribute structure of the key to store.
- * \param[out] expected_size On success, a byte size large enough to contain
- * the declared key.
+ * \param[in] attributes The key attributes.
+ * \param[out] key_buffer_size Minimum buffer size to contain the key material
*
* \retval #PSA_SUCCESS
+ * The minimum size for a buffer to contain the key material has been
+ * returned successfully.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * The size in bits of the key is not valid.
* \retval #PSA_ERROR_NOT_SUPPORTED
+ * The type and/or the size in bits of the key or the combination of
+ * the two is not supported.
*/
-static psa_status_t get_expected_key_size( const psa_key_attributes_t *attributes,
- size_t *expected_size )
+psa_status_t psa_driver_wrapper_get_key_buffer_size(
+ const psa_key_attributes_t *attributes,
+ size_t *key_buffer_size )
{
- size_t buffer_size = 0;
psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
psa_key_type_t key_type = attributes->core.type;
size_t key_bits = attributes->core.bits;
+ *key_buffer_size = 0;
switch( location )
{
- case PSA_KEY_LOCATION_LOCAL_STORAGE:
- buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE( key_type, key_bits );
-
- if( buffer_size == 0 )
- return( PSA_ERROR_NOT_SUPPORTED );
-
- *expected_size = buffer_size;
- return( PSA_SUCCESS );
-
#if defined(PSA_CRYPTO_DRIVER_TEST)
case PSA_CRYPTO_TEST_DRIVER_LIFETIME:
#ifdef TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION
- *expected_size = test_size_function( key_type, key_bits );
+ *key_buffer_size = test_size_function( key_type, key_bits );
return( PSA_SUCCESS );
#else /* TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION */
if( PSA_KEY_TYPE_IS_KEY_PAIR( key_type ) )
{
- int public_key_overhead = ( ( TEST_DRIVER_KEY_CONTEXT_STORE_PUBLIC_KEY == 1 ) ?
- PSA_EXPORT_KEY_OUTPUT_SIZE( key_type, key_bits ) : 0 );
- *expected_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE
+ int public_key_overhead =
+ ( ( TEST_DRIVER_KEY_CONTEXT_STORE_PUBLIC_KEY == 1 ) ?
+ PSA_EXPORT_KEY_OUTPUT_SIZE( key_type, key_bits ) : 0 );
+ *key_buffer_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE
+ TEST_DRIVER_KEY_CONTEXT_PUBLIC_KEY_SIZE
+ public_key_overhead;
}
- else if( PSA_KEY_TYPE_IS_PUBLIC_KEY( attributes->core.type ) )
+ else if( PSA_KEY_TYPE_IS_PUBLIC_KEY( key_type ) )
{
- *expected_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE
+ *key_buffer_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE
+ TEST_DRIVER_KEY_CONTEXT_PUBLIC_KEY_SIZE;
}
else if ( !PSA_KEY_TYPE_IS_KEY_PAIR( key_type ) &&
- !PSA_KEY_TYPE_IS_PUBLIC_KEY ( attributes->core.type ) )
+ !PSA_KEY_TYPE_IS_PUBLIC_KEY ( key_type ) )
{
- *expected_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE
+ *key_buffer_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE
+ TEST_DRIVER_KEY_CONTEXT_SYMMETRIC_FACTOR
* ( ( key_bits + 7 ) / 8 );
}
@@ -306,21 +300,26 @@
#endif /* PSA_CRYPTO_DRIVER_TEST */
default:
+ (void)key_type;
+ (void)key_bits;
return( PSA_ERROR_NOT_SUPPORTED );
}
}
-#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
-psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes,
- psa_key_slot_t *slot )
+psa_status_t psa_driver_wrapper_generate_key(
+ const psa_key_attributes_t *attributes,
+ uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
{
-#if defined(PSA_CRYPTO_DRIVER_PRESENT)
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+ psa_key_location_t location =
+ PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime);
+
/* Try dynamically-registered SE interface first */
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
const psa_drv_se_t *drv;
psa_drv_se_context_t *drv_context;
- if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) )
+ if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) )
{
size_t pubkey_length = 0; /* We don't support this feature yet */
if( drv->key_management == NULL ||
@@ -330,83 +329,53 @@
return( PSA_ERROR_NOT_SUPPORTED );
}
return( drv->key_management->p_generate(
- drv_context, psa_key_slot_get_slot_number( slot ),
+ drv_context,
+ *( (psa_key_slot_number_t *)key_buffer ),
attributes, NULL, 0, &pubkey_length ) );
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
- /* Then try accelerator API */
-#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
- psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
- psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime);
- size_t export_size = 0;
-
- status = get_expected_key_size( attributes, &export_size );
- if( status != PSA_SUCCESS )
- return( status );
-
- slot->key.data = mbedtls_calloc(1, export_size);
- if( slot->key.data == NULL )
- return( PSA_ERROR_INSUFFICIENT_MEMORY );
- slot->key.bytes = export_size;
-
switch( location )
{
case PSA_KEY_LOCATION_LOCAL_STORAGE:
- /* Key is stored in the slot in export representation, so
- * cycle through all known transparent accelerators */
-
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
/* Transparent drivers are limited to generating asymmetric keys */
- if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) )
+ if( PSA_KEY_TYPE_IS_ASYMMETRIC( attributes->core.type ) )
{
- status = PSA_ERROR_NOT_SUPPORTED;
- break;
- }
+ /* Cycle through all known transparent accelerators */
#if defined(PSA_CRYPTO_DRIVER_TEST)
- status = test_transparent_generate_key( attributes,
- slot->key.data,
- slot->key.bytes,
- &slot->key.bytes );
- /* Declared with fallback == true */
- if( status != PSA_ERROR_NOT_SUPPORTED )
- break;
+ status = test_transparent_generate_key(
+ attributes, key_buffer, key_buffer_size,
+ key_buffer_length );
+ /* Declared with fallback == true */
+ if( status != PSA_ERROR_NOT_SUPPORTED )
+ break;
#endif /* PSA_CRYPTO_DRIVER_TEST */
- /* Fell through, meaning no accelerator supports this operation */
- status = PSA_ERROR_NOT_SUPPORTED;
+ }
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+ /* Software fallback */
+ status = psa_generate_key_internal(
+ attributes, key_buffer, key_buffer_size, key_buffer_length );
break;
+
/* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
#if defined(PSA_CRYPTO_DRIVER_TEST)
case PSA_CRYPTO_TEST_DRIVER_LIFETIME:
- status = test_opaque_generate_key( attributes,
- slot->key.data,
- slot->key.bytes,
- &slot->key.bytes );
+ status = test_opaque_generate_key(
+ attributes, key_buffer, key_buffer_size, key_buffer_length );
break;
#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
default:
/* Key is declared with a lifetime not known to us */
status = PSA_ERROR_INVALID_ARGUMENT;
break;
}
- if( status != PSA_SUCCESS )
- {
- /* free allocated buffer */
- mbedtls_free( slot->key.data );
- slot->key.data = NULL;
- slot->key.bytes = 0;
- }
-
return( status );
-#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
- return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
-#else /* PSA_CRYPTO_DRIVER_PRESENT */
- (void) attributes;
- (void) slot;
-
- return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* PSA_CRYPTO_DRIVER_PRESENT */
}
psa_status_t psa_driver_wrapper_import_key(
diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h
index 27d8b64..ad16cdd 100644
--- a/library/psa_crypto_driver_wrappers.h
+++ b/library/psa_crypto_driver_wrappers.h
@@ -63,9 +63,13 @@
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length );
+psa_status_t psa_driver_wrapper_get_key_buffer_size(
+ const psa_key_attributes_t *attributes,
+ size_t *key_buffer_size );
+
psa_status_t psa_driver_wrapper_generate_key(
const psa_key_attributes_t *attributes,
- psa_key_slot_t *slot );
+ uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length );
/*
* Cipher functions
diff --git a/library/psa_crypto_ecp.c b/library/psa_crypto_ecp.c
index 1a8f15e..23ec6ac 100644
--- a/library/psa_crypto_ecp.c
+++ b/library/psa_crypto_ecp.c
@@ -292,6 +292,51 @@
#endif /* defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
* defined(BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
+#if defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR)
+static psa_status_t ecp_generate_key(
+ const psa_key_attributes_t *attributes,
+ uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
+{
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
+ attributes->core.type );
+ mbedtls_ecp_group_id grp_id =
+ mbedtls_ecc_group_of_psa( curve, attributes->core.bits, 0 );
+
+ const mbedtls_ecp_curve_info *curve_info =
+ mbedtls_ecp_curve_info_from_grp_id( grp_id );
+ mbedtls_ecp_keypair ecp;
+
+ if( attributes->domain_parameters_size != 0 )
+ return( PSA_ERROR_NOT_SUPPORTED );
+
+ if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL )
+ return( PSA_ERROR_NOT_SUPPORTED );
+
+ mbedtls_ecp_keypair_init( &ecp );
+ ret = mbedtls_ecp_gen_key( grp_id, &ecp,
+ mbedtls_psa_get_random,
+ MBEDTLS_PSA_RANDOM_STATE );
+ if( ret != 0 )
+ {
+ mbedtls_ecp_keypair_free( &ecp );
+ return( mbedtls_to_psa_error( ret ) );
+ }
+
+ status = mbedtls_to_psa_error(
+ mbedtls_ecp_write_key( &ecp, key_buffer, key_buffer_size ) );
+
+ mbedtls_ecp_keypair_free( &ecp );
+
+ if( status == PSA_SUCCESS )
+ *key_buffer_length = key_buffer_size;
+
+ return( status );
+}
+#endif /* defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */
+
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
@@ -318,6 +363,16 @@
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR)
+psa_status_t mbedtls_psa_ecp_generate_key(
+ const psa_key_attributes_t *attributes,
+ uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
+{
+ return( ecp_generate_key( attributes, key_buffer, key_buffer_size,
+ key_buffer_length ) );
+}
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */
+
/*
* BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY.
*/
@@ -350,6 +405,18 @@
#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) ||
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) */
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) && \
+ defined(MBEDTLS_GENPRIME)
+psa_status_t mbedtls_transparent_test_driver_ecp_generate_key(
+ const psa_key_attributes_t *attributes,
+ uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
+{
+ return( ecp_generate_key( attributes, key_buffer, key_buffer_size,
+ key_buffer_length ) );
+}
+#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) &&
+ defined(MBEDTLS_GENPRIME) */
+
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/library/psa_crypto_ecp.h b/library/psa_crypto_ecp.h
index 59b61b9..5c9b63c 100644
--- a/library/psa_crypto_ecp.h
+++ b/library/psa_crypto_ecp.h
@@ -123,11 +123,35 @@
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length );
+/**
+ * \brief Generate an ECP key.
+ *
+ * \note The signature of the function is that of a PSA driver generate_key
+ * entry point.
+ *
+ * \param[in] attributes The attributes for the ECP key to generate.
+ * \param[out] key_buffer Buffer where the key data is to be written.
+ * \param[in] key_buffer_size Size of \p key_buffer in bytes.
+ * \param[out] key_buffer_length On success, the number of bytes written in
+ * \p key_buffer.
+ *
+ * \retval #PSA_SUCCESS
+ * The key was successfully generated.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * Key length or type not supported.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * The size of \p key_buffer is too small.
+ */
+psa_status_t mbedtls_psa_ecp_generate_key(
+ const psa_key_attributes_t *attributes,
+ uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length );
+
/*
* BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY.
*/
#if defined(PSA_CRYPTO_DRIVER_TEST)
+
psa_status_t mbedtls_transparent_test_driver_ecp_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
@@ -139,6 +163,10 @@
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length );
+psa_status_t mbedtls_transparent_test_driver_ecp_generate_key(
+ const psa_key_attributes_t *attributes,
+ uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length );
+
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_ECP_H */
diff --git a/library/psa_crypto_rsa.c b/library/psa_crypto_rsa.c
index aae1d05..fa64001 100644
--- a/library/psa_crypto_rsa.c
+++ b/library/psa_crypto_rsa.c
@@ -24,6 +24,7 @@
#include <psa/crypto.h>
#include "psa_crypto_core.h"
+#include "psa_crypto_random_impl.h"
#include "psa_crypto_rsa.h"
#include <stdlib.h>
@@ -258,6 +259,66 @@
#endif /* defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR) ||
* defined(BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
+#if defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR)
+static psa_status_t psa_rsa_read_exponent( const uint8_t *domain_parameters,
+ size_t domain_parameters_size,
+ int *exponent )
+{
+ size_t i;
+ uint32_t acc = 0;
+
+ if( domain_parameters_size == 0 )
+ {
+ *exponent = 65537;
+ return( PSA_SUCCESS );
+ }
+
+ /* Mbed TLS encodes the public exponent as an int. For simplicity, only
+ * support values that fit in a 32-bit integer, which is larger than
+ * int on just about every platform anyway. */
+ if( domain_parameters_size > sizeof( acc ) )
+ return( PSA_ERROR_NOT_SUPPORTED );
+ for( i = 0; i < domain_parameters_size; i++ )
+ acc = ( acc << 8 ) | domain_parameters[i];
+ if( acc > INT_MAX )
+ return( PSA_ERROR_NOT_SUPPORTED );
+ *exponent = acc;
+ return( PSA_SUCCESS );
+}
+
+static psa_status_t rsa_generate_key(
+ const psa_key_attributes_t *attributes,
+ uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
+{
+ psa_status_t status;
+ mbedtls_rsa_context rsa;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ int exponent;
+
+ status = psa_rsa_read_exponent( attributes->domain_parameters,
+ attributes->domain_parameters_size,
+ &exponent );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE );
+ ret = mbedtls_rsa_gen_key( &rsa,
+ mbedtls_psa_get_random,
+ MBEDTLS_PSA_RANDOM_STATE,
+ (unsigned int)attributes->core.bits,
+ exponent );
+ if( ret != 0 )
+ return( mbedtls_to_psa_error( ret ) );
+
+ status = mbedtls_psa_rsa_export_key( attributes->core.type,
+ &rsa, key_buffer, key_buffer_size,
+ key_buffer_length );
+ mbedtls_rsa_free( &rsa );
+
+ return( status );
+}
+#endif /* defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR) */
+
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
@@ -284,6 +345,16 @@
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) ||
* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR)
+psa_status_t mbedtls_psa_rsa_generate_key(
+ const psa_key_attributes_t *attributes,
+ uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
+{
+ return( rsa_generate_key( attributes, key_buffer, key_buffer_size,
+ key_buffer_length ) );
+}
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) */
+
/*
* BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY.
*/
@@ -316,6 +387,16 @@
#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) ||
defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY) */
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR)
+psa_status_t mbedtls_transparent_test_driver_rsa_generate_key(
+ const psa_key_attributes_t *attributes,
+ uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
+{
+ return( rsa_generate_key( attributes, key_buffer, key_buffer_size,
+ key_buffer_length ) );
+}
+#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) */
+
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/library/psa_crypto_rsa.h b/library/psa_crypto_rsa.h
index 64013df..08182a7 100644
--- a/library/psa_crypto_rsa.h
+++ b/library/psa_crypto_rsa.h
@@ -114,6 +114,29 @@
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length );
+/**
+ * \brief Generate an RSA key.
+ *
+ * \note The signature of the function is that of a PSA driver generate_key
+ * entry point.
+ *
+ * \param[in] attributes The attributes for the RSA key to generate.
+ * \param[out] key_buffer Buffer where the key data is to be written.
+ * \param[in] key_buffer_size Size of \p key_buffer in bytes.
+ * \param[out] key_buffer_length On success, the number of bytes written in
+ * \p key_buffer.
+ *
+ * \retval #PSA_SUCCESS
+ * The key was successfully generated.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * Key length or type not supported.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ * The size of \p key_buffer is too small.
+ */
+psa_status_t mbedtls_psa_rsa_generate_key(
+ const psa_key_attributes_t *attributes,
+ uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length );
+
/*
* BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY.
*/
@@ -131,6 +154,10 @@
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length );
+psa_status_t mbedtls_transparent_test_driver_rsa_generate_key(
+ const psa_key_attributes_t *attributes,
+ uint8_t *key, size_t key_size, size_t *key_length );
+
#endif /* PSA_CRYPTO_DRIVER_TEST */
#endif /* PSA_CRYPTO_RSA_H */
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index e9d15e4..1036a7c 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -1371,7 +1371,7 @@
scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
# Need to define the correct symbol and include the test driver header path in order to build with the test driver
- make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
+ make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR -DMBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
msg "test: full + MBEDTLS_PSA_CRYPTO_CONFIG"
make test
diff --git a/tests/src/drivers/key_management.c b/tests/src/drivers/key_management.c
index be6a814..10a40c3 100644
--- a/tests/src/drivers/key_management.c
+++ b/tests/src/drivers/key_management.c
@@ -45,11 +45,6 @@
const psa_key_attributes_t *attributes,
uint8_t *key, size_t key_size, size_t *key_length )
{
-#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) && \
- !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
- (void)attributes;
-#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR &&
- * !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */
++test_driver_key_management_hooks.hits;
if( test_driver_key_management_hooks.forced_status != PSA_SUCCESS )
@@ -66,66 +61,26 @@
}
/* Copied from psa_crypto.c */
-#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \
- defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR)
if ( PSA_KEY_TYPE_IS_ECC( psa_get_key_type( attributes ) )
&& PSA_KEY_TYPE_IS_KEY_PAIR( psa_get_key_type( attributes ) ) )
{
- psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
- psa_get_key_type( attributes ) );
- mbedtls_ecp_group_id grp_id =
- mbedtls_ecc_group_of_psa(
- curve,
- psa_get_key_bits( attributes ), 0 );
- const mbedtls_ecp_curve_info *curve_info =
- mbedtls_ecp_curve_info_from_grp_id( grp_id );
- mbedtls_ecp_keypair ecp;
- mbedtls_test_rnd_pseudo_info rnd_info;
- memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
-
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- if( attributes->domain_parameters_size != 0 )
- return( PSA_ERROR_NOT_SUPPORTED );
- if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL )
- return( PSA_ERROR_NOT_SUPPORTED );
- if( curve_info->bit_size != psa_get_key_bits( attributes ) )
- return( PSA_ERROR_INVALID_ARGUMENT );
- mbedtls_ecp_keypair_init( &ecp );
- ret = mbedtls_ecp_gen_key( grp_id, &ecp,
- &mbedtls_test_rnd_pseudo_rand,
- &rnd_info );
- if( ret != 0 )
- {
- mbedtls_ecp_keypair_free( &ecp );
- return( mbedtls_to_psa_error( ret ) );
- }
-
- /* Make sure to use export representation */
- size_t bytes = PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) );
- if( key_size < bytes )
- {
- mbedtls_ecp_keypair_free( &ecp );
- return( PSA_ERROR_BUFFER_TOO_SMALL );
- }
- psa_status_t status = mbedtls_to_psa_error(
- mbedtls_mpi_write_binary( &ecp.d, key, bytes ) );
-
- if( status == PSA_SUCCESS )
- {
- *key_length = bytes;
- }
- else
- {
- memset( key, 0, bytes );
- }
-
- mbedtls_ecp_keypair_free( &ecp );
- return( status );
+ return( mbedtls_transparent_test_driver_ecp_generate_key(
+ attributes, key, key_size, key_length ) );
}
else
-#endif /* MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR ||
- * MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */
- return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) */
+
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR)
+ if ( psa_get_key_type( attributes ) == PSA_KEY_TYPE_RSA_KEY_PAIR )
+ return( mbedtls_transparent_test_driver_rsa_generate_key(
+ attributes, key, key_size, key_length ) );
+ else
+#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) */
+ {
+ (void)attributes;
+ return( PSA_ERROR_NOT_SUPPORTED );
+ }
}
psa_status_t test_opaque_generate_key(
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index c37bdce..c981e98 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -2915,7 +2915,7 @@
generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:PSA_ERROR_NOT_SUPPORTED:0
PSA generate key: ECC, Curve25519, good
-depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_ECP_DP_CURVE25519_ENABLED:!MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_ECP_DP_CURVE25519_ENABLED
generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):255:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_SUCCESS:0
PSA generate key: RSA, default e
diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.data b/tests/suites/test_suite_psa_crypto_driver_wrappers.data
index 1fd449f..14f84c0 100644
--- a/tests/suites/test_suite_psa_crypto_driver_wrappers.data
+++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.data
@@ -38,6 +38,10 @@
depends_on:MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR
generate_key:PSA_ERROR_NOT_SUPPORTED:"":PSA_SUCCESS
+generate_key through transparent driver: fallback not available
+depends_on:!MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR
+generate_key:PSA_ERROR_NOT_SUPPORTED:"":PSA_ERROR_NOT_SUPPORTED
+
generate_key through transparent driver: error
generate_key:PSA_ERROR_GENERIC_ERROR:"":PSA_ERROR_GENERIC_ERROR