diff --git a/include/psa/crypto_platform.h b/include/psa/crypto_platform.h index 9cc27f6798..4a6328a152 100644 --- a/include/psa/crypto_platform.h +++ b/include/psa/crypto_platform.h @@ -49,34 +49,6 @@ #define inline __inline #endif -/* Integral type representing a key handle. */ -typedef uint16_t psa_key_handle_t; -#define PSA_KEY_HANDLE_INIT ( (psa_key_handle_t)0 ) - -/** Check whether a handle is null. - * - * \param handle Key handle. - * - * \return Non-zero if the key handle is null, zero otherwise. - */ -static inline int psa_key_handle_is_null( psa_key_handle_t handle ) -{ - return( handle == 0 ); -} - -/** Compare two handles. - * - * \param handle1 First handle. - * \param handle2 Second handle. - * - * \return Non-zero if the two handles are equal, zero otherwise. - */ -static inline int psa_key_handle_equal( psa_key_handle_t handle1, - psa_key_handle_t handle2 ) -{ - return( handle1 == handle2 ); -} - #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) /* Building for the PSA Crypto service on a PSA platform, a key owner is a PSA diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h index 923b02b53b..b5e68d4bde 100644 --- a/include/psa/crypto_types.h +++ b/include/psa/crypto_types.h @@ -247,6 +247,12 @@ typedef struct #endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ +/* + * To support temporary both openless APIs and psa_open_key(), define + * psa_key_handle_t to be equal to mbedtls_svc_key_id_t. + */ +typedef mbedtls_svc_key_id_t psa_key_handle_t; + /**@}*/ /** \defgroup policy Key policies diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 3eb64d8cce..5061ab4c93 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1700,6 +1700,17 @@ static inline int mbedtls_svc_key_id_equal( mbedtls_svc_key_id_t id1, return( id1 == id2 ); } +/** Check whether a key identifier is null. + * + * \param key Key identifier. + * + * \return Non-zero if the key identifier is null, zero otherwise. + */ +static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) +{ + return( key == 0 ); +} + #else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ #define MBEDTLS_SVC_KEY_ID_INIT ( (mbedtls_svc_key_id_t){ 0, 0 } ) @@ -1732,8 +1743,45 @@ static inline int mbedtls_svc_key_id_equal( mbedtls_svc_key_id_t id1, mbedtls_key_owner_id_equal( id1.owner, id2.owner ) ); } +/** Check whether a key identifier is null. + * + * \param key Key identifier. + * + * \return Non-zero if the key identifier is null, zero otherwise. + */ +static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) +{ + return( ( key.key_id == 0 ) && ( key.owner == 0 ) ); +} + #endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ +#define PSA_KEY_HANDLE_INIT MBEDTLS_SVC_KEY_ID_INIT + +/** Compare two handles. + * + * \param handle1 First handle. + * \param handle2 Second handle. + * + * \return Non-zero if the two handles are equal, zero otherwise. + */ +static inline int psa_key_handle_equal( psa_key_handle_t handle1, + psa_key_handle_t handle2 ) +{ + return( mbedtls_svc_key_id_equal( handle1, handle2 ) ); +} + +/** Check wether an handle is null. + * + * \param handle Handle + * + * \return Non-zero if the handle is null, zero otherwise. + */ +static inline int psa_key_handle_is_null( psa_key_handle_t handle ) +{ + return( mbedtls_svc_key_id_is_null( handle ) ); +} + /**@}*/ /** \defgroup policy Key policies diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 5d9b34e77e..f8a8c0ab7b 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1861,7 +1861,7 @@ static psa_status_t psa_start_key_creation( if( status != PSA_SUCCESS ) return( status ); - status = psa_get_empty_key_slot( handle, &volatile_key_id, p_slot ); + status = psa_get_empty_key_slot( &volatile_key_id, p_slot ); if( status != PSA_SUCCESS ) return( status ); slot = *p_slot; @@ -1870,9 +1870,19 @@ static psa_status_t psa_start_key_creation( * creation mechanism to verify that this information is correct. * It's automatically correct for mechanisms that use the bit-size as * an input (generate, device) but not for those where the bit-size - * is optional (import, copy). */ + * is optional (import, copy). In case of a volatile key, assign it the + * volatile key identifier associated to the slot returned to contain its + * definition. */ slot->attr = attributes->core; + if( PSA_KEY_LIFETIME_IS_VOLATILE( slot->attr.lifetime ) ) + { +#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) + slot->attr.id = volatile_key_id; +#else + slot->attr.id.key_id = volatile_key_id; +#endif + } /* Erase external-only flags from the internal copy. To access * external-only flags, query `attributes`. Thanks to the check @@ -1928,7 +1938,9 @@ static psa_status_t psa_start_key_creation( } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - return( status ); + *handle = slot->attr.id; + + return( PSA_SUCCESS ); } /** Finalize the creation of a key once its key material has been set. diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index 6303473d9d..8ef851bddf 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -64,36 +64,41 @@ psa_status_t psa_validate_key_id( mbedtls_svc_key_id_t key, int vendor_ok ) ( key_id <= PSA_KEY_ID_VENDOR_MAX ) ) return( PSA_SUCCESS ); - return( PSA_ERROR_INVALID_ARGUMENT ); + return( PSA_ERROR_INVALID_HANDLE ); } -/* Access a key slot at the given handle. The handle of a key slot is - * the index of the slot in the global slot array, plus one so that handles - * start at 1 and not 0. */ -psa_status_t psa_get_key_slot( psa_key_handle_t handle, - psa_key_slot_t **p_slot ) +static psa_key_slot_t* psa_get_slot_from_volatile_key_id( + mbedtls_svc_key_id_t key ) { - psa_key_slot_t *slot = NULL; + psa_key_slot_t *slot; + psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key ); - if( ! global_data.key_slots_initialized ) - return( PSA_ERROR_BAD_STATE ); + if( ( key_id < PSA_KEY_ID_VOLATILE_MIN ) || + ( key_id > PSA_KEY_ID_VOLATILE_MAX ) ) + return( NULL ); - /* 0 is not a valid handle under any circumstance. This - * implementation provides slots number 1 to N where N is the - * number of available slots. */ - if( psa_key_handle_is_null( handle ) || - ( handle > ARRAY_LENGTH( global_data.key_slots ) ) ) - return( PSA_ERROR_INVALID_HANDLE ); - slot = &global_data.key_slots[handle - 1]; + slot = &global_data.key_slots[ key_id - PSA_KEY_ID_VOLATILE_MIN ]; - /* If the slot isn't occupied, the handle is invalid. */ - if( ! psa_is_key_slot_occupied( slot ) ) - return( PSA_ERROR_INVALID_HANDLE ); - - *p_slot = slot; - return( PSA_SUCCESS ); + return( mbedtls_svc_key_id_equal( key, slot->attr.id ) ? slot : NULL ); } +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) +static psa_key_slot_t* psa_get_slot_from_key_id( + mbedtls_svc_key_id_t key ) +{ + psa_key_slot_t *slot = &global_data.key_slots[ PSA_KEY_SLOT_COUNT ]; + + while( slot > &global_data.key_slots[ 0 ] ) + { + slot--; + if( mbedtls_svc_key_id_equal( key, slot->attr.id ) ) + return( slot ); + } + + return( NULL ); +} +#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + psa_status_t psa_initialize_key_slots( void ) { /* Nothing to do: program startup and psa_wipe_all_key_slots() both @@ -115,8 +120,7 @@ void psa_wipe_all_key_slots( void ) global_data.key_slots_initialized = 0; } -psa_status_t psa_get_empty_key_slot( psa_key_handle_t *handle, - psa_key_id_t *volatile_key_id, +psa_status_t psa_get_empty_key_slot( psa_key_id_t *volatile_key_id, psa_key_slot_t **p_slot ) { size_t slot_idx; @@ -129,7 +133,6 @@ psa_status_t psa_get_empty_key_slot( psa_key_handle_t *handle, *p_slot = &global_data.key_slots[ slot_idx - 1 ]; if( ! psa_is_key_slot_occupied( *p_slot ) ) { - *handle = (psa_key_handle_t)slot_idx; *volatile_key_id = PSA_KEY_ID_VOLATILE_MIN + ( (psa_key_id_t)slot_idx ) - 1; @@ -177,8 +180,50 @@ exit: psa_free_persistent_key_data( key_data, key_data_length ); return( status ); } +#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ + +psa_status_t psa_get_key_slot( mbedtls_svc_key_id_t key, + psa_key_slot_t **p_slot ) +{ + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + + *p_slot = NULL; + if( ! global_data.key_slots_initialized ) + return( PSA_ERROR_BAD_STATE ); + + status = psa_validate_key_id( key, 1 ); + if( status != PSA_SUCCESS ) + return( status ); + + *p_slot = psa_get_slot_from_volatile_key_id( key ); + if( *p_slot != NULL ) + return( PSA_SUCCESS ); + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + psa_key_id_t volatile_key_id; + + *p_slot = psa_get_slot_from_key_id( key ); + if( *p_slot != NULL ) + return( PSA_SUCCESS ); + + status = psa_get_empty_key_slot( &volatile_key_id, p_slot ); + if( status != PSA_SUCCESS ) + return( status ); + + (*p_slot)->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT; + (*p_slot)->attr.id = key; + + status = psa_load_persistent_key_into_slot( *p_slot ); + if( status != PSA_SUCCESS ) + psa_wipe_key_slot( *p_slot ); + + return( status ); +#else + return( PSA_ERROR_DOES_NOT_EXIST ); #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ +} + psa_status_t psa_validate_key_location( psa_key_lifetime_t lifetime, psa_se_drv_table_entry_t **p_drv ) { @@ -226,29 +271,18 @@ psa_status_t psa_open_key( mbedtls_svc_key_id_t key, psa_key_handle_t *handle ) { #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) psa_status_t status; - psa_key_id_t volatile_key_id; psa_key_slot_t *slot; - *handle = 0; - - status = psa_validate_key_id( key, 1 ); - if( status != PSA_SUCCESS ) - return( status ); - - status = psa_get_empty_key_slot( handle, &volatile_key_id, &slot ); - if( status != PSA_SUCCESS ) - return( status ); - - slot->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT; - slot->attr.id = key; - - status = psa_load_persistent_key_into_slot( slot ); + status = psa_get_key_slot( key, &slot ); if( status != PSA_SUCCESS ) { - psa_wipe_key_slot( slot ); *handle = PSA_KEY_HANDLE_INIT; + return( status ); } - return( status ); + + *handle = key; + + return( PSA_SUCCESS ); #else /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ (void) key; diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h index d649f53a7c..98a1ce7535 100644 --- a/library/psa_crypto_slot_management.h +++ b/library/psa_crypto_slot_management.h @@ -22,6 +22,7 @@ #define PSA_CRYPTO_SLOT_MANAGEMENT_H #include "psa/crypto.h" +#include "psa_crypto_core.h" #include "psa_crypto_se.h" /* Number of key slots (plus one because 0 is not used). @@ -45,21 +46,38 @@ */ #define PSA_KEY_ID_VOLATILE_MAX PSA_KEY_ID_VENDOR_MAX -/** Access a key slot at the given handle. +/** Retrieve the description of a key given its identifier. * - * \param handle Key handle to query. + * The descriptions of volatile keys and loaded persistent keys are + * stored in key slots. This function returns a pointer to the key slot + * containing the description of a key given its identifier. + * + * In case of a persistent key, the function loads the description of the key + * into a key slot if not already done. + * + * \param key Key identifier to query. * \param[out] p_slot On success, `*p_slot` contains a pointer to the - * key slot in memory designated by \p handle. + * key slot containing the description of the key + * identified by \p key. * - * \retval PSA_SUCCESS - * Success: \p handle is a handle to `*p_slot`. Note that `*p_slot` - * may be empty or occupied. - * \retval PSA_ERROR_INVALID_HANDLE - * \p handle is out of range or is not in use. - * \retval PSA_ERROR_BAD_STATE + * \retval #PSA_SUCCESS + * The pointer to the key slot containing the description of the key + * identified by \p key was returned. + * \retval #PSA_ERROR_BAD_STATE * The library has not been initialized. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p key is not a valid key identifier. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \p key is a persistent key identifier. The implementation does not + * have sufficient resources to load the persistent key. This can be + * due to a lack of empty key slot, or available memory. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * There is no key with key identifier \p key. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_DATA_CORRUPT */ -psa_status_t psa_get_key_slot( psa_key_handle_t handle, +psa_status_t psa_get_key_slot( mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot ); /** Initialize the key slot structures. @@ -79,8 +97,6 @@ void psa_wipe_all_key_slots( void ); * This function returns a key slot that is available for use and is in its * ground state (all-bits-zero). * - * \param[out] handle On success, a slot number that can be used - * as a handle to the slot. * \param[out] volatile_key_id On success, volatile key identifier * associated to the returned slot. * \param[out] p_slot On success, a pointer to the slot. @@ -89,8 +105,7 @@ void psa_wipe_all_key_slots( void ); * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_BAD_STATE */ -psa_status_t psa_get_empty_key_slot( psa_key_handle_t *handle, - psa_key_id_t *volatile_key_id, +psa_status_t psa_get_empty_key_slot( psa_key_id_t *volatile_key_id, psa_key_slot_t **p_slot ); /** Test whether a lifetime designates a key in an external cryptoprocessor. diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 16bd619523..246d71a8d8 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -3577,8 +3577,10 @@ exit: if( ( status != PSA_SUCCESS ) && ( opt.query_config_mode == DFL_QUERY_CONFIG_MODE ) ) { - mbedtls_printf( "Failed to destroy key slot %u - error was %d", - (unsigned) slot, (int) status ); + mbedtls_printf( "Failed to destroy key slot %u-%u - error was %d", + MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( slot ), + MBEDTLS_SVC_KEY_ID_GET_KEY_ID( slot ), + (int) status ); if( ret == 0 ) ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index fce2e22c63..eb4ab0d8ff 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -4518,8 +4518,10 @@ exit: if( ( status != PSA_SUCCESS ) && ( opt.query_config_mode == DFL_QUERY_CONFIG_MODE ) ) { - mbedtls_printf( "Failed to destroy key slot %u - error was %d", - (unsigned) psk_slot, (int) status ); + mbedtls_printf( "Failed to destroy key slot %u-%u - error was %d", + MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( psk_slot ), + MBEDTLS_SVC_KEY_ID_GET_KEY_ID( psk_slot ), + (int) status ); } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED && diff --git a/tests/suites/test_suite_psa_crypto_init.function b/tests/suites/test_suite_psa_crypto_init.function index c9fdcd1803..d587886dcb 100644 --- a/tests/suites/test_suite_psa_crypto_init.function +++ b/tests/suites/test_suite_psa_crypto_init.function @@ -185,7 +185,7 @@ void validate_module_init_key_based( int count ) psa_status_t status; uint8_t data[10] = { 0 }; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_handle_t handle = 0xdead; + psa_key_handle_t handle = mbedtls_svc_key_id_make( 0xdead, 0xdead ); int i; for( i = 0; i < count; i++ ) diff --git a/tests/suites/test_suite_psa_crypto_slot_management.function b/tests/suites/test_suite_psa_crypto_slot_management.function index a99f7de5ed..c688474aa5 100644 --- a/tests/suites/test_suite_psa_crypto_slot_management.function +++ b/tests/suites/test_suite_psa_crypto_slot_management.function @@ -2,6 +2,7 @@ #include #include "test/psa_crypto_helpers.h" +#include "psa_crypto_slot_management.h" #include "psa_crypto_storage.h" typedef enum @@ -389,7 +390,7 @@ void open_fail( int id_arg, { mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, id_arg ); psa_status_t expected_status = expected_status_arg; - psa_key_handle_t handle = 0xdead; + psa_key_handle_t handle = mbedtls_svc_key_id_make( 0xdead, 0xdead ); PSA_ASSERT( psa_crypto_init( ) ); @@ -409,7 +410,7 @@ void create_fail( int lifetime_arg, int id_arg, mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, id_arg ); psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_status_t expected_status = expected_status_arg; - psa_key_handle_t handle = 0xdead; + psa_key_handle_t handle = mbedtls_svc_key_id_make( 0xdead, 0xdead ); uint8_t material[1] = {'k'}; TEST_USES_KEY_ID( id ); @@ -583,7 +584,7 @@ void copy_to_occupied( int source_lifetime_arg, int source_id_arg, psa_algorithm_t target_alg = target_alg_arg; psa_key_handle_t target_handle = PSA_KEY_HANDLE_INIT; psa_key_type_t target_type = target_type_arg; - psa_key_handle_t new_handle = 0xdead; + psa_key_handle_t new_handle = mbedtls_svc_key_id_make( 0xdead, 0xdead ); uint8_t *export_buffer = NULL; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_key_attributes_t attributes1 = PSA_KEY_ATTRIBUTES_INIT; @@ -677,6 +678,7 @@ void invalid_handle( int handle_construction, { psa_key_handle_t valid_handle = PSA_KEY_HANDLE_INIT; psa_key_handle_t invalid_handle = PSA_KEY_HANDLE_INIT; + psa_key_id_t key_id; psa_status_t close_status = close_status_arg; psa_status_t usage_status = usage_status_arg; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; @@ -700,14 +702,26 @@ void invalid_handle( int handle_construction, invalid_handle = PSA_KEY_HANDLE_INIT; break; case INVALID_HANDLE_UNOPENED: - /* We can't easily construct a handle that's never been opened - * without knowing how the implementation constructs handle - * values. The current test code assumes that valid handles - * are in a range between 1 and some maximum. */ - if( valid_handle == 1 ) - invalid_handle = 2; + + /* + * MBEDTLS_SVC_KEY_ID_GET_KEY_ID( valid_handle ) is a volatile + * key identifier as the imported key is a volatile key. Volatile + * key identifiers are in the range from PSA_KEY_ID_VOLATILE_MIN + * to PSA_KEY_ID_VOLATILE_MAX included. Thus pick a key identifier + * in the range from PSA_KEY_ID_VOLATILE_MIN to + * PSA_KEY_ID_VOLATILE_MAX different from + * MBEDTLS_SVC_KEY_ID_GET_KEY_ID( valid_handle ) to build an + * unopened and thus invalid identifier. + */ + + if( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( valid_handle ) == + PSA_KEY_ID_VOLATILE_MIN ) + key_id = PSA_KEY_ID_VOLATILE_MIN + 1; else - invalid_handle = valid_handle - 1; + key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID( valid_handle ) - 1; + + invalid_handle = + mbedtls_svc_key_id_make( 0, key_id ); break; case INVALID_HANDLE_CLOSED: PSA_ASSERT( psa_import_key( &attributes, @@ -716,7 +730,8 @@ void invalid_handle( int handle_construction, PSA_ASSERT( psa_destroy_key( invalid_handle ) ); break; case INVALID_HANDLE_HUGE: - invalid_handle = (psa_key_handle_t) ( -1 ); + invalid_handle = + mbedtls_svc_key_id_make( 0, PSA_KEY_ID_VENDOR_MAX + 1 ); break; default: TEST_ASSERT( ! "unknown handle construction" );