0174be2c17
It's potentially useful in all PSA test suites, of which there are now several.
396 lines
13 KiB
Text
396 lines
13 KiB
Text
/* BEGIN_HEADER */
|
|
#include <stdint.h>
|
|
|
|
#if defined(MBEDTLS_PSA_CRYPTO_SPM)
|
|
#include "spm/psa_defs.h"
|
|
#endif
|
|
#include "psa/crypto.h"
|
|
|
|
#include "psa_crypto_storage.h"
|
|
|
|
typedef enum
|
|
{
|
|
CLOSE_BY_CLOSE,
|
|
CLOSE_BY_DESTROY,
|
|
CLOSE_BY_SHUTDOWN,
|
|
} close_method_t;
|
|
|
|
typedef enum
|
|
{
|
|
KEEP_OPEN,
|
|
CLOSE_BEFORE,
|
|
CLOSE_AFTER,
|
|
} reopen_policy_t;
|
|
|
|
/* All test functions that create persistent keys must call
|
|
* `TEST_MAX_KEY_ID( key_id )` before creating a persistent key with this
|
|
* identifier, and must call psa_purge_key_storage() in their cleanup
|
|
* code. */
|
|
|
|
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
|
|
/* There is no API to purge all keys. For this test suite, require that
|
|
* all key IDs be less than a certain maximum, or a well-known value
|
|
* which corresponds to a file that does not contain a key. */
|
|
#define MAX_KEY_ID_FOR_TEST 32
|
|
#define KEY_ID_IS_WELL_KNOWN( key_id ) \
|
|
( ( key_id ) == PSA_CRYPTO_ITS_RANDOM_SEED_UID )
|
|
#define TEST_MAX_KEY_ID( key_id ) \
|
|
TEST_ASSERT( ( key_id ) <= MAX_KEY_ID_FOR_TEST || \
|
|
KEY_ID_IS_WELL_KNOWN( key_id ) )
|
|
void psa_purge_key_storage( void )
|
|
{
|
|
psa_key_id_t i;
|
|
/* 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( i = 0; i <= MAX_KEY_ID_FOR_TEST; i++ )
|
|
psa_destroy_persistent_key( i );
|
|
}
|
|
#else
|
|
#define TEST_MAX_KEY_ID( key_id ) ( (void) ( key_id ) )
|
|
#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
|
|
|
|
static int psa_key_policy_equal( psa_key_policy_t *p1,
|
|
psa_key_policy_t *p2 )
|
|
{
|
|
return( psa_key_policy_get_usage( p1 ) == psa_key_policy_get_usage( p2 ) &&
|
|
psa_key_policy_get_algorithm( p1 ) == psa_key_policy_get_algorithm( p2 ) );
|
|
}
|
|
|
|
/* END_HEADER */
|
|
|
|
/* BEGIN_DEPENDENCIES
|
|
* depends_on:MBEDTLS_PSA_CRYPTO_C
|
|
* END_DEPENDENCIES
|
|
*/
|
|
|
|
/* BEGIN_CASE */
|
|
void transient_slot_lifecycle( int type_arg, int max_bits_arg,
|
|
int alg_arg, int usage_arg,
|
|
data_t *key_data,
|
|
int close_method_arg )
|
|
{
|
|
psa_key_type_t type = type_arg;
|
|
size_t max_bits = max_bits_arg;
|
|
psa_algorithm_t alg = alg_arg;
|
|
psa_key_usage_t usage_flags = usage_arg;
|
|
close_method_t close_method = close_method_arg;
|
|
psa_key_type_t read_type;
|
|
psa_key_handle_t handle = 0;
|
|
psa_key_policy_t policy;
|
|
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
/* Get a handle and import a key. */
|
|
PSA_ASSERT( psa_allocate_key( type, max_bits, &handle ) );
|
|
TEST_ASSERT( handle != 0 );
|
|
psa_key_policy_init( &policy );
|
|
psa_key_policy_set_usage( &policy, usage_flags, alg );
|
|
PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
|
|
PSA_ASSERT( psa_import_key( handle, type, key_data->x, key_data->len ) );
|
|
PSA_ASSERT( psa_get_key_information( handle, &read_type, NULL ) );
|
|
TEST_ASSERT( read_type == 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:
|
|
mbedtls_psa_crypto_free( );
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
break;
|
|
}
|
|
/* Test that the handle is now invalid. */
|
|
TEST_ASSERT( psa_get_key_information( handle, &read_type, NULL ) ==
|
|
PSA_ERROR_INVALID_HANDLE );
|
|
TEST_ASSERT( psa_close_key( handle ) == PSA_ERROR_INVALID_HANDLE );
|
|
|
|
exit:
|
|
mbedtls_psa_crypto_free( );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */
|
|
void persistent_slot_lifecycle( int lifetime_arg, int id_arg,
|
|
int type_arg, int max_bits_arg,
|
|
int alg_arg, int usage_arg,
|
|
data_t *key_data,
|
|
int close_method_arg )
|
|
{
|
|
psa_key_lifetime_t lifetime = lifetime_arg;
|
|
psa_key_id_t id = id_arg;
|
|
psa_key_type_t type = type_arg;
|
|
size_t max_bits = max_bits_arg;
|
|
psa_algorithm_t alg = alg_arg;
|
|
psa_key_usage_t usage_flags = usage_arg;
|
|
close_method_t close_method = close_method_arg;
|
|
psa_key_type_t read_type;
|
|
psa_key_handle_t handle = 0;
|
|
psa_key_policy_t policy;
|
|
|
|
TEST_MAX_KEY_ID( id );
|
|
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
/* Get a handle and import a key. */
|
|
PSA_ASSERT( psa_create_key( lifetime, id, type, max_bits, &handle ) );
|
|
TEST_ASSERT( handle != 0 );
|
|
psa_key_policy_init( &policy );
|
|
psa_key_policy_set_usage( &policy, usage_flags, alg );
|
|
PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
|
|
PSA_ASSERT( psa_import_key( handle, type, key_data->x, key_data->len ) );
|
|
PSA_ASSERT( psa_get_key_information( handle, &read_type, NULL ) );
|
|
TEST_ASSERT( read_type == type );
|
|
|
|
/* Close the key and reopen it. */
|
|
PSA_ASSERT( psa_close_key( handle ) );
|
|
PSA_ASSERT( psa_open_key( lifetime, id, &handle ) );
|
|
PSA_ASSERT( psa_get_key_information( handle, &read_type, NULL ) );
|
|
TEST_ASSERT( read_type == 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:
|
|
mbedtls_psa_crypto_free( );
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
break;
|
|
}
|
|
/* Test that the handle is now invalid. */
|
|
TEST_ASSERT( psa_get_key_information( handle, &read_type, NULL ) ==
|
|
PSA_ERROR_INVALID_HANDLE );
|
|
TEST_ASSERT( psa_close_key( handle ) == PSA_ERROR_INVALID_HANDLE );
|
|
|
|
/* Try to reopen the key. If we destroyed it, check that it doesn't
|
|
* exist, otherwise check that it still exists. */
|
|
switch( close_method )
|
|
{
|
|
case CLOSE_BY_CLOSE:
|
|
case CLOSE_BY_SHUTDOWN:
|
|
PSA_ASSERT( psa_open_key( lifetime, id, &handle ) );
|
|
PSA_ASSERT( psa_get_key_information( handle, &read_type, NULL ) );
|
|
TEST_ASSERT( read_type == type );
|
|
break;
|
|
case CLOSE_BY_DESTROY:
|
|
TEST_ASSERT( psa_open_key( lifetime, id, &handle ) ==
|
|
PSA_ERROR_EMPTY_SLOT );
|
|
break;
|
|
}
|
|
|
|
exit:
|
|
mbedtls_psa_crypto_free( );
|
|
psa_purge_key_storage( );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */
|
|
void create_existent( int lifetime_arg, int id_arg,
|
|
int new_type_arg,
|
|
int reopen_policy_arg )
|
|
{
|
|
psa_key_lifetime_t lifetime = lifetime_arg;
|
|
psa_key_id_t id = id_arg;
|
|
psa_key_handle_t handle1 = 0, handle2 = 0;
|
|
psa_key_policy_t policy1, read_policy;
|
|
psa_key_type_t type1 = PSA_KEY_TYPE_RAW_DATA;
|
|
psa_key_type_t type2 = new_type_arg;
|
|
psa_key_type_t read_type;
|
|
const uint8_t material1[16] = "test material #1";
|
|
size_t bits1 = PSA_BYTES_TO_BITS( sizeof( material1 ) );
|
|
size_t read_bits;
|
|
uint8_t reexported[sizeof( material1 )];
|
|
size_t reexported_length;
|
|
reopen_policy_t reopen_policy = reopen_policy_arg;
|
|
|
|
TEST_MAX_KEY_ID( id );
|
|
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
/* Create a key. */
|
|
PSA_ASSERT( psa_create_key( lifetime, id, type1, bits1, &handle1 ) );
|
|
TEST_ASSERT( handle1 != 0 );
|
|
psa_key_policy_init( &policy1 );
|
|
psa_key_policy_set_usage( &policy1, PSA_KEY_USAGE_EXPORT, 0 );
|
|
PSA_ASSERT( psa_set_key_policy( handle1, &policy1 ) );
|
|
PSA_ASSERT( psa_import_key( handle1, type1,
|
|
material1, sizeof( material1 ) ) );
|
|
|
|
if( reopen_policy == CLOSE_BEFORE )
|
|
PSA_ASSERT( psa_close_key( handle1 ) );
|
|
|
|
/* Attempt to create a new key in the same slot. */
|
|
TEST_ASSERT( psa_create_key( lifetime, id, type2, bits1, &handle2 ) ==
|
|
PSA_ERROR_OCCUPIED_SLOT );
|
|
TEST_ASSERT( handle2 == 0 );
|
|
|
|
if( reopen_policy == CLOSE_AFTER )
|
|
PSA_ASSERT( psa_close_key( handle1 ) );
|
|
if( reopen_policy == CLOSE_BEFORE || reopen_policy == CLOSE_AFTER )
|
|
PSA_ASSERT( psa_open_key( lifetime, id, &handle1 ) );
|
|
|
|
/* Check that the original key hasn't changed. */
|
|
PSA_ASSERT( psa_get_key_policy( handle1, &read_policy ) );
|
|
TEST_ASSERT( psa_key_policy_equal( &read_policy, &policy1 ) );
|
|
PSA_ASSERT( psa_get_key_information( handle1, &read_type, &read_bits ) );
|
|
TEST_ASSERT( read_type == type1 );
|
|
TEST_ASSERT( read_bits == bits1 );
|
|
PSA_ASSERT( psa_export_key( handle1,
|
|
reexported, sizeof( reexported ),
|
|
&reexported_length ) );
|
|
ASSERT_COMPARE( material1, sizeof( material1 ),
|
|
reexported, reexported_length );
|
|
|
|
exit:
|
|
mbedtls_psa_crypto_free( );
|
|
psa_purge_key_storage( );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void open_fail( int lifetime_arg, int id_arg,
|
|
int expected_status_arg )
|
|
{
|
|
psa_key_lifetime_t lifetime = lifetime_arg;
|
|
psa_key_id_t id = id_arg;
|
|
psa_status_t expected_status = expected_status_arg;
|
|
psa_key_handle_t handle = 0xdead;
|
|
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
TEST_ASSERT( psa_open_key( lifetime, id, &handle ) == expected_status );
|
|
TEST_ASSERT( handle == 0 );
|
|
|
|
exit:
|
|
mbedtls_psa_crypto_free( );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void create_fail( int lifetime_arg, int id_arg,
|
|
int type_arg, int max_bits_arg,
|
|
int expected_status_arg )
|
|
{
|
|
psa_key_lifetime_t lifetime = lifetime_arg;
|
|
psa_key_id_t id = id_arg;
|
|
psa_key_type_t type = type_arg;
|
|
size_t max_bits = max_bits_arg;
|
|
psa_status_t expected_status = expected_status_arg;
|
|
psa_key_handle_t handle = 0xdead;
|
|
|
|
TEST_MAX_KEY_ID( id );
|
|
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
TEST_ASSERT( psa_create_key( lifetime, id,
|
|
type, max_bits,
|
|
&handle ) == expected_status );
|
|
TEST_ASSERT( handle == 0 );
|
|
|
|
exit:
|
|
mbedtls_psa_crypto_free( );
|
|
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
|
|
psa_purge_key_storage( );
|
|
#endif
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void invalid_handle( )
|
|
{
|
|
psa_key_handle_t handle1 = 0;
|
|
psa_key_policy_t policy;
|
|
psa_key_type_t read_type;
|
|
size_t read_bits;
|
|
uint8_t material[1] = "a";
|
|
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
/* Allocate a handle and store a key in it. */
|
|
PSA_ASSERT( psa_allocate_key( PSA_KEY_TYPE_RAW_DATA, 1, &handle1 ) );
|
|
TEST_ASSERT( handle1 != 0 );
|
|
psa_key_policy_init( &policy );
|
|
psa_key_policy_set_usage( &policy, 0, 0 );
|
|
PSA_ASSERT( psa_set_key_policy( handle1, &policy ) );
|
|
PSA_ASSERT( psa_import_key( handle1, PSA_KEY_TYPE_RAW_DATA,
|
|
material, sizeof( material ) ) );
|
|
|
|
/* Attempt to close and destroy some invalid handles. */
|
|
TEST_ASSERT( psa_close_key( 0 ) == PSA_ERROR_INVALID_HANDLE );
|
|
TEST_ASSERT( psa_close_key( handle1 - 1 ) == PSA_ERROR_INVALID_HANDLE );
|
|
TEST_ASSERT( psa_close_key( handle1 + 1 ) == PSA_ERROR_INVALID_HANDLE );
|
|
TEST_ASSERT( psa_destroy_key( 0 ) == PSA_ERROR_INVALID_HANDLE );
|
|
TEST_ASSERT( psa_destroy_key( handle1 - 1 ) == PSA_ERROR_INVALID_HANDLE );
|
|
TEST_ASSERT( psa_destroy_key( handle1 + 1 ) == PSA_ERROR_INVALID_HANDLE );
|
|
|
|
/* After all this, check that the original handle is intact. */
|
|
PSA_ASSERT( psa_get_key_information( handle1, &read_type, &read_bits ) );
|
|
TEST_ASSERT( read_type == PSA_KEY_TYPE_RAW_DATA );
|
|
TEST_ASSERT( read_bits == PSA_BYTES_TO_BITS( sizeof( material ) ) );
|
|
PSA_ASSERT( psa_close_key( handle1 ) );
|
|
|
|
exit:
|
|
mbedtls_psa_crypto_free( );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void many_transient_handles( int max_handles_arg )
|
|
{
|
|
psa_key_handle_t *handles = NULL;
|
|
size_t max_handles = max_handles_arg;
|
|
size_t i, j;
|
|
psa_status_t status;
|
|
psa_key_policy_t policy;
|
|
uint8_t exported[sizeof( size_t )];
|
|
size_t exported_length;
|
|
size_t max_bits = PSA_BITS_TO_BYTES( sizeof( exported ) );
|
|
|
|
ASSERT_ALLOC( handles, max_handles );
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
psa_key_policy_init( &policy );
|
|
psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, 0 );
|
|
|
|
for( i = 0; i < max_handles; i++ )
|
|
{
|
|
status = psa_allocate_key( PSA_KEY_TYPE_RAW_DATA, max_bits,
|
|
&handles[i] );
|
|
if( status == PSA_ERROR_INSUFFICIENT_MEMORY )
|
|
break;
|
|
TEST_ASSERT( status == PSA_SUCCESS );
|
|
TEST_ASSERT( handles[i] != 0 );
|
|
for( j = 0; j < i; j++ )
|
|
TEST_ASSERT( handles[i] != handles[j] );
|
|
PSA_ASSERT( psa_set_key_policy( handles[i], &policy ) );
|
|
PSA_ASSERT( psa_import_key( handles[i], PSA_KEY_TYPE_RAW_DATA,
|
|
(uint8_t *) &i, sizeof( i ) ) );
|
|
}
|
|
max_handles = i;
|
|
|
|
for( i = 1; i < max_handles; i++ )
|
|
{
|
|
PSA_ASSERT( psa_close_key( handles[i - 1] ) );
|
|
PSA_ASSERT( psa_export_key( handles[i],
|
|
exported, sizeof( exported ),
|
|
&exported_length ) );
|
|
ASSERT_COMPARE( exported, exported_length,
|
|
(uint8_t *) &i, sizeof( i ) );
|
|
}
|
|
PSA_ASSERT( psa_close_key( handles[i - 1] ) );
|
|
|
|
exit:
|
|
mbedtls_psa_crypto_free( );
|
|
mbedtls_free( handles );
|
|
}
|
|
/* END_CASE */
|
|
|