From dd413d3c928e8941ea4d74ff89fd4e1632f4ed23 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 28 May 2019 15:06:43 +0200 Subject: [PATCH] Test shutdown without closing handles Add some test cases that shut down and restart without explicitly closing handles, and check that the handles are properly invalidated. --- tests/psa_helpers.function | 24 ++++- ...test_suite_psa_crypto_slot_management.data | 24 ++++- ..._suite_psa_crypto_slot_management.function | 98 +++++++++++++------ 3 files changed, 111 insertions(+), 35 deletions(-) diff --git a/tests/psa_helpers.function b/tests/psa_helpers.function index 22055003b..edaea8024 100644 --- a/tests/psa_helpers.function +++ b/tests/psa_helpers.function @@ -32,7 +32,7 @@ */ #define PSA_ASSERT( expr ) TEST_EQUAL( ( expr ), PSA_SUCCESS ) -static void test_helper_psa_done( int line, const char *file ) +static int test_helper_is_psa_pristine( int line, const char *file ) { mbedtls_psa_stats_t stats; const char *msg = NULL; @@ -48,12 +48,28 @@ static void test_helper_psa_done( int line, const char *file ) else if( stats.half_filled_slots != 0 ) msg = "A half-filled slot has not been cleared properly."; - /* If the test failed, don't overwrite the failure information. - * Do keep the stats lookup above, because it can be convenient to - * break on it when debugging a failure. */ + /* If the test has already failed, don't overwrite the failure + * information. Do keep the stats lookup above, because it can be + * convenient to break on it when debugging a failure. */ if( msg != NULL && test_info.failed == 0 ) test_fail( msg, line, file ); + return( msg == NULL ); +} + +/** Check that no PSA slots are in use. + */ +#define ASSERT_PSA_PRISTINE( ) \ + do \ + { \ + if( ! test_helper_is_psa_pristine( __LINE__, __FILE__ ) ) \ + goto exit; \ + } \ + while( 0 ) + +static void test_helper_psa_done( int line, const char *file ) +{ + (void) test_helper_is_psa_pristine( line, file ); mbedtls_psa_crypto_free( ); } diff --git a/tests/suites/test_suite_psa_crypto_slot_management.data b/tests/suites/test_suite_psa_crypto_slot_management.data index e65befe38..233b16698 100644 --- a/tests/suites/test_suite_psa_crypto_slot_management.data +++ b/tests/suites/test_suite_psa_crypto_slot_management.data @@ -1,19 +1,31 @@ Transient slot, check after closing transient_slot_lifecycle:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_CLOSE +Transient slot, check after closing and restarting +transient_slot_lifecycle:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_CLOSE_WITH_SHUTDOWN + Transient slot, check after destroying transient_slot_lifecycle:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_DESTROY -Transient slot, check after restart +Transient slot, check after destroying and restarting +transient_slot_lifecycle:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_DESTROY_WITH_SHUTDOWN + +Transient slot, check after restart with live handles transient_slot_lifecycle:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_SHUTDOWN Persistent slot, check after closing, id=min persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_CLOSE +Persistent slot, check after closing and restarting, id=min +persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_CLOSE + Persistent slot, check after destroying, id=min persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_DESTROY -Persistent slot, check after restart, id=min +Persistent slot, check after destroying and restarting, id=min +persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_DESTROY + +Persistent slot, check after restart with live handle, id=min persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_SHUTDOWN Persistent slot, check after closing, id=max @@ -29,6 +41,10 @@ Persistent slot: ECP keypair (ECDSA, exportable); close depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_ECDSA_ANY:0:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_CLOSE +Persistent slot: ECP keypair (ECDSA, exportable); close+restart +depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_ECDSA_ANY:0:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_CLOSE_WITH_SHUTDOWN + Persistent slot: ECP keypair (ECDSA, exportable); restart depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_ECDSA_ANY:0:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_SHUTDOWN @@ -37,6 +53,10 @@ Persistent slot: ECP keypair (ECDH+ECDSA, exportable); close depends_on:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_ALG_ECDSA_ANY:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_CLOSE +Persistent slot: ECP keypair (ECDH+ECDSA, exportable); close+restart +depends_on:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_ALG_ECDSA_ANY:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_CLOSE_WITH_SHUTDOWN + Persistent slot: ECP keypair (ECDH+ECDSA, exportable); restart depends_on:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_ALG_ECDSA_ANY:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_SHUTDOWN diff --git a/tests/suites/test_suite_psa_crypto_slot_management.function b/tests/suites/test_suite_psa_crypto_slot_management.function index 589d1ecb1..da93bc829 100644 --- a/tests/suites/test_suite_psa_crypto_slot_management.function +++ b/tests/suites/test_suite_psa_crypto_slot_management.function @@ -6,9 +6,11 @@ typedef enum { - CLOSE_BY_CLOSE, - CLOSE_BY_DESTROY, - CLOSE_BY_SHUTDOWN, + CLOSE_BY_CLOSE, /**< Close the handle(s). */ + CLOSE_BY_DESTROY, /**< Destroy the handle(s). */ + CLOSE_BY_SHUTDOWN, /**< Deinit and reinit without closing handles. */ + CLOSE_BY_CLOSE_WITH_SHUTDOWN, /**< Close handle(s) then deinit/reinit. */ + CLOSE_BY_DESTROY_WITH_SHUTDOWN, /**< Destroy handle(s) then deinit/reinit. */ } close_method_t; typedef enum @@ -62,6 +64,58 @@ static void psa_purge_key_storage( void ) #define TEST_USES_KEY_ID( key_id ) ( (void) ( key_id ) ) #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ +/** Apply \p close_method to invalidate the specified handles: + * close it, destroy it, or do nothing; + */ +static int invalidate_handle( close_method_t close_method, + psa_key_handle_t handle ) +{ + switch( close_method ) + { + case CLOSE_BY_CLOSE: + case CLOSE_BY_CLOSE_WITH_SHUTDOWN: + PSA_ASSERT( psa_close_key( handle ) ); + break; + case CLOSE_BY_DESTROY: + case CLOSE_BY_DESTROY_WITH_SHUTDOWN: + PSA_ASSERT( psa_destroy_key( handle ) ); + break; + case CLOSE_BY_SHUTDOWN: + break; + } + return( 1 ); +exit: + return( 0 ); +} + +/** Restart the PSA subsystem if \p close_method says so. */ +static int invalidate_psa( close_method_t close_method ) +{ + switch( close_method ) + { + case CLOSE_BY_CLOSE: + case CLOSE_BY_DESTROY: + return( 1 ); + case CLOSE_BY_CLOSE_WITH_SHUTDOWN: + case CLOSE_BY_DESTROY_WITH_SHUTDOWN: + /* All keys must have been closed. */ + PSA_DONE( ); + break; + case CLOSE_BY_SHUTDOWN: + /* Some keys may remain behind, and we're testing that this + * properly closes them. */ + mbedtls_psa_crypto_free( ); + break; + } + + PSA_ASSERT( psa_crypto_init( ) ); + ASSERT_PSA_PRISTINE( ); + return( 1 ); + +exit: + return( 0 ); +} + /* END_HEADER */ /* BEGIN_DEPENDENCIES @@ -94,19 +148,10 @@ void transient_slot_lifecycle( int usage_arg, int alg_arg, TEST_EQUAL( psa_get_key_type( &attributes ), type ); /* Do something that invalidates the handle. */ - switch( close_method ) - { - case CLOSE_BY_CLOSE: - PSA_ASSERT( psa_close_key( handle ) ); - break; - case CLOSE_BY_DESTROY: - PSA_ASSERT( psa_destroy_key( handle ) ); - break; - case CLOSE_BY_SHUTDOWN: - PSA_DONE( ); - PSA_ASSERT( psa_crypto_init( ) ); - break; - } + if( ! invalidate_handle( close_method, handle ) ) + goto exit; + if( ! invalidate_psa( close_method ) ) + goto exit; /* Test that the handle is now invalid. */ TEST_EQUAL( psa_get_key_attributes( handle, &attributes ), @@ -171,19 +216,11 @@ void persistent_slot_lifecycle( int lifetime_arg, int id_arg, TEST_EQUAL( psa_get_key_type( &attributes ), type ); /* Do something that invalidates the handle. */ - switch( close_method ) - { - case CLOSE_BY_CLOSE: - PSA_ASSERT( psa_close_key( handle ) ); - break; - case CLOSE_BY_DESTROY: - PSA_ASSERT( psa_destroy_key( handle ) ); - break; - case CLOSE_BY_SHUTDOWN: - PSA_DONE( ); - PSA_ASSERT( psa_crypto_init( ) ); - break; - } + if( ! invalidate_handle( close_method, handle ) ) + goto exit; + if( ! invalidate_psa( close_method ) ) + goto exit; + /* Test that the handle is now invalid. */ TEST_EQUAL( psa_get_key_attributes( handle, &read_attributes ), PSA_ERROR_INVALID_HANDLE ); @@ -196,6 +233,7 @@ void persistent_slot_lifecycle( int lifetime_arg, int id_arg, switch( close_method ) { case CLOSE_BY_CLOSE: + case CLOSE_BY_CLOSE_WITH_SHUTDOWN: case CLOSE_BY_SHUTDOWN: PSA_ASSERT( psa_open_key( id, &handle ) ); PSA_ASSERT( psa_get_key_attributes( handle, &read_attributes ) ); @@ -230,7 +268,9 @@ void persistent_slot_lifecycle( int lifetime_arg, int id_arg, } PSA_ASSERT( psa_close_key( handle ) ); break; + case CLOSE_BY_DESTROY: + case CLOSE_BY_DESTROY_WITH_SHUTDOWN: TEST_EQUAL( psa_open_key( id, &handle ), PSA_ERROR_DOES_NOT_EXIST ); break;