/* BEGIN_HEADER */ #include "psa/crypto_se_driver.h" #include "psa_crypto_se.h" #include "psa_crypto_storage.h" /** The location and lifetime used for tests that use a single driver. */ #define TEST_DRIVER_LOCATION 1 #define TEST_SE_PERSISTENT_LIFETIME \ ( PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( \ PSA_KEY_PERSISTENCE_DEFAULT, TEST_DRIVER_LOCATION ) ) static struct { uint16_t called; psa_key_location_t location; psa_status_t return_value; } mock_init_data; static struct { uint16_t called; psa_key_slot_number_t key_slot; psa_key_attributes_t attributes; size_t pubkey_size; psa_status_t return_value; } mock_generate_data; static struct { uint16_t called; psa_key_slot_number_t key_slot; psa_key_attributes_t attributes; size_t bits; size_t data_length; psa_status_t return_value; } mock_import_data; static struct { uint16_t called; psa_key_slot_number_t slot_number; size_t data_size; psa_status_t return_value; } mock_export_data; static struct { uint16_t called; psa_key_slot_number_t slot_number; size_t data_size; psa_status_t return_value; } mock_export_public_data; static struct { uint16_t called; psa_key_slot_number_t key_slot; psa_algorithm_t alg; size_t hash_length; size_t signature_size; psa_status_t return_value; } mock_sign_data; static struct { uint16_t called; psa_key_slot_number_t key_slot; psa_algorithm_t alg; size_t hash_length; size_t signature_length; psa_status_t return_value; } mock_verify_data; static struct { uint16_t called; psa_status_t return_value; } mock_allocate_data; static struct { uint16_t called; psa_key_slot_number_t slot_number; psa_status_t return_value; } mock_destroy_data; #define MAX_KEY_ID_FOR_TEST 10 static void psa_purge_storage( void ) { psa_key_id_t id; psa_key_location_t location; /* The tests may have potentially created key ids from 1 to * MAX_KEY_ID_FOR_TEST. In addition, run the destroy function on key id * 0, which file-based storage uses as a temporary file. */ for( id = 0; id <= MAX_KEY_ID_FOR_TEST; id++ ) psa_destroy_persistent_key( mbedtls_svc_key_id_make( 1, id ) ); /* Purge the transaction file. */ psa_crypto_stop_transaction( ); /* Purge driver persistent data. */ for( location = 0; location < PSA_MAX_SE_LOCATION; location++ ) psa_destroy_se_persistent_data( location ); } static void mock_teardown( void ) { memset( &mock_init_data, 0, sizeof( mock_init_data ) ); memset( &mock_import_data, 0, sizeof( mock_import_data ) ); memset( &mock_export_data, 0, sizeof( mock_export_data ) ); memset( &mock_export_public_data, 0, sizeof( mock_export_public_data ) ); memset( &mock_sign_data, 0, sizeof( mock_sign_data ) ); memset( &mock_verify_data, 0, sizeof( mock_verify_data ) ); memset( &mock_allocate_data, 0, sizeof( mock_allocate_data ) ); memset( &mock_destroy_data, 0, sizeof( mock_destroy_data ) ); memset( &mock_generate_data, 0, sizeof( mock_generate_data ) ); psa_purge_storage( ); } static psa_status_t mock_init( psa_drv_se_context_t *drv_context, void *persistent_data, psa_key_location_t location ) { (void) drv_context; (void) persistent_data; mock_init_data.called++; mock_init_data.location = location; return( mock_init_data.return_value ); } static psa_status_t mock_generate( psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, const psa_key_attributes_t *attributes, uint8_t *pubkey, size_t pubkey_size, size_t *pubkey_length ) { (void) drv_context; (void) pubkey; (void) pubkey_length; mock_generate_data.called++; mock_generate_data.key_slot = key_slot; mock_generate_data.attributes = *attributes; mock_generate_data.pubkey_size = pubkey_size; return( mock_generate_data.return_value ); } static psa_status_t mock_import( psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, size_t *bits ) { (void) drv_context; (void) data; *bits = mock_import_data.bits; mock_import_data.called++; mock_import_data.key_slot = key_slot; mock_import_data.attributes = *attributes; mock_import_data.data_length = data_length; return( mock_import_data.return_value ); } psa_status_t mock_export( psa_drv_se_context_t *context, psa_key_slot_number_t slot_number, uint8_t *p_data, size_t data_size, size_t *p_data_length ) { (void) context; (void) p_data; (void) p_data_length; mock_export_data.called++; mock_export_data.slot_number = slot_number; mock_export_data.data_size = data_size; return( mock_export_data.return_value ); } psa_status_t mock_export_public( psa_drv_se_context_t *context, psa_key_slot_number_t slot_number, uint8_t *p_data, size_t data_size, size_t *p_data_length ) { (void) context; (void) p_data; (void) p_data_length; mock_export_public_data.called++; mock_export_public_data.slot_number = slot_number; mock_export_public_data.data_size = data_size; return( mock_export_public_data.return_value ); } psa_status_t mock_sign( psa_drv_se_context_t *context, psa_key_slot_number_t key_slot, psa_algorithm_t alg, const uint8_t *p_hash, size_t hash_length, uint8_t *p_signature, size_t signature_size, size_t *p_signature_length ) { (void) context; (void) p_hash; (void) p_signature; (void) p_signature_length; mock_sign_data.called++; mock_sign_data.key_slot = key_slot; mock_sign_data.alg = alg; mock_sign_data.hash_length = hash_length; mock_sign_data.signature_size = signature_size; return mock_sign_data.return_value; } psa_status_t mock_verify( psa_drv_se_context_t *context, psa_key_slot_number_t key_slot, psa_algorithm_t alg, const uint8_t *p_hash, size_t hash_length, const uint8_t *p_signature, size_t signature_length ) { (void) context; (void) p_hash; (void) p_signature; mock_verify_data.called++; mock_verify_data.key_slot = key_slot; mock_verify_data.alg = alg; mock_verify_data.hash_length = hash_length; mock_verify_data.signature_length = signature_length; return mock_verify_data.return_value; } psa_status_t mock_allocate( psa_drv_se_context_t *drv_context, void *persistent_data, const psa_key_attributes_t *attributes, psa_key_creation_method_t method, psa_key_slot_number_t *key_slot ) { (void) drv_context; (void) persistent_data; (void) attributes; (void) method; (void) key_slot; mock_allocate_data.called++; *key_slot = 0; return( mock_allocate_data.return_value ); } psa_status_t mock_destroy( psa_drv_se_context_t *context, void *persistent_data, psa_key_slot_number_t slot_number ) { (void) context; (void) persistent_data; mock_destroy_data.called++; mock_destroy_data.slot_number = slot_number; return( mock_destroy_data.return_value ); } /* END_HEADER */ /* BEGIN_DEPENDENCIES * depends_on:MBEDTLS_PSA_CRYPTO_SE_C * END_DEPENDENCIES */ /* BEGIN_CASE */ void mock_init( int location_arg, int expected_register_status_arg, int driver_status_arg, int expected_psa_status_arg, int expected_called ) { psa_key_location_t location = location_arg; psa_status_t expected_register_status = expected_register_status_arg; psa_status_t driver_status = driver_status_arg; psa_status_t expected_psa_status = expected_psa_status_arg; psa_drv_se_t driver = { .hal_version = PSA_DRV_SE_HAL_VERSION, .p_init = mock_init, }; int psa_crypto_init_called = 0; mock_init_data.return_value = driver_status; TEST_EQUAL( psa_register_se_driver( location, &driver ), expected_register_status ); psa_crypto_init_called = 1; TEST_EQUAL( psa_crypto_init( ), expected_psa_status ); TEST_EQUAL( mock_init_data.called, expected_called ); if( expected_called ) TEST_EQUAL( mock_init_data.location, location ); exit: if( psa_crypto_init_called ) PSA_DONE( ); mock_teardown( ); } /* END_CASE */ /* BEGIN_CASE */ void mock_import( int mock_alloc_return_value, int mock_import_return_value, int bits, int expected_result ) { psa_drv_se_t driver; psa_drv_se_key_management_t key_management; psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime ); mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 ); mbedtls_svc_key_id_t returned_id; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; const uint8_t key_material[3] = {0xfa, 0xca, 0xde}; mock_allocate_data.return_value = mock_alloc_return_value; mock_import_data.return_value = mock_import_return_value; mock_import_data.bits = bits; memset( &driver, 0, sizeof( driver ) ); memset( &key_management, 0, sizeof( key_management ) ); driver.hal_version = PSA_DRV_SE_HAL_VERSION; driver.key_management = &key_management; key_management.p_import = mock_import; key_management.p_destroy = mock_destroy; key_management.p_allocate = mock_allocate; PSA_ASSERT( psa_register_se_driver( location, &driver ) ); PSA_ASSERT( psa_crypto_init( ) ); psa_set_key_id( &attributes, id ); psa_set_key_lifetime( &attributes, lifetime ); psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT ); psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA ); TEST_ASSERT( psa_import_key( &attributes, key_material, sizeof( key_material ), &returned_id ) == expected_result ); TEST_ASSERT( mock_allocate_data.called == 1 ); TEST_ASSERT( mock_import_data.called == ( mock_alloc_return_value == PSA_SUCCESS? 1 : 0 ) ); if( mock_alloc_return_value == PSA_SUCCESS ) { TEST_ASSERT( mbedtls_svc_key_id_equal( mock_import_data.attributes.core.id, id ) ); } else { TEST_ASSERT( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( mock_import_data.attributes.core.id ) == 0 ); TEST_ASSERT( MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( mock_import_data.attributes.core.id ) == 0 ); } TEST_ASSERT( mock_import_data.attributes.core.lifetime == ( mock_alloc_return_value == PSA_SUCCESS? lifetime : 0 ) ); TEST_ASSERT( mock_import_data.attributes.core.policy.usage == ( mock_alloc_return_value == PSA_SUCCESS? PSA_KEY_USAGE_EXPORT : 0 ) ); TEST_ASSERT( mock_import_data.attributes.core.type == ( mock_alloc_return_value == PSA_SUCCESS? PSA_KEY_TYPE_RAW_DATA : 0 ) ); if( expected_result == PSA_SUCCESS ) { PSA_ASSERT( psa_destroy_key( id ) ); TEST_ASSERT( mock_destroy_data.called == 1 ); } exit: PSA_DONE( ); mock_teardown( ); } /* END_CASE */ /* BEGIN_CASE */ void mock_export( int mock_export_return_value, int expected_result ) { psa_drv_se_t driver; psa_drv_se_key_management_t key_management; psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime ); mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 ); mbedtls_svc_key_id_t returned_id; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; const uint8_t key_material[3] = {0xfa, 0xca, 0xde}; uint8_t exported[sizeof( key_material )]; size_t exported_length; mock_export_data.return_value = mock_export_return_value; memset( &driver, 0, sizeof( driver ) ); memset( &key_management, 0, sizeof( key_management ) ); driver.hal_version = PSA_DRV_SE_HAL_VERSION; driver.key_management = &key_management; driver.p_init = mock_init; key_management.p_import = mock_import; key_management.p_export = mock_export; key_management.p_destroy = mock_destroy; key_management.p_allocate = mock_allocate; PSA_ASSERT( psa_register_se_driver( location, &driver ) ); PSA_ASSERT( psa_crypto_init( ) ); psa_set_key_id( &attributes, id ); psa_set_key_lifetime( &attributes, lifetime ); psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT ); psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA ); PSA_ASSERT( psa_import_key( &attributes, key_material, sizeof( key_material ), &returned_id ) ); TEST_ASSERT( psa_export_key( id, exported, sizeof( exported ), &exported_length ) == expected_result ); TEST_ASSERT( mock_export_data.called == 1 ); PSA_ASSERT( psa_destroy_key( id ) ); TEST_ASSERT( mock_destroy_data.called == 1 ); exit: PSA_DONE( ); mock_teardown( ); } /* END_CASE */ /* BEGIN_CASE */ void mock_generate( int mock_alloc_return_value, int mock_generate_return_value, int expected_result ) { psa_drv_se_t driver; psa_drv_se_key_management_t key_management; psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime ); mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 ); mbedtls_svc_key_id_t returned_id; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; mock_allocate_data.return_value = mock_alloc_return_value; mock_generate_data.return_value = mock_generate_return_value; memset( &driver, 0, sizeof( driver ) ); memset( &key_management, 0, sizeof( key_management ) ); driver.hal_version = PSA_DRV_SE_HAL_VERSION; driver.key_management = &key_management; key_management.p_generate = mock_generate; key_management.p_destroy = mock_destroy; key_management.p_allocate = mock_allocate; PSA_ASSERT( psa_register_se_driver( location, &driver ) ); PSA_ASSERT( psa_crypto_init( ) ); psa_set_key_id( &attributes, id ); psa_set_key_lifetime( &attributes, lifetime ); psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT ); psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA ); psa_set_key_bits( &attributes, 8 ); TEST_ASSERT( psa_generate_key( &attributes, &returned_id) == expected_result ); TEST_ASSERT( mock_allocate_data.called == 1 ); TEST_ASSERT( mock_generate_data.called == ( mock_alloc_return_value == PSA_SUCCESS? 1 : 0 ) ); if( mock_alloc_return_value == PSA_SUCCESS ) { TEST_ASSERT( mbedtls_svc_key_id_equal( mock_generate_data.attributes.core.id, id ) ); } else { TEST_ASSERT( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( mock_generate_data.attributes.core.id ) == 0 ); TEST_ASSERT( MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( mock_generate_data.attributes.core.id ) == 0 ); } TEST_ASSERT( mock_generate_data.attributes.core.lifetime == ( mock_alloc_return_value == PSA_SUCCESS? lifetime : 0 ) ); TEST_ASSERT( mock_generate_data.attributes.core.policy.usage == ( mock_alloc_return_value == PSA_SUCCESS? PSA_KEY_USAGE_EXPORT : 0 ) ); TEST_ASSERT( mock_generate_data.attributes.core.type == ( mock_alloc_return_value == PSA_SUCCESS? PSA_KEY_TYPE_RAW_DATA : 0 ) ); if( expected_result == PSA_SUCCESS ) { PSA_ASSERT( psa_destroy_key( id ) ); TEST_ASSERT( mock_destroy_data.called == 1 ); } exit: PSA_DONE( ); mock_teardown( ); } /* END_CASE */ /* BEGIN_CASE */ void mock_export_public( int mock_export_public_return_value, int expected_result ) { psa_drv_se_t driver; psa_drv_se_key_management_t key_management; psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime ); mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 ); mbedtls_svc_key_id_t returned_id; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; const uint8_t key_material[3] = {0xfa, 0xca, 0xde}; uint8_t exported[sizeof( key_material )]; size_t exported_length; mock_export_public_data.return_value = mock_export_public_return_value; memset( &driver, 0, sizeof( driver ) ); memset( &key_management, 0, sizeof( key_management ) ); driver.hal_version = PSA_DRV_SE_HAL_VERSION; driver.key_management = &key_management; key_management.p_import = mock_import; key_management.p_export_public = mock_export_public; key_management.p_destroy = mock_destroy; key_management.p_allocate = mock_allocate; PSA_ASSERT( psa_register_se_driver( location, &driver ) ); PSA_ASSERT( psa_crypto_init( ) ); psa_set_key_id( &attributes, id ); psa_set_key_lifetime( &attributes, lifetime ); psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT ); psa_set_key_type( &attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY ); PSA_ASSERT( psa_import_key( &attributes, key_material, sizeof( key_material ), &returned_id ) ); TEST_ASSERT( psa_export_public_key( id, exported, sizeof(exported), &exported_length ) == expected_result ); TEST_ASSERT( mock_export_public_data.called == 1 ); PSA_ASSERT( psa_destroy_key( id ) ); TEST_ASSERT( mock_destroy_data.called == 1 ); exit: PSA_DONE( ); mock_teardown( ); } /* END_CASE */ /* BEGIN_CASE */ void mock_sign( int mock_sign_return_value, int expected_result ) { psa_drv_se_t driver; psa_drv_se_key_management_t key_management; psa_drv_se_asymmetric_t asymmetric; psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime ); mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 ); mbedtls_svc_key_id_t returned_id; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; const uint8_t key_material[3] = {0xfa, 0xca, 0xde}; psa_algorithm_t algorithm = PSA_ALG_ECDSA(PSA_ALG_SHA_256); const uint8_t hash[1] = {'H'}; uint8_t signature[1] = {'S'}; size_t signature_length; mock_sign_data.return_value = mock_sign_return_value; memset( &driver, 0, sizeof( driver ) ); memset( &key_management, 0, sizeof( key_management ) ); memset( &asymmetric, 0, sizeof( asymmetric ) ); driver.hal_version = PSA_DRV_SE_HAL_VERSION; driver.key_management = &key_management; key_management.p_import = mock_import; key_management.p_destroy = mock_destroy; key_management.p_allocate = mock_allocate; driver.asymmetric = &asymmetric; asymmetric.p_sign = mock_sign; PSA_ASSERT( psa_register_se_driver( location, &driver ) ); PSA_ASSERT( psa_crypto_init( ) ); psa_set_key_id( &attributes, id ); psa_set_key_lifetime( &attributes, lifetime ); psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH ); psa_set_key_algorithm( &attributes, algorithm ); psa_set_key_type( &attributes, PSA_KEY_TYPE_RSA_KEY_PAIR ); PSA_ASSERT( psa_import_key( &attributes, key_material, sizeof( key_material ), &returned_id ) ); TEST_ASSERT( psa_sign_hash( id, algorithm, hash, sizeof( hash ), signature, sizeof( signature ), &signature_length) == expected_result ); TEST_ASSERT( mock_sign_data.called == 1 ); PSA_ASSERT( psa_destroy_key( id ) ); TEST_ASSERT( mock_destroy_data.called == 1 ); exit: PSA_DONE( ); mock_teardown( ); } /* END_CASE */ /* BEGIN_CASE */ void mock_verify( int mock_verify_return_value, int expected_result ) { psa_drv_se_t driver; psa_drv_se_key_management_t key_management; psa_drv_se_asymmetric_t asymmetric; psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime ); mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 ); mbedtls_svc_key_id_t returned_id; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; const uint8_t key_material[3] = {0xfa, 0xca, 0xde}; psa_algorithm_t algorithm = PSA_ALG_ECDSA(PSA_ALG_SHA_256); const uint8_t hash[1] = {'H'}; const uint8_t signature[1] = {'S'}; mock_verify_data.return_value = mock_verify_return_value; memset( &driver, 0, sizeof( driver ) ); memset( &key_management, 0, sizeof( key_management ) ); memset( &asymmetric, 0, sizeof( asymmetric ) ); driver.hal_version = PSA_DRV_SE_HAL_VERSION; driver.key_management = &key_management; key_management.p_import = mock_import; key_management.p_destroy = mock_destroy; key_management.p_allocate = mock_allocate; driver.asymmetric = &asymmetric; asymmetric.p_verify = mock_verify; PSA_ASSERT( psa_register_se_driver( location, &driver ) ); PSA_ASSERT( psa_crypto_init( ) ); psa_set_key_id( &attributes, id ); psa_set_key_lifetime( &attributes, lifetime ); psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH ); psa_set_key_algorithm( &attributes, algorithm ); psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA ); PSA_ASSERT( psa_import_key( &attributes, key_material, sizeof( key_material ), &returned_id ) ); TEST_ASSERT( psa_verify_hash( id, algorithm, hash, sizeof( hash ), signature, sizeof( signature ) ) == expected_result ); TEST_ASSERT( mock_verify_data.called == 1 ); PSA_ASSERT( psa_destroy_key( id ) ); TEST_ASSERT( mock_destroy_data.called == 1 ); exit: PSA_DONE( ); mock_teardown( ); } /* END_CASE */