/* BEGIN_HEADER */ /* The tests in this module verify the contents of key store files. They * access internal key storage functions directly. Some of the tests depend * on the the storage format. On the other hand, these tests treat the storage * subsystem as a black box, and in particular have no reliance on the * internals of the ITS implementation. */ #include #include "test/psa_crypto_helpers.h" #include "psa_crypto_storage.h" #include "mbedtls/md.h" #define PSA_KEY_STORAGE_MAGIC_HEADER "PSA\0KEY" #define PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ( sizeof( PSA_KEY_STORAGE_MAGIC_HEADER ) ) /* Enforce the storage format for keys. The storage format is not a public * documented interface, but it must be preserved between versions so that * upgrades work smoothly, so it's a stable interface nonetheless. */ typedef struct { uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH]; uint8_t version[4]; uint8_t lifetime[sizeof( psa_key_lifetime_t )]; uint8_t type[4]; uint8_t policy[sizeof( psa_key_policy_t )]; uint8_t data_len[4]; uint8_t key_data[]; } psa_persistent_key_storage_format; /* END_HEADER */ /* BEGIN_DEPENDENCIES * depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_PSA_CRYPTO_STORAGE_C * END_DEPENDENCIES */ /* BEGIN_CASE */ void format_storage_data_check( data_t *key_data, data_t *expected_file_data, int key_lifetime, int key_type, int key_usage, int key_alg, int key_alg2 ) { uint8_t *file_data = NULL; size_t file_data_length = key_data->len + sizeof( psa_persistent_key_storage_format ); psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_set_key_lifetime( &attributes, key_lifetime ); psa_set_key_type( &attributes, key_type ); psa_set_key_usage_flags( &attributes, key_usage ); psa_set_key_algorithm( &attributes, key_alg ); psa_set_key_enrollment_algorithm( &attributes, key_alg2 ); ASSERT_ALLOC( file_data, file_data_length ); psa_format_key_data_for_storage( key_data->x, key_data->len, &attributes.core, file_data ); ASSERT_COMPARE( expected_file_data->x, expected_file_data->len, file_data, file_data_length ); exit: mbedtls_free( file_data ); } /* END_CASE */ /* BEGIN_CASE */ void parse_storage_data_check( data_t *file_data, data_t *expected_key_data, int expected_key_lifetime, int expected_key_type, int expected_key_usage, int expected_key_alg, int expected_key_alg2, int expected_status ) { uint8_t *key_data = NULL; size_t key_data_length = 0; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status; status = psa_parse_key_data_from_storage( file_data->x, file_data->len, &key_data, &key_data_length, &attributes.core ); TEST_EQUAL( status, expected_status ); if( status != PSA_SUCCESS ) goto exit; TEST_EQUAL( psa_get_key_lifetime( &attributes ), (psa_key_type_t) expected_key_lifetime ); TEST_EQUAL( psa_get_key_type( &attributes ), (psa_key_type_t) expected_key_type ); TEST_EQUAL( psa_get_key_usage_flags( &attributes ), (uint32_t) expected_key_usage ); TEST_EQUAL( psa_get_key_algorithm( &attributes ), (uint32_t) expected_key_alg ); TEST_EQUAL( psa_get_key_enrollment_algorithm( &attributes ), (uint32_t) expected_key_alg2 ); ASSERT_COMPARE( expected_key_data->x, expected_key_data->len, key_data, key_data_length ); exit: mbedtls_free( key_data ); } /* END_CASE */ /* BEGIN_CASE */ void save_large_persistent_key( int data_length_arg, int expected_status ) { psa_key_id_t key_id = 42; psa_key_handle_t handle = 0; uint8_t *data = NULL; size_t data_length = data_length_arg; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; ASSERT_ALLOC( data, data_length ); PSA_ASSERT( psa_crypto_init() ); psa_set_key_id( &attributes, key_id ); psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA ); TEST_EQUAL( psa_import_key( &attributes, data, data_length, &handle ), expected_status ); if( expected_status == PSA_SUCCESS ) PSA_ASSERT( psa_destroy_key( handle ) ); exit: mbedtls_free( data ); PSA_DONE(); psa_destroy_persistent_key( key_id ); } /* END_CASE */ /* BEGIN_CASE */ void persistent_key_destroy( int key_id_arg, int restart, int first_type_arg, data_t *first_data, int second_type_arg, data_t *second_data ) { psa_key_id_t key_id = key_id_arg; psa_key_handle_t handle = 0; psa_key_type_t first_type = (psa_key_type_t) first_type_arg; psa_key_type_t second_type = (psa_key_type_t) second_type_arg; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; PSA_ASSERT( psa_crypto_init() ); psa_set_key_id( &attributes, key_id ); psa_set_key_type( &attributes, first_type ); PSA_ASSERT( psa_import_key( &attributes, first_data->x, first_data->len, &handle ) ); if( restart ) { psa_close_key( handle ); PSA_DONE(); PSA_ASSERT( psa_crypto_init() ); PSA_ASSERT( psa_open_key( key_id, &handle ) ); } TEST_EQUAL( psa_is_key_present_in_storage( key_id ), 1 ); /* Destroy the key */ PSA_ASSERT( psa_destroy_key( handle ) ); /* Check key slot storage is removed */ TEST_EQUAL( psa_is_key_present_in_storage( key_id ), 0 ); TEST_EQUAL( psa_open_key( key_id, &handle ), PSA_ERROR_DOES_NOT_EXIST ); TEST_EQUAL( handle, 0 ); /* Shutdown and restart */ PSA_DONE(); PSA_ASSERT( psa_crypto_init() ); /* Create another key in the same slot */ psa_set_key_id( &attributes, key_id ); psa_set_key_type( &attributes, second_type ); PSA_ASSERT( psa_import_key( &attributes, second_data->x, second_data->len, &handle ) ); PSA_ASSERT( psa_destroy_key( handle ) ); exit: PSA_DONE(); psa_destroy_persistent_key( key_id ); } /* END_CASE */ /* BEGIN_CASE */ void persistent_key_import( int key_id_arg, int type_arg, data_t *data, int restart, int expected_status ) { psa_key_id_t key_id = (psa_key_id_t) key_id_arg; psa_key_type_t type = (psa_key_type_t) type_arg; psa_key_handle_t handle = 0; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; PSA_ASSERT( psa_crypto_init() ); psa_set_key_id( &attributes, key_id ); psa_set_key_type( &attributes, type ); TEST_EQUAL( psa_import_key( &attributes, data->x, data->len, &handle ), expected_status ); if( expected_status != PSA_SUCCESS ) { TEST_EQUAL( psa_is_key_present_in_storage( key_id ), 0 ); goto exit; } if( restart ) { psa_close_key( handle ); PSA_DONE(); PSA_ASSERT( psa_crypto_init() ); PSA_ASSERT( psa_open_key( key_id, &handle ) ); } psa_reset_key_attributes( &attributes ); PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) ); TEST_EQUAL( psa_get_key_id( &attributes ), key_id ); TEST_EQUAL( psa_get_key_lifetime( &attributes ), PSA_KEY_LIFETIME_PERSISTENT ); TEST_EQUAL( psa_get_key_type( &attributes ), type ); TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 ); TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 ); PSA_ASSERT( psa_destroy_key( handle ) ); exit: psa_reset_key_attributes( &attributes ); psa_destroy_persistent_key( key_id ); PSA_DONE(); } /* END_CASE */ /* BEGIN_CASE */ void import_export_persistent_key( data_t *data, int type_arg, int expected_bits, int restart, int key_not_exist ) { psa_key_id_t key_id = 42; psa_key_type_t type = (psa_key_type_t) type_arg; psa_key_handle_t handle = 0; unsigned char *exported = NULL; size_t export_size = data->len; size_t exported_length; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; ASSERT_ALLOC( exported, export_size ); PSA_ASSERT( psa_crypto_init( ) ); psa_set_key_id( &attributes, key_id ); psa_set_key_type( &attributes, type ); psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT ); /* Import the key */ PSA_ASSERT( psa_import_key( &attributes, data->x, data->len, &handle ) ); if( restart ) { psa_close_key( handle ); PSA_DONE(); PSA_ASSERT( psa_crypto_init() ); PSA_ASSERT( psa_open_key( key_id, &handle ) ); } /* Test the key information */ psa_reset_key_attributes( &attributes ); PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) ); TEST_EQUAL( psa_get_key_id( &attributes ), key_id ); TEST_EQUAL( psa_get_key_lifetime( &attributes ), PSA_KEY_LIFETIME_PERSISTENT ); TEST_EQUAL( psa_get_key_type( &attributes ), type ); TEST_EQUAL( psa_get_key_bits( &attributes ), (size_t) expected_bits ); TEST_EQUAL( psa_get_key_usage_flags( &attributes ), PSA_KEY_USAGE_EXPORT ); TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 ); TEST_EQUAL( psa_is_key_present_in_storage( key_id ), 1 ); if( key_not_exist ) { psa_destroy_persistent_key( key_id ); } /* Export the key */ PSA_ASSERT( psa_export_key( handle, exported, export_size, &exported_length ) ); ASSERT_COMPARE( data->x, data->len, exported, exported_length ); /* Destroy the key */ PSA_ASSERT( psa_destroy_key( handle ) ); TEST_EQUAL( psa_is_key_present_in_storage( key_id ), 0 ); exit: psa_reset_key_attributes( &attributes ); mbedtls_free( exported ); PSA_DONE( ); psa_destroy_persistent_key( key_id ); } /* END_CASE */