diff --git a/library/psa_crypto.c b/library/psa_crypto.c index b69658ce5..ab4e47ab0 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -739,7 +739,7 @@ static psa_status_t psa_load_ecp_representation( psa_key_type_t type, * - The byte 0x04; * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. - * So its data length is 2m+1 where n is the key size in bits. + * So its data length is 2m+1 where m is the curve size in bits. */ if( ( data_length & 1 ) == 0 ) return( PSA_ERROR_INVALID_ARGUMENT ); @@ -969,14 +969,45 @@ static psa_status_t psa_allocate_buffer_to_slot( psa_key_slot_t *slot, return( PSA_SUCCESS ); } -/** Import key data into a slot. `slot->attr.type` must have been set - * previously. This function assumes that the slot does not contain - * any key material yet. On failure, the slot content is unchanged. */ -psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, - const uint8_t *data, - size_t data_length ) +psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot, + const uint8_t* data, + size_t data_length ) +{ + psa_status_t status = psa_allocate_buffer_to_slot( slot, + data_length ); + if( status != PSA_SUCCESS ) + return( status ); + + memcpy( slot->data.key.data, data, data_length ); + return( PSA_SUCCESS ); +} + +/** Import key data into a slot. + * + * `slot->type` must have been set previously. + * This function assumes that the slot does not contain any key material yet. + * On failure, the slot content is unchanged. + * + * Persistent storage is not affected. + * + * \param[in,out] slot The key slot to import data into. + * Its `type` field must have previously been set to + * the desired key type. + * It must not contain any key material yet. + * \param[in] data Buffer containing the key material to parse and import. + * \param data_length Size of \p data in bytes. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, + const uint8_t *data, + size_t data_length ) { psa_status_t status = PSA_SUCCESS; + size_t bit_size; /* zero-length keys are never supported. */ if( data_length == 0 ) @@ -984,7 +1015,7 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, if( key_type_is_raw_bytes( slot->attr.type ) ) { - size_t bit_size = PSA_BYTES_TO_BITS( data_length ); + bit_size = PSA_BYTES_TO_BITS( data_length ); /* Ensure that the bytes-to-bits conversion hasn't overflown. */ if( data_length > SIZE_MAX / 8 ) @@ -1000,47 +1031,65 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, return( status ); /* Allocate memory for the key */ - status = psa_allocate_buffer_to_slot( slot, data_length ); + status = psa_copy_key_material_into_slot( slot, data, data_length ); if( status != PSA_SUCCESS ) return( status ); - /* copy key into allocated buffer */ - memcpy( slot->data.key.data, data, data_length ); - /* Write the actual key size to the slot. * psa_start_key_creation() wrote the size declared by the * caller, which may be 0 (meaning unspecified) or wrong. */ slot->attr.bits = (psa_key_bits_t) bit_size; + + return( PSA_SUCCESS ); } - else if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) + else if( PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) ) { + /* Try validation through accelerators first. */ + bit_size = slot->attr.bits; + psa_key_attributes_t attributes = { + .core = slot->attr + }; + status = psa_driver_wrapper_validate_key( &attributes, + data, + data_length, + &bit_size ); + if( status == PSA_SUCCESS ) + { + /* Key has been validated successfully by an accelerator. + * Copy key material into slot. */ + status = psa_copy_key_material_into_slot( slot, data, data_length ); + if( status != PSA_SUCCESS ) + return( status ); + + slot->attr.bits = (psa_key_bits_t) bit_size; + return( PSA_SUCCESS ); + } + else if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); + + /* Key format is not supported by any accelerator, try software fallback + * if present. */ #if defined(MBEDTLS_ECP_C) - status = psa_import_ecp_key( slot, - data, data_length ); -#else - /* No drivers have been implemented yet, so without mbed TLS backing - * there's no way to do ECP with the current library. */ - return( PSA_ERROR_NOT_SUPPORTED ); + if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) + { + return( psa_import_ecp_key( slot, data, data_length ) ); + } #endif /* defined(MBEDTLS_ECP_C) */ - } - else if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) - { #if defined(MBEDTLS_RSA_C) - status = psa_import_rsa_key( slot, - data, data_length ); -#else - /* No drivers have been implemented yet, so without mbed TLS backing - * there's no way to do RSA with the current library. */ - status = PSA_ERROR_NOT_SUPPORTED; + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + { + return( psa_import_rsa_key( slot, data, data_length ) ); + } #endif /* defined(MBEDTLS_RSA_C) */ + + /* Fell through the fallback as well, so have nothing else to try. */ + return( PSA_ERROR_NOT_SUPPORTED ); } else { /* Unknown key type */ return( PSA_ERROR_NOT_SUPPORTED ); } - - return( status ); } /** Calculate the intersection of two algorithm usage policies. @@ -1916,22 +1965,11 @@ static psa_status_t psa_finish_key_creation( else #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ { - size_t buffer_size = - PSA_KEY_EXPORT_MAX_SIZE( slot->attr.type, - slot->attr.bits ); - uint8_t *buffer = mbedtls_calloc( 1, buffer_size ); - size_t length = 0; - if( buffer == NULL ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - status = psa_internal_export_key( slot, - buffer, buffer_size, &length, - 0 ); - if( status == PSA_SUCCESS ) - status = psa_save_persistent_key( &slot->attr, - buffer, length ); - - mbedtls_platform_zeroize( buffer, buffer_size ); - mbedtls_free( buffer ); + /* Key material is saved in export representation in the slot, so + * just pass the slot buffer for storage. */ + status = psa_save_persistent_key( &slot->attr, + slot->data.key.data, + slot->data.key.bytes ); } } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ @@ -2179,26 +2217,16 @@ exit: static psa_status_t psa_copy_key_material( const psa_key_slot_t *source, psa_key_slot_t *target ) { - psa_status_t status; - uint8_t *buffer = NULL; - size_t buffer_size = 0; - size_t length; - - buffer_size = PSA_KEY_EXPORT_MAX_SIZE( source->attr.type, - psa_get_key_slot_bits( source ) ); - buffer = mbedtls_calloc( 1, buffer_size ); - if( buffer == NULL ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - status = psa_internal_export_key( source, buffer, buffer_size, &length, 0 ); + psa_status_t status = psa_copy_key_material_into_slot( target, + source->data.key.data, + source->data.key.bytes ); if( status != PSA_SUCCESS ) - goto exit; - target->attr.type = source->attr.type; - status = psa_import_key_into_slot( target, buffer, length ); + return( status ); -exit: - mbedtls_platform_zeroize( buffer, buffer_size ); - mbedtls_free( buffer ); - return( status ); + target->attr.type = source->attr.type; + target->attr.bits = source->attr.bits; + + return( PSA_SUCCESS ); } psa_status_t psa_copy_key( psa_key_handle_t source_handle, diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index 6ee17fce0..8d1f1bb28 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -137,30 +137,26 @@ static inline void psa_key_slot_clear_bits( psa_key_slot_t *slot, */ psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ); -/** Import key data into a slot. +/** Copy key data (in export format) into an empty key slot. * - * `slot->type` must have been set previously. - * This function assumes that the slot does not contain any key material yet. - * On failure, the slot content is unchanged. + * This function assumes that the slot does not contain + * any key material yet. On failure, the slot content is unchanged. * - * Persistent storage is not affected. + * \param[in,out] slot Key slot to copy the key into. + * \param[in] data Buffer containing the key material. + * \param data_length Size of the key buffer. * - * \param[in,out] slot The key slot to import data into. - * Its `type` field must have previously been set to - * the desired key type. - * It must not contain any key material yet. - * \param[in] data Buffer containing the key material to parse and import. - * \param data_length Size of \p data in bytes. - * - * \retval PSA_SUCCESS - * \retval PSA_ERROR_INVALID_ARGUMENT - * \retval PSA_ERROR_NOT_SUPPORTED - * \retval PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_SUCCESS + * The key has been copied successfully. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * Not enough memory was available for allocation of the + * copy buffer. + * \retval #PSA_ERROR_ALREADY_EXISTS + * There was other key material already present in the slot. */ -psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, - const uint8_t *data, - size_t data_length ); - +psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot, + const uint8_t *data, + size_t data_length ); /** Convert an mbed TLS error code to a PSA error code * diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index d6531377b..4040b36b6 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -410,6 +410,34 @@ psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attrib #endif /* PSA_CRYPTO_DRIVER_PRESENT */ } +psa_status_t psa_driver_wrapper_validate_key( const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + size_t *bits ) +{ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + /* Try accelerators in turn */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = test_transparent_validate_key( attributes, + data, + data_length, + bits ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + + return( PSA_ERROR_NOT_SUPPORTED ); +#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + (void) attributes; + (void) data; + (void) data_length; + (void) bits; + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_PRESENT */ +} + /* * Cipher functions */ diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h index 0db15d6c3..b0b483bb5 100644 --- a/library/psa_crypto_driver_wrappers.h +++ b/library/psa_crypto_driver_wrappers.h @@ -43,9 +43,18 @@ psa_status_t psa_driver_wrapper_verify_hash( psa_key_slot_t *slot, const uint8_t *signature, size_t signature_length ); +/* + * Key handling functions + */ + 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_validate_key( const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + size_t *bits ); + /* * Cipher functions */ diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index b7a3c1338..5140772e0 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -141,7 +141,9 @@ static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *slot ) else #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ { - status = psa_import_key_into_slot( slot, key_data, key_data_length ); + status = psa_copy_key_material_into_slot( slot, key_data, key_data_length ); + if( status != PSA_SUCCESS ) + goto exit; } exit: diff --git a/library/psa_crypto_storage.h b/library/psa_crypto_storage.h index de845a748..3def1b5e4 100644 --- a/library/psa_crypto_storage.h +++ b/library/psa_crypto_storage.h @@ -81,9 +81,10 @@ int psa_is_key_present_in_storage( const mbedtls_svc_key_id_t key ); * This function formats the key data and metadata and saves it to a * persistent storage backend. The storage location corresponding to the * key slot must be empty, otherwise this function will fail. This function - * should be called after psa_import_key_into_slot() to ensure the + * should be called after loading the key into an internal slot to ensure the * persistent key is not saved into a storage location corresponding to an - * already occupied non-persistent key, as well as validating the key data. + * already occupied non-persistent key, as well as ensuring the key data is + * validated. * * * \param[in] attr The attributes of the key to save. diff --git a/tests/include/test/drivers/keygen.h b/tests/include/test/drivers/key_management.h similarity index 61% rename from tests/include/test/drivers/keygen.h rename to tests/include/test/drivers/key_management.h index b72c65c78..56f3ef82e 100644 --- a/tests/include/test/drivers/keygen.h +++ b/tests/include/test/drivers/key_management.h @@ -1,5 +1,5 @@ /* - * Test driver for generating keys. + * Test driver for generating and verifying keys. */ /* Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 @@ -17,8 +17,8 @@ * limitations under the License. */ -#ifndef PSA_CRYPTO_TEST_DRIVERS_KEYGEN_H -#define PSA_CRYPTO_TEST_DRIVERS_KEYGEN_H +#ifndef PSA_CRYPTO_TEST_DRIVERS_KEY_MANAGEMENT_H +#define PSA_CRYPTO_TEST_DRIVERS_KEY_MANAGEMENT_H #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" @@ -36,18 +36,19 @@ typedef struct { /* If not PSA_SUCCESS, return this error code instead of processing the * function call. */ psa_status_t forced_status; - /* Count the amount of times one of the keygen driver functions is called. */ + /* Count the amount of times one of the key management driver functions + * is called. */ unsigned long hits; -} test_driver_keygen_hooks_t; +} test_driver_key_management_hooks_t; -#define TEST_DRIVER_KEYGEN_INIT { NULL, 0, PSA_ERROR_NOT_SUPPORTED, 0 } -static inline test_driver_keygen_hooks_t test_driver_keygen_hooks_init( void ) +#define TEST_DRIVER_KEY_MANAGEMENT_INIT { NULL, 0, PSA_ERROR_NOT_SUPPORTED, 0 } +static inline test_driver_key_management_hooks_t test_driver_key_management_hooks_init( void ) { - const test_driver_keygen_hooks_t v = TEST_DRIVER_KEYGEN_INIT; + const test_driver_key_management_hooks_t v = TEST_DRIVER_KEY_MANAGEMENT_INIT; return( v ); } -extern test_driver_keygen_hooks_t test_driver_keygen_hooks; +extern test_driver_key_management_hooks_t test_driver_key_management_hooks; psa_status_t test_transparent_generate_key( const psa_key_attributes_t *attributes, @@ -57,5 +58,10 @@ psa_status_t test_opaque_generate_key( const psa_key_attributes_t *attributes, uint8_t *key, size_t key_size, size_t *key_length ); +psa_status_t test_transparent_validate_key(const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + size_t *bits); + #endif /* PSA_CRYPTO_DRIVER_TEST */ -#endif /* PSA_CRYPTO_TEST_DRIVERS_KEYGEN_H */ +#endif /* PSA_CRYPTO_TEST_DRIVERS_KEY_MANAGEMENT_H */ diff --git a/tests/include/test/drivers/signature.h b/tests/include/test/drivers/signature.h index e41892e77..8abcb111a 100644 --- a/tests/include/test/drivers/signature.h +++ b/tests/include/test/drivers/signature.h @@ -36,7 +36,7 @@ typedef struct { /* If not PSA_SUCCESS, return this error code instead of processing the * function call. */ psa_status_t forced_status; - /* Count the amount of times one of the keygen driver functions is called. */ + /* Count the amount of times one of the signature driver functions is called. */ unsigned long hits; } test_driver_signature_hooks_t; diff --git a/tests/include/test/drivers/test_driver.h b/tests/include/test/drivers/test_driver.h index ee5974217..f26b795dd 100644 --- a/tests/include/test/drivers/test_driver.h +++ b/tests/include/test/drivers/test_driver.h @@ -23,7 +23,7 @@ #define PSA_CRYPTO_TEST_DRIVER_LIFETIME 0x7fffff #include "test/drivers/signature.h" -#include "test/drivers/keygen.h" +#include "test/drivers/key_management.h" #include "test/drivers/cipher.h" #include "test/drivers/size.h" diff --git a/tests/src/drivers/key_management.c b/tests/src/drivers/key_management.c new file mode 100644 index 000000000..9bef4b678 --- /dev/null +++ b/tests/src/drivers/key_management.c @@ -0,0 +1,241 @@ +/* + * Test driver for generating and verifying keys. + * Currently only supports generating and verifying ECC keys. + */ +/* Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST) +#include "psa/crypto.h" +#include "psa_crypto_core.h" +#include "mbedtls/ecp.h" +#include "mbedtls/error.h" + +#include "test/drivers/key_management.h" + +#include "test/random.h" + +#include + +test_driver_key_management_hooks_t test_driver_key_management_hooks = + TEST_DRIVER_KEY_MANAGEMENT_INIT; + +psa_status_t test_transparent_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key, size_t key_size, size_t *key_length ) +{ + ++test_driver_key_management_hooks.hits; + + if( test_driver_key_management_hooks.forced_status != PSA_SUCCESS ) + return( test_driver_key_management_hooks.forced_status ); + + if( test_driver_key_management_hooks.forced_output != NULL ) + { + if( test_driver_key_management_hooks.forced_output_length > key_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + memcpy( key, test_driver_key_management_hooks.forced_output, + test_driver_key_management_hooks.forced_output_length ); + *key_length = test_driver_key_management_hooks.forced_output_length; + return( PSA_SUCCESS ); + } + + /* Copied from psa_crypto.c */ +#if defined(MBEDTLS_ECP_C) + 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_BITS_TO_BYTES( psa_get_key_bits( attributes ) ) ); + 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 ); + } + else +#endif /* MBEDTLS_ECP_C */ + return( PSA_ERROR_NOT_SUPPORTED ); +} + +psa_status_t test_opaque_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key, size_t key_size, size_t *key_length ) +{ + (void) attributes; + (void) key; + (void) key_size; + (void) key_length; + return( PSA_ERROR_NOT_SUPPORTED ); +} + +psa_status_t test_transparent_validate_key(const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + size_t *bits) +{ + ++test_driver_key_management_hooks.hits; + + if( test_driver_key_management_hooks.forced_status != PSA_SUCCESS ) + return( test_driver_key_management_hooks.forced_status ); + +#if defined(MBEDTLS_ECP_C) + psa_key_type_t type = psa_get_key_type( attributes ); + if ( PSA_KEY_TYPE_IS_ECC( type ) ) + { + // Code mostly copied from psa_load_ecp_representation + psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( type ); + mbedtls_ecp_group_id grp_id; + mbedtls_ecp_keypair ecp; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if( psa_get_key_bits( attributes ) == 0 ) + { + // Attempt auto-detect of curve bit size + size_t curve_size = data_length; + + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) && + PSA_KEY_TYPE_ECC_GET_FAMILY( type ) != PSA_ECC_FAMILY_MONTGOMERY ) + { + /* A Weierstrass public key is represented as: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. + * So its data length is 2m+1 where m is the curve size in bits. + */ + if( ( data_length & 1 ) == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + curve_size = data_length / 2; + + /* Montgomery public keys are represented in compressed format, meaning + * their curve_size is equal to the amount of input. */ + + /* Private keys are represented in uncompressed private random integer + * format, meaning their curve_size is equal to the amount of input. */ + } + + grp_id = mbedtls_ecc_group_of_psa( curve, curve_size ); + } + else + { + grp_id = mbedtls_ecc_group_of_psa( curve, + PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) ) ); + } + + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_grp_id( grp_id ); + + 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 ); + + *bits = curve_info->bit_size; + + mbedtls_ecp_keypair_init( &ecp ); + + status = mbedtls_to_psa_error( + mbedtls_ecp_group_load( &ecp.grp, grp_id ) ); + if( status != PSA_SUCCESS ) + goto ecp_exit; + + /* Load the key material. */ + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ) + { + /* Load the public value. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_point_read_binary( &ecp.grp, &ecp.Q, + data, + data_length ) ); + if( status != PSA_SUCCESS ) + goto ecp_exit; + + /* Check that the point is on the curve. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_check_pubkey( &ecp.grp, &ecp.Q ) ); + } + else + { + /* Load and validate the secret value. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_read_key( ecp.grp.id, + &ecp, + data, + data_length ) ); + } + +ecp_exit: + mbedtls_ecp_keypair_free( &ecp ); + return( status ); + } + return( PSA_ERROR_NOT_SUPPORTED ); +#else + (void) data; + (void) data_length; + (void) bits; + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* MBEDTLS_ECP_C */ +} + +#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */ diff --git a/tests/src/drivers/keygen.c b/tests/src/drivers/keygen.c deleted file mode 100644 index f15a4bc9a..000000000 --- a/tests/src/drivers/keygen.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Test driver for generating keys. - * Currently only supports generating ECC keys. - */ -/* Copyright The Mbed TLS Contributors - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST) -#include "psa/crypto.h" -#include "psa_crypto_core.h" -#include "mbedtls/ecp.h" -#include "mbedtls/error.h" - -#include "test/drivers/keygen.h" - -#include "test/random.h" - -#include - -test_driver_keygen_hooks_t test_driver_keygen_hooks = TEST_DRIVER_KEYGEN_INIT; - -psa_status_t test_transparent_generate_key( - const psa_key_attributes_t *attributes, - uint8_t *key, size_t key_size, size_t *key_length ) -{ - ++test_driver_keygen_hooks.hits; - - if( test_driver_keygen_hooks.forced_status != PSA_SUCCESS ) - return( test_driver_keygen_hooks.forced_status ); - - if( test_driver_keygen_hooks.forced_output != NULL ) - { - if( test_driver_keygen_hooks.forced_output_length > key_size ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); - memcpy( key, test_driver_keygen_hooks.forced_output, - test_driver_keygen_hooks.forced_output_length ); - *key_length = test_driver_keygen_hooks.forced_output_length; - return( PSA_SUCCESS ); - } - - /* Copied from psa_crypto.c */ -#if defined(MBEDTLS_ECP_C) - 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_BITS_TO_BYTES( psa_get_key_bits( attributes ) ) ); - 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; - } - - mbedtls_ecp_keypair_free( &ecp ); - return( status ); - } - else -#endif /* MBEDTLS_ECP_C */ - return( PSA_ERROR_NOT_SUPPORTED ); -} - -psa_status_t test_opaque_generate_key( - const psa_key_attributes_t *attributes, - uint8_t *key, size_t key_size, size_t *key_length ) -{ - (void) attributes; - (void) key; - (void) key_size; - (void) key_length; - return( PSA_ERROR_NOT_SUPPORTED ); -} - -#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */ diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.data b/tests/suites/test_suite_psa_crypto_driver_wrappers.data index 7abc25692..1f1ee39cd 100644 --- a/tests/suites/test_suite_psa_crypto_driver_wrappers.data +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.data @@ -40,6 +40,25 @@ generate_key:PSA_ERROR_NOT_SUPPORTED:"":PSA_SUCCESS generate_key through transparent driver: error generate_key:PSA_ERROR_GENERIC_ERROR:"":PSA_ERROR_GENERIC_ERROR +validate key through transparent driver: good private key +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +validate_key:PSA_SUCCESS:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_SUCCESS + +validate key through transparent driver: good public key +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +validate_key:PSA_SUCCESS:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_SUCCESS + +validate key through transparent driver: fallback private key +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +validate_key:PSA_ERROR_NOT_SUPPORTED:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_SUCCESS + +validate key through transparent driver: fallback public key +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +validate_key:PSA_ERROR_NOT_SUPPORTED:PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_SUCCESS + +validate key through transparent driver: error +validate_key:PSA_ERROR_GENERIC_ERROR:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ERROR_GENERIC_ERROR + PSA symmetric encrypt: AES-CTR, 16 bytes, good depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":0:PSA_SUCCESS:PSA_SUCCESS diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/tests/suites/test_suite_psa_crypto_driver_wrappers.function index 951670d56..a0140d2cb 100644 --- a/tests/suites/test_suite_psa_crypto_driver_wrappers.function +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function @@ -132,7 +132,7 @@ void generate_key( int force_status_arg, psa_status_t actual_status; uint8_t actual_output[PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(256)] = {0}; size_t actual_output_length; - test_driver_keygen_hooks = test_driver_keygen_hooks_init(); + test_driver_key_management_hooks = test_driver_key_management_hooks_init(); psa_set_key_type( &attributes, PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_CURVE_SECP_R1 ) ); @@ -142,18 +142,18 @@ void generate_key( int force_status_arg, if( fake_output->len > 0 ) { - expected_output = test_driver_keygen_hooks.forced_output = fake_output->x; - expected_output_length = test_driver_keygen_hooks.forced_output_length = + expected_output = test_driver_key_management_hooks.forced_output = fake_output->x; + expected_output_length = test_driver_key_management_hooks.forced_output_length = fake_output->len; } - test_driver_keygen_hooks.hits = 0; - test_driver_keygen_hooks.forced_status = force_status; + test_driver_key_management_hooks.hits = 0; + test_driver_key_management_hooks.forced_status = force_status; PSA_ASSERT( psa_crypto_init( ) ); actual_status = psa_generate_key( &attributes, &handle ); - TEST_EQUAL( test_driver_keygen_hooks.hits, 1 ); + TEST_EQUAL( test_driver_key_management_hooks.hits, 1 ); TEST_EQUAL( actual_status, expected_status ); if( actual_status == PSA_SUCCESS ) @@ -180,7 +180,41 @@ exit: psa_reset_key_attributes( &attributes ); psa_destroy_key( handle ); PSA_DONE( ); - test_driver_keygen_hooks = test_driver_keygen_hooks_init(); + test_driver_key_management_hooks = test_driver_key_management_hooks_init(); +} +/* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +void validate_key( int force_status_arg, + int key_type_arg, + data_t *key_input, + int expected_status_arg ) +{ + psa_status_t force_status = force_status_arg; + psa_status_t expected_status = expected_status_arg; + psa_key_type_t key_type = key_type_arg; + psa_key_handle_t handle = 0; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t actual_status; + test_driver_key_management_hooks = test_driver_key_management_hooks_init(); + + psa_set_key_type( &attributes, + key_type ); + psa_set_key_bits( &attributes, 0 ); + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT ); + + test_driver_key_management_hooks.forced_status = force_status; + + PSA_ASSERT( psa_crypto_init( ) ); + + actual_status = psa_import_key( &attributes, key_input->x, key_input->len, &handle ); + TEST_EQUAL( test_driver_key_management_hooks.hits, 1 ); + TEST_EQUAL( actual_status, expected_status ); +exit: + psa_reset_key_attributes( &attributes ); + psa_destroy_key( handle ); + PSA_DONE( ); + test_driver_key_management_hooks = test_driver_key_management_hooks_init(); } /* END_CASE */ diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj index 8870cc0c0..801f17c3e 100644 --- a/visualc/VS2010/mbedTLS.vcxproj +++ b/visualc/VS2010/mbedTLS.vcxproj @@ -241,7 +241,7 @@ - +