1838e82190
This file isn't like the other .function files: it isn't concatenated by a separate preprocessing script, but included via C preprocessing. Rename this file to .h. This isn't a normal C header, because it defines auxiliary functions. But the functions aren't big and we only have one compilation unit per executable, so this is good enough for what we're doing.
713 lines
26 KiB
Text
713 lines
26 KiB
Text
/* BEGIN_HEADER */
|
|
#include <stdint.h>
|
|
|
|
#include "psa_crypto_helpers.h"
|
|
#include "psa_crypto_storage.h"
|
|
|
|
typedef enum
|
|
{
|
|
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
|
|
{
|
|
KEEP_OPEN,
|
|
CLOSE_BEFORE,
|
|
CLOSE_AFTER,
|
|
} reopen_policy_t;
|
|
|
|
/* All test functions that create persistent keys must call
|
|
* `TEST_USES_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)
|
|
static psa_key_id_t key_ids_used_in_test[9];
|
|
static size_t num_key_ids_used;
|
|
|
|
/* Record a key id as potentially used in a test case. */
|
|
static int test_uses_key_id( psa_key_id_t key_id )
|
|
{
|
|
size_t i;
|
|
if( key_id > PSA_MAX_PERSISTENT_KEY_IDENTIFIER )
|
|
{
|
|
/* Don't touch key id values that designate non-key files. */
|
|
return( 1 );
|
|
}
|
|
for( i = 0; i < num_key_ids_used ; i++ )
|
|
{
|
|
if( key_id == key_ids_used_in_test[i] )
|
|
return( 1 );
|
|
}
|
|
if( num_key_ids_used == ARRAY_LENGTH( key_ids_used_in_test ) )
|
|
return( 0 );
|
|
key_ids_used_in_test[num_key_ids_used] = key_id;
|
|
++num_key_ids_used;
|
|
return( 1 );
|
|
}
|
|
#define TEST_USES_KEY_ID( key_id ) \
|
|
TEST_ASSERT( test_uses_key_id( key_id ) )
|
|
|
|
/* Destroy all key ids that may have been created by the current test case. */
|
|
static void psa_purge_key_storage( void )
|
|
{
|
|
size_t i;
|
|
for( i = 0; i < num_key_ids_used; i++ )
|
|
psa_destroy_persistent_key( key_ids_used_in_test[i] );
|
|
num_key_ids_used = 0;
|
|
}
|
|
#else
|
|
#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
|
|
* depends_on:MBEDTLS_PSA_CRYPTO_C
|
|
* END_DEPENDENCIES
|
|
*/
|
|
|
|
/* BEGIN_CASE */
|
|
void transient_slot_lifecycle( int usage_arg, int alg_arg,
|
|
int type_arg, data_t *key_data,
|
|
int close_method_arg )
|
|
{
|
|
psa_algorithm_t alg = alg_arg;
|
|
psa_key_usage_t usage_flags = usage_arg;
|
|
psa_key_type_t type = type_arg;
|
|
close_method_t close_method = close_method_arg;
|
|
psa_key_handle_t handle = 0;
|
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
/* Import a key. */
|
|
psa_set_key_usage_flags( &attributes, usage_flags );
|
|
psa_set_key_algorithm( &attributes, alg );
|
|
psa_set_key_type( &attributes, type );
|
|
PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
|
|
&handle ) );
|
|
TEST_ASSERT( handle != 0 );
|
|
PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
|
|
TEST_EQUAL( psa_get_key_type( &attributes ), type );
|
|
|
|
/* Do something that invalidates the handle. */
|
|
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 ),
|
|
PSA_ERROR_INVALID_HANDLE );
|
|
TEST_EQUAL( psa_close_key( handle ), PSA_ERROR_INVALID_HANDLE );
|
|
|
|
exit:
|
|
PSA_DONE( );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */
|
|
void persistent_slot_lifecycle( int lifetime_arg, int id_arg,
|
|
int usage_arg, int alg_arg, int alg2_arg,
|
|
int type_arg, data_t *key_data,
|
|
int close_method_arg )
|
|
{
|
|
psa_key_lifetime_t lifetime = lifetime_arg;
|
|
psa_key_id_t id = id_arg;
|
|
psa_algorithm_t alg = alg_arg;
|
|
psa_algorithm_t alg2 = alg2_arg;
|
|
psa_key_usage_t usage_flags = usage_arg;
|
|
psa_key_type_t type = type_arg;
|
|
close_method_t close_method = close_method_arg;
|
|
psa_key_handle_t handle = 0;
|
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
psa_key_attributes_t read_attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
uint8_t *reexported = NULL;
|
|
size_t reexported_length = -1;
|
|
|
|
TEST_USES_KEY_ID( id );
|
|
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
/* Get a handle and import a key. */
|
|
psa_set_key_id( &attributes, id );
|
|
psa_set_key_lifetime( &attributes, lifetime );
|
|
psa_set_key_type( &attributes, type );
|
|
psa_set_key_usage_flags( &attributes, usage_flags );
|
|
psa_set_key_algorithm( &attributes, alg );
|
|
psa_set_key_enrollment_algorithm( &attributes, alg2 );
|
|
PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
|
|
&handle ) );
|
|
TEST_ASSERT( handle != 0 );
|
|
PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
|
|
TEST_EQUAL( psa_get_key_lifetime( &attributes ), lifetime );
|
|
TEST_EQUAL( psa_get_key_id( &attributes ), id );
|
|
TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage_flags );
|
|
TEST_EQUAL( psa_get_key_algorithm( &attributes ), alg );
|
|
TEST_EQUAL( psa_get_key_enrollment_algorithm( &attributes ), alg2 );
|
|
TEST_EQUAL( psa_get_key_type( &attributes ), type );
|
|
|
|
/* Close the key and reopen it. */
|
|
PSA_ASSERT( psa_close_key( handle ) );
|
|
PSA_ASSERT( psa_open_key( id, &handle ) );
|
|
PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
|
|
TEST_EQUAL( psa_get_key_lifetime( &attributes ), lifetime );
|
|
TEST_EQUAL( psa_get_key_id( &attributes ), id );
|
|
TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage_flags );
|
|
TEST_EQUAL( psa_get_key_algorithm( &attributes ), alg );
|
|
TEST_EQUAL( psa_get_key_enrollment_algorithm( &attributes ), alg2 );
|
|
TEST_EQUAL( psa_get_key_type( &attributes ), type );
|
|
|
|
/* Do something that invalidates the handle. */
|
|
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 );
|
|
psa_reset_key_attributes( &read_attributes );
|
|
TEST_EQUAL( 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 and has the expected
|
|
* content. */
|
|
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 ) );
|
|
TEST_EQUAL( psa_get_key_lifetime( &attributes ),
|
|
psa_get_key_lifetime( &read_attributes ) );
|
|
TEST_EQUAL( psa_get_key_id( &attributes ),
|
|
psa_get_key_id( &read_attributes ) );
|
|
TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage_flags );
|
|
TEST_EQUAL( psa_get_key_algorithm( &attributes ),
|
|
psa_get_key_algorithm( &read_attributes ) );
|
|
TEST_EQUAL( psa_get_key_enrollment_algorithm( &attributes ),
|
|
psa_get_key_enrollment_algorithm( &read_attributes ) );
|
|
TEST_EQUAL( psa_get_key_type( &attributes ),
|
|
psa_get_key_type( &read_attributes ) );
|
|
TEST_EQUAL( psa_get_key_bits( &attributes ),
|
|
psa_get_key_bits( &read_attributes ) );
|
|
if( usage_flags & PSA_KEY_USAGE_EXPORT )
|
|
{
|
|
ASSERT_ALLOC( reexported, key_data->len );
|
|
PSA_ASSERT( psa_export_key( handle,
|
|
reexported, key_data->len,
|
|
&reexported_length ) );
|
|
ASSERT_COMPARE( key_data->x, key_data->len,
|
|
reexported, reexported_length );
|
|
}
|
|
else
|
|
{
|
|
TEST_EQUAL( psa_export_key( handle,
|
|
reexported, sizeof( reexported ),
|
|
&reexported_length ),
|
|
PSA_ERROR_NOT_PERMITTED );
|
|
}
|
|
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;
|
|
}
|
|
|
|
exit:
|
|
PSA_DONE( );
|
|
psa_purge_key_storage( );
|
|
mbedtls_free( reexported );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */
|
|
void create_existent( int lifetime_arg, int id_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_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
psa_key_type_t type1 = PSA_KEY_TYPE_RAW_DATA;
|
|
const uint8_t material1[5] = "a key";
|
|
const uint8_t material2[5] = "b key";
|
|
size_t bits1 = PSA_BYTES_TO_BITS( sizeof( material1 ) );
|
|
uint8_t reexported[sizeof( material1 )];
|
|
size_t reexported_length;
|
|
reopen_policy_t reopen_policy = reopen_policy_arg;
|
|
|
|
TEST_USES_KEY_ID( id );
|
|
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
/* Create a key. */
|
|
psa_set_key_id( &attributes, id );
|
|
psa_set_key_lifetime( &attributes, lifetime );
|
|
psa_set_key_type( &attributes, type1 );
|
|
psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT );
|
|
psa_set_key_algorithm( &attributes, 0 );
|
|
PSA_ASSERT( psa_import_key( &attributes, material1, sizeof( material1 ),
|
|
&handle1 ) );
|
|
TEST_ASSERT( handle1 != 0 );
|
|
|
|
if( reopen_policy == CLOSE_BEFORE )
|
|
PSA_ASSERT( psa_close_key( handle1 ) );
|
|
|
|
/* Attempt to create a new key in the same slot. */
|
|
TEST_EQUAL( psa_import_key( &attributes, material2, sizeof( material2 ),
|
|
&handle2 ),
|
|
PSA_ERROR_ALREADY_EXISTS );
|
|
TEST_EQUAL( 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( id, &handle1 ) );
|
|
|
|
/* Check that the original key hasn't changed. */
|
|
psa_reset_key_attributes( &attributes );
|
|
PSA_ASSERT( psa_get_key_attributes( handle1, &attributes ) );
|
|
TEST_EQUAL( psa_get_key_id( &attributes ), id );
|
|
TEST_EQUAL( psa_get_key_lifetime( &attributes ), lifetime );
|
|
TEST_EQUAL( psa_get_key_type( &attributes ), type1 );
|
|
TEST_EQUAL( psa_get_key_bits( &attributes ), bits1 );
|
|
TEST_EQUAL( psa_get_key_usage_flags( &attributes ), PSA_KEY_USAGE_EXPORT );
|
|
TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
|
|
|
|
PSA_ASSERT( psa_export_key( handle1,
|
|
reexported, sizeof( reexported ),
|
|
&reexported_length ) );
|
|
ASSERT_COMPARE( material1, sizeof( material1 ),
|
|
reexported, reexported_length );
|
|
|
|
PSA_ASSERT( psa_close_key( handle1 ) );
|
|
|
|
exit:
|
|
PSA_DONE( );
|
|
psa_purge_key_storage( );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void open_fail( int id_arg,
|
|
int expected_status_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_EQUAL( psa_open_key( id, &handle ), expected_status );
|
|
TEST_EQUAL( handle, 0 );
|
|
|
|
exit:
|
|
PSA_DONE( );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void create_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_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
psa_status_t expected_status = expected_status_arg;
|
|
psa_key_handle_t handle = 0xdead;
|
|
uint8_t material[1] = {'k'};
|
|
|
|
TEST_USES_KEY_ID( id );
|
|
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
psa_set_key_id( &attributes, id );
|
|
psa_set_key_lifetime( &attributes, lifetime );
|
|
psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA );
|
|
TEST_EQUAL( psa_import_key( &attributes, material, sizeof( material ),
|
|
&handle ),
|
|
expected_status );
|
|
TEST_EQUAL( handle, 0 );
|
|
|
|
exit:
|
|
PSA_DONE( );
|
|
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
|
|
psa_purge_key_storage( );
|
|
#endif
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void copy_across_lifetimes( int source_lifetime_arg, int source_id_arg,
|
|
int source_usage_arg,
|
|
int source_alg_arg, int source_alg2_arg,
|
|
int type_arg, data_t *material,
|
|
int target_lifetime_arg, int target_id_arg,
|
|
int target_usage_arg,
|
|
int target_alg_arg, int target_alg2_arg,
|
|
int expected_usage_arg,
|
|
int expected_alg_arg, int expected_alg2_arg )
|
|
{
|
|
psa_key_lifetime_t source_lifetime = source_lifetime_arg;
|
|
psa_key_id_t source_id = source_id_arg;
|
|
psa_key_usage_t source_usage = source_usage_arg;
|
|
psa_algorithm_t source_alg = source_alg_arg;
|
|
psa_key_handle_t source_handle = 0;
|
|
psa_key_attributes_t source_attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
psa_key_type_t source_type = type_arg;
|
|
psa_key_lifetime_t target_lifetime = target_lifetime_arg;
|
|
psa_key_id_t target_id = target_id_arg;
|
|
psa_key_usage_t target_usage = target_usage_arg;
|
|
psa_algorithm_t target_alg = target_alg_arg;
|
|
psa_key_handle_t target_handle = 0;
|
|
psa_key_attributes_t target_attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
psa_key_usage_t expected_usage = expected_usage_arg;
|
|
psa_algorithm_t expected_alg = expected_alg_arg;
|
|
psa_algorithm_t expected_alg2 = expected_alg2_arg;
|
|
uint8_t *export_buffer = NULL;
|
|
|
|
TEST_USES_KEY_ID( source_id );
|
|
TEST_USES_KEY_ID( target_id );
|
|
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
/* Populate the source slot. */
|
|
if( source_lifetime != PSA_KEY_LIFETIME_VOLATILE )
|
|
{
|
|
psa_set_key_id( &source_attributes, source_id );
|
|
psa_set_key_lifetime( &source_attributes, source_lifetime );
|
|
}
|
|
psa_set_key_type( &source_attributes, source_type );
|
|
psa_set_key_usage_flags( &source_attributes, source_usage );
|
|
psa_set_key_algorithm( &source_attributes, source_alg );
|
|
psa_set_key_enrollment_algorithm( &source_attributes, source_alg2_arg );
|
|
PSA_ASSERT( psa_import_key( &source_attributes,
|
|
material->x, material->len,
|
|
&source_handle ) );
|
|
/* Update the attributes with the bit size. */
|
|
PSA_ASSERT( psa_get_key_attributes( source_handle, &source_attributes ) );
|
|
|
|
/* Prepare the target slot. */
|
|
if( target_lifetime != PSA_KEY_LIFETIME_VOLATILE )
|
|
{
|
|
psa_set_key_id( &target_attributes, target_id );
|
|
psa_set_key_lifetime( &target_attributes, target_lifetime );
|
|
}
|
|
psa_set_key_usage_flags( &target_attributes, target_usage );
|
|
psa_set_key_algorithm( &target_attributes, target_alg );
|
|
psa_set_key_enrollment_algorithm( &target_attributes, target_alg2_arg );
|
|
|
|
/* Copy the key. */
|
|
PSA_ASSERT( psa_copy_key( source_handle,
|
|
&target_attributes, &target_handle ) );
|
|
|
|
/* Destroy the source to ensure that this doesn't affect the target. */
|
|
PSA_ASSERT( psa_destroy_key( source_handle ) );
|
|
|
|
/* If the target key is persistent, restart the system to make
|
|
* sure that the material is still alive. */
|
|
if( target_lifetime != PSA_KEY_LIFETIME_VOLATILE )
|
|
{
|
|
mbedtls_psa_crypto_free( );
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
PSA_ASSERT( psa_open_key( target_id, &target_handle ) );
|
|
}
|
|
|
|
/* Test that the target slot has the expected content. */
|
|
psa_reset_key_attributes( &target_attributes );
|
|
PSA_ASSERT( psa_get_key_attributes( target_handle, &target_attributes ) );
|
|
TEST_EQUAL( target_id, psa_get_key_id( &target_attributes ) );
|
|
TEST_EQUAL( target_lifetime, psa_get_key_lifetime( &target_attributes ) );
|
|
TEST_EQUAL( source_type, psa_get_key_type( &target_attributes ) );
|
|
TEST_EQUAL( psa_get_key_bits( &source_attributes ),
|
|
psa_get_key_bits( &target_attributes ) );
|
|
TEST_EQUAL( expected_usage, psa_get_key_usage_flags( &target_attributes ) );
|
|
TEST_EQUAL( expected_alg, psa_get_key_algorithm( &target_attributes ) );
|
|
TEST_EQUAL( expected_alg2,
|
|
psa_get_key_enrollment_algorithm( &target_attributes ) );
|
|
if( expected_usage & PSA_KEY_USAGE_EXPORT )
|
|
{
|
|
size_t length;
|
|
ASSERT_ALLOC( export_buffer, material->len );
|
|
PSA_ASSERT( psa_export_key( target_handle, export_buffer,
|
|
material->len, &length ) );
|
|
ASSERT_COMPARE( material->x, material->len,
|
|
export_buffer, length );
|
|
}
|
|
else
|
|
{
|
|
size_t length;
|
|
/* Check that the key is actually non-exportable. */
|
|
TEST_EQUAL( psa_export_key( target_handle, export_buffer,
|
|
material->len, &length ),
|
|
PSA_ERROR_NOT_PERMITTED );
|
|
}
|
|
|
|
PSA_ASSERT( psa_destroy_key( target_handle ) );
|
|
|
|
exit:
|
|
PSA_DONE( );
|
|
mbedtls_free( export_buffer );
|
|
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
|
|
psa_purge_key_storage( );
|
|
#endif
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void copy_to_occupied( int source_lifetime_arg, int source_id_arg,
|
|
int source_usage_arg, int source_alg_arg,
|
|
int source_type_arg, data_t *source_material,
|
|
int target_lifetime_arg, int target_id_arg,
|
|
int target_usage_arg, int target_alg_arg,
|
|
int target_type_arg, data_t *target_material )
|
|
{
|
|
psa_key_lifetime_t source_lifetime = source_lifetime_arg;
|
|
psa_key_id_t source_id = source_id_arg;
|
|
psa_key_usage_t source_usage = source_usage_arg;
|
|
psa_algorithm_t source_alg = source_alg_arg;
|
|
psa_key_handle_t source_handle = 0;
|
|
psa_key_type_t source_type = source_type_arg;
|
|
psa_key_lifetime_t target_lifetime = target_lifetime_arg;
|
|
psa_key_id_t target_id = target_id_arg;
|
|
psa_key_usage_t target_usage = target_usage_arg;
|
|
psa_algorithm_t target_alg = target_alg_arg;
|
|
psa_key_handle_t target_handle = 0;
|
|
psa_key_type_t target_type = target_type_arg;
|
|
psa_key_handle_t new_handle = 0xdead;
|
|
uint8_t *export_buffer = NULL;
|
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
psa_key_attributes_t attributes1 = PSA_KEY_ATTRIBUTES_INIT;
|
|
psa_key_attributes_t attributes2 = PSA_KEY_ATTRIBUTES_INIT;
|
|
|
|
TEST_USES_KEY_ID( source_id );
|
|
TEST_USES_KEY_ID( target_id );
|
|
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
/* Populate the source slot. */
|
|
if( source_lifetime != PSA_KEY_LIFETIME_VOLATILE )
|
|
{
|
|
psa_set_key_id( &attributes, source_id );
|
|
psa_set_key_lifetime( &attributes, source_lifetime );
|
|
}
|
|
psa_set_key_type( &attributes, source_type );
|
|
psa_set_key_usage_flags( &attributes, source_usage );
|
|
psa_set_key_algorithm( &attributes, source_alg );
|
|
PSA_ASSERT( psa_import_key( &attributes,
|
|
source_material->x, source_material->len,
|
|
&source_handle ) );
|
|
|
|
/* Populate the target slot. */
|
|
if( target_id == source_id )
|
|
{
|
|
target_handle = source_handle;
|
|
}
|
|
else
|
|
{
|
|
psa_set_key_id( &attributes1, target_id );
|
|
psa_set_key_lifetime( &attributes1, target_lifetime );
|
|
psa_set_key_type( &attributes1, target_type );
|
|
psa_set_key_usage_flags( &attributes1, target_usage );
|
|
psa_set_key_algorithm( &attributes1, target_alg );
|
|
PSA_ASSERT( psa_import_key( &attributes1,
|
|
target_material->x, target_material->len,
|
|
&target_handle ) );
|
|
}
|
|
PSA_ASSERT( psa_get_key_attributes( target_handle, &attributes1 ) );
|
|
|
|
/* Make a copy attempt. */
|
|
psa_set_key_id( &attributes, target_id );
|
|
psa_set_key_lifetime( &attributes, target_lifetime );
|
|
TEST_EQUAL( psa_copy_key( source_handle,
|
|
&attributes, &new_handle ),
|
|
PSA_ERROR_ALREADY_EXISTS );
|
|
TEST_EQUAL( new_handle , 0 );
|
|
|
|
/* Test that the target slot is unaffected. */
|
|
PSA_ASSERT( psa_get_key_attributes( target_handle, &attributes2 ) );
|
|
TEST_EQUAL( psa_get_key_id( &attributes1 ),
|
|
psa_get_key_id( &attributes2 ) );
|
|
TEST_EQUAL( psa_get_key_lifetime( &attributes1 ),
|
|
psa_get_key_lifetime( &attributes2 ) );
|
|
TEST_EQUAL( psa_get_key_type( &attributes1 ),
|
|
psa_get_key_type( &attributes2 ) );
|
|
TEST_EQUAL( psa_get_key_bits( &attributes1 ),
|
|
psa_get_key_bits( &attributes2 ) );
|
|
TEST_EQUAL( psa_get_key_usage_flags( &attributes1 ),
|
|
psa_get_key_usage_flags( &attributes2 ) );
|
|
TEST_EQUAL( psa_get_key_algorithm( &attributes1 ),
|
|
psa_get_key_algorithm( &attributes2 ) );
|
|
if( target_usage & PSA_KEY_USAGE_EXPORT )
|
|
{
|
|
size_t length;
|
|
ASSERT_ALLOC( export_buffer, target_material->len );
|
|
PSA_ASSERT( psa_export_key( target_handle, export_buffer,
|
|
target_material->len, &length ) );
|
|
ASSERT_COMPARE( target_material->x, target_material->len,
|
|
export_buffer, length );
|
|
}
|
|
|
|
PSA_ASSERT( psa_destroy_key( source_handle ) );
|
|
if( target_handle != source_handle )
|
|
PSA_ASSERT( psa_destroy_key( target_handle ) );
|
|
|
|
exit:
|
|
PSA_DONE( );
|
|
mbedtls_free( export_buffer );
|
|
#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_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
uint8_t material[1] = "a";
|
|
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
/* Allocate a handle and store a key in it. */
|
|
psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA );
|
|
psa_set_key_usage_flags( &attributes, 0 );
|
|
psa_set_key_algorithm( &attributes, 0 );
|
|
PSA_ASSERT( psa_import_key( &attributes,
|
|
material, sizeof( material ),
|
|
&handle1 ) );
|
|
TEST_ASSERT( handle1 != 0 );
|
|
|
|
/* Attempt to close and destroy some invalid handles. */
|
|
TEST_EQUAL( psa_close_key( 0 ), PSA_ERROR_INVALID_HANDLE );
|
|
TEST_EQUAL( psa_close_key( handle1 - 1 ), PSA_ERROR_INVALID_HANDLE );
|
|
TEST_EQUAL( psa_close_key( handle1 + 1 ), PSA_ERROR_INVALID_HANDLE );
|
|
TEST_EQUAL( psa_destroy_key( 0 ), PSA_ERROR_INVALID_HANDLE );
|
|
TEST_EQUAL( psa_destroy_key( handle1 - 1 ), PSA_ERROR_INVALID_HANDLE );
|
|
TEST_EQUAL( psa_destroy_key( handle1 + 1 ), PSA_ERROR_INVALID_HANDLE );
|
|
|
|
/* After all this, check that the original handle is intact. */
|
|
PSA_ASSERT( psa_get_key_attributes( handle1, &attributes ) );
|
|
TEST_EQUAL( psa_get_key_type( &attributes ), PSA_KEY_TYPE_RAW_DATA );
|
|
TEST_EQUAL( psa_get_key_bits( &attributes ),
|
|
PSA_BYTES_TO_BITS( sizeof( material ) ) );
|
|
PSA_ASSERT( psa_close_key( handle1 ) );
|
|
|
|
exit:
|
|
PSA_DONE( );
|
|
}
|
|
/* 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_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
uint8_t exported[sizeof( size_t )];
|
|
size_t exported_length;
|
|
|
|
ASSERT_ALLOC( handles, max_handles );
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT );
|
|
psa_set_key_algorithm( &attributes, 0 );
|
|
psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA );
|
|
|
|
for( i = 0; i < max_handles; i++ )
|
|
{
|
|
status = psa_import_key( &attributes,
|
|
(uint8_t *) &i, sizeof( i ),
|
|
&handles[i] );
|
|
if( status == PSA_ERROR_INSUFFICIENT_MEMORY )
|
|
break;
|
|
PSA_ASSERT( status );
|
|
TEST_ASSERT( handles[i] != 0 );
|
|
for( j = 0; j < i; j++ )
|
|
TEST_ASSERT( handles[i] != handles[j] );
|
|
}
|
|
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:
|
|
PSA_DONE( );
|
|
mbedtls_free( handles );
|
|
}
|
|
/* END_CASE */
|
|
|