mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-11-23 16:55:47 +01:00
f3801fff77
The methods to import and generate a key in a secure element drivers were written for an earlier version of the application-side interface. Now that there is a psa_key_attributes_t structure that combines all key metadata including its lifetime (location), type, size, policy and extra type-specific data (domain parameters), pass that to drivers instead of separate arguments for each piece of metadata. This makes the interface less cluttered. Update parameter names and descriptions to follow general conventions. Document the public-key output on key generation more precisely. Explain that it is optional in a driver, and when a driver would implement it. Declare that it is optional in the core, too (which means that a crypto core might not support drivers for secure elements that do need this feature). Update the implementation and the tests accordingly.
801 lines
29 KiB
Plaintext
801 lines
29 KiB
Plaintext
/* BEGIN_HEADER */
|
|
#include "psa_crypto_helpers.h"
|
|
#include "psa/crypto_se_driver.h"
|
|
|
|
#include "psa_crypto_se.h"
|
|
#include "psa_crypto_storage.h"
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* Test driver helpers */
|
|
/****************************************************************/
|
|
|
|
/** The minimum valid lifetime value for a secure element driver. */
|
|
#define MIN_DRIVER_LIFETIME 2
|
|
|
|
/** The driver detected a condition that shouldn't happen.
|
|
* This is probably a bug in the library. */
|
|
#define PSA_ERROR_DETECTED_BY_DRIVER ((psa_status_t)( -500 ))
|
|
|
|
/** Like #TEST_ASSERT for use in a driver method.
|
|
*
|
|
* Use this macro to assert on guarantees provided by the core.
|
|
*/
|
|
#define DRIVER_ASSERT( TEST ) \
|
|
do { \
|
|
if( ! (TEST) ) \
|
|
{ \
|
|
test_fail( #TEST, __LINE__, __FILE__ ); \
|
|
return( PSA_ERROR_DETECTED_BY_DRIVER ); \
|
|
} \
|
|
} while( 0 )
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* Miscellaneous driver methods */
|
|
/****************************************************************/
|
|
|
|
typedef struct
|
|
{
|
|
psa_key_slot_number_t slot_number;
|
|
psa_key_creation_method_t method;
|
|
psa_status_t status;
|
|
} validate_slot_number_directions_t;
|
|
static validate_slot_number_directions_t validate_slot_number_directions;
|
|
|
|
/* Validate a choice of slot number as directed. */
|
|
static psa_status_t validate_slot_number_as_directed(
|
|
psa_drv_se_context_t *context,
|
|
const psa_key_attributes_t *attributes,
|
|
psa_key_creation_method_t method,
|
|
psa_key_slot_number_t slot_number )
|
|
{
|
|
(void) context;
|
|
(void) attributes;
|
|
DRIVER_ASSERT( slot_number == validate_slot_number_directions.slot_number );
|
|
DRIVER_ASSERT( method == validate_slot_number_directions.method );
|
|
return( validate_slot_number_directions.status );
|
|
}
|
|
|
|
/* Allocate slot numbers with a monotonic counter. */
|
|
static psa_status_t counter_allocate( psa_drv_se_context_t *context,
|
|
void *persistent_data,
|
|
const psa_key_attributes_t *attributes,
|
|
psa_key_creation_method_t method,
|
|
psa_key_slot_number_t *slot_number )
|
|
{
|
|
psa_key_slot_number_t *p_counter = persistent_data;
|
|
(void) attributes;
|
|
(void) method;
|
|
if( context->persistent_data_size != sizeof( psa_key_slot_number_t ) )
|
|
return( PSA_ERROR_DETECTED_BY_DRIVER );
|
|
++*p_counter;
|
|
if( *p_counter == 0 )
|
|
return( PSA_ERROR_INSUFFICIENT_STORAGE );
|
|
*slot_number = *p_counter;
|
|
return( PSA_SUCCESS );
|
|
}
|
|
|
|
/* Null import: do nothing, but pretend it worked. */
|
|
static psa_status_t null_import( psa_drv_se_context_t *context,
|
|
psa_key_slot_number_t slot_number,
|
|
const psa_key_attributes_t *attributes,
|
|
const uint8_t *data,
|
|
size_t data_length,
|
|
size_t *bits )
|
|
{
|
|
(void) context;
|
|
(void) slot_number;
|
|
(void) attributes;
|
|
(void) data;
|
|
/* We're supposed to return a key size. Return one that's correct for
|
|
* plain data keys. */
|
|
*bits = PSA_BYTES_TO_BITS( data_length );
|
|
return( PSA_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* RAM-based test driver */
|
|
/****************************************************************/
|
|
|
|
#define RAM_MAX_KEY_SIZE 64
|
|
typedef struct
|
|
{
|
|
psa_key_lifetime_t lifetime;
|
|
psa_key_type_t type;
|
|
size_t bits;
|
|
uint8_t content[RAM_MAX_KEY_SIZE];
|
|
} ram_slot_t;
|
|
static ram_slot_t ram_slots[16];
|
|
|
|
/* A type with at least ARRAY_LENGTH(ram_slots) bits, containing a
|
|
* bit vector indicating which slots are in use. */
|
|
typedef uint16_t ram_slot_usage_t;
|
|
|
|
static uint8_t ram_min_slot = 0;
|
|
|
|
static void ram_slots_reset( void )
|
|
{
|
|
memset( ram_slots, 0, sizeof( ram_slots ) );
|
|
ram_min_slot = 0;
|
|
}
|
|
|
|
static psa_status_t ram_import( psa_drv_se_context_t *context,
|
|
psa_key_slot_number_t slot_number,
|
|
const psa_key_attributes_t *attributes,
|
|
const uint8_t *data,
|
|
size_t data_length,
|
|
size_t *bits )
|
|
{
|
|
(void) context;
|
|
DRIVER_ASSERT( slot_number < ARRAY_LENGTH( ram_slots ) );
|
|
if( data_length > sizeof( ram_slots[slot_number].content ) )
|
|
return( PSA_ERROR_INSUFFICIENT_STORAGE );
|
|
ram_slots[slot_number].lifetime = psa_get_key_lifetime( attributes );
|
|
ram_slots[slot_number].type = psa_get_key_type( attributes );
|
|
ram_slots[slot_number].bits = PSA_BYTES_TO_BITS( data_length );
|
|
*bits = PSA_BYTES_TO_BITS( data_length );
|
|
memcpy( ram_slots[slot_number].content, data, data_length );
|
|
return( PSA_SUCCESS );
|
|
}
|
|
|
|
static psa_status_t ram_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 )
|
|
{
|
|
size_t actual_size;
|
|
(void) context;
|
|
DRIVER_ASSERT( slot_number < ARRAY_LENGTH( ram_slots ) );
|
|
actual_size = PSA_BITS_TO_BYTES( ram_slots[slot_number].bits );
|
|
if( actual_size > data_size )
|
|
return( PSA_ERROR_BUFFER_TOO_SMALL );
|
|
*p_data_length = actual_size;
|
|
memcpy( p_data, ram_slots[slot_number].content, actual_size );
|
|
return( PSA_SUCCESS );
|
|
}
|
|
|
|
static psa_status_t ram_destroy( psa_drv_se_context_t *context,
|
|
void *persistent_data,
|
|
psa_key_slot_number_t slot_number )
|
|
{
|
|
ram_slot_usage_t *slot_usage = persistent_data;
|
|
DRIVER_ASSERT( context->persistent_data_size == sizeof( ram_slot_usage_t ) );
|
|
DRIVER_ASSERT( slot_number < ARRAY_LENGTH( ram_slots ) );
|
|
memset( &ram_slots[slot_number], 0, sizeof( ram_slots[slot_number] ) );
|
|
*slot_usage &= ~(ram_slot_usage_t)( 1 << slot_number );
|
|
return( PSA_SUCCESS );
|
|
}
|
|
|
|
static psa_status_t ram_allocate( psa_drv_se_context_t *context,
|
|
void *persistent_data,
|
|
const psa_key_attributes_t *attributes,
|
|
psa_key_creation_method_t method,
|
|
psa_key_slot_number_t *slot_number )
|
|
{
|
|
ram_slot_usage_t *slot_usage = persistent_data;
|
|
(void) attributes;
|
|
(void) method;
|
|
DRIVER_ASSERT( context->persistent_data_size == sizeof( ram_slot_usage_t ) );
|
|
for( *slot_number = ram_min_slot;
|
|
*slot_number < ARRAY_LENGTH( ram_slots );
|
|
++( *slot_number ) )
|
|
{
|
|
if( ! ( *slot_usage & 1 << *slot_number ) )
|
|
return( PSA_SUCCESS );
|
|
}
|
|
return( PSA_ERROR_INSUFFICIENT_STORAGE );
|
|
}
|
|
|
|
static psa_status_t ram_validate_slot_number(
|
|
psa_drv_se_context_t *context,
|
|
const psa_key_attributes_t *attributes,
|
|
psa_key_creation_method_t method,
|
|
psa_key_slot_number_t slot_number )
|
|
{
|
|
(void) context;
|
|
(void) attributes;
|
|
(void) method;
|
|
if( slot_number >= ARRAY_LENGTH( ram_slots ) )
|
|
return( PSA_ERROR_INVALID_ARGUMENT );
|
|
return( PSA_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* Other test helper functions */
|
|
/****************************************************************/
|
|
|
|
/* Check that the attributes of a key reported by psa_get_key_attributes()
|
|
* are consistent with the attributes used when creating the key. */
|
|
static int check_key_attributes(
|
|
psa_key_handle_t handle,
|
|
const psa_key_attributes_t *reference_attributes )
|
|
{
|
|
int ok = 0;
|
|
psa_key_attributes_t actual_attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
|
|
PSA_ASSERT( psa_get_key_attributes( handle, &actual_attributes ) );
|
|
|
|
TEST_EQUAL( psa_get_key_id( &actual_attributes ),
|
|
psa_get_key_id( reference_attributes ) );
|
|
TEST_EQUAL( psa_get_key_lifetime( &actual_attributes ),
|
|
psa_get_key_lifetime( reference_attributes ) );
|
|
TEST_EQUAL( psa_get_key_type( &actual_attributes ),
|
|
psa_get_key_type( reference_attributes ) );
|
|
TEST_EQUAL( psa_get_key_usage_flags( &actual_attributes ),
|
|
psa_get_key_usage_flags( reference_attributes ) );
|
|
TEST_EQUAL( psa_get_key_algorithm( &actual_attributes ),
|
|
psa_get_key_algorithm( reference_attributes ) );
|
|
TEST_EQUAL( psa_get_key_enrollment_algorithm( &actual_attributes ),
|
|
psa_get_key_enrollment_algorithm( reference_attributes ) );
|
|
if( psa_get_key_bits( reference_attributes ) != 0 )
|
|
{
|
|
TEST_EQUAL( psa_get_key_bits( &actual_attributes ),
|
|
psa_get_key_bits( reference_attributes ) );
|
|
}
|
|
|
|
{
|
|
psa_key_slot_number_t actual_slot_number = 0xdeadbeef;
|
|
psa_key_slot_number_t desired_slot_number = 0xb90cc011;
|
|
psa_key_lifetime_t lifetime =
|
|
psa_get_key_lifetime( &actual_attributes );
|
|
psa_status_t status = psa_get_key_slot_number( &actual_attributes,
|
|
&actual_slot_number );
|
|
if( lifetime < MIN_DRIVER_LIFETIME )
|
|
{
|
|
/* The key is not in a secure element. */
|
|
TEST_EQUAL( status, PSA_ERROR_INVALID_ARGUMENT );
|
|
}
|
|
else
|
|
{
|
|
/* The key is in a secure element. If it had been created
|
|
* in a specific slot, check that it is reported there. */
|
|
PSA_ASSERT( status );
|
|
status = psa_get_key_slot_number( reference_attributes,
|
|
&desired_slot_number );
|
|
if( status == PSA_SUCCESS )
|
|
{
|
|
TEST_EQUAL( desired_slot_number, actual_slot_number );
|
|
}
|
|
}
|
|
}
|
|
ok = 1;
|
|
|
|
exit:
|
|
return( ok );
|
|
}
|
|
|
|
/* Check that a function's return status is "smoke-free", i.e. that
|
|
* it's an acceptable error code when calling an API function that operates
|
|
* on a key with potentially bogus parameters. */
|
|
static int is_status_smoke_free( psa_status_t status )
|
|
{
|
|
switch( status )
|
|
{
|
|
case PSA_SUCCESS:
|
|
case PSA_ERROR_NOT_SUPPORTED:
|
|
case PSA_ERROR_NOT_PERMITTED:
|
|
case PSA_ERROR_BUFFER_TOO_SMALL:
|
|
case PSA_ERROR_INVALID_ARGUMENT:
|
|
case PSA_ERROR_INVALID_SIGNATURE:
|
|
case PSA_ERROR_INVALID_PADDING:
|
|
return( 1 );
|
|
default:
|
|
return( 0 );
|
|
}
|
|
}
|
|
#define SMOKE_ASSERT( expr ) \
|
|
TEST_ASSERT( is_status_smoke_free( expr ) )
|
|
|
|
/* Smoke test a key. There are mostly no wrong answers here since we pass
|
|
* mostly bogus parameters: the goal is to ensure that there is no memory
|
|
* corruption or crash. This test function is most useful when run under
|
|
* an environment with sanity checks such as ASan or MSan. */
|
|
static int smoke_test_key( psa_key_handle_t handle )
|
|
{
|
|
int ok = 0;
|
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
psa_mac_operation_t mac_operation = PSA_MAC_OPERATION_INIT;
|
|
psa_cipher_operation_t cipher_operation = PSA_CIPHER_OPERATION_INIT;
|
|
psa_key_derivation_operation_t derivation_operation =
|
|
PSA_KEY_DERIVATION_OPERATION_INIT;
|
|
uint8_t buffer[80]; /* large enough for a public key for ECDH */
|
|
size_t length;
|
|
psa_key_handle_t handle2 = 0;
|
|
|
|
SMOKE_ASSERT( psa_get_key_attributes( handle, &attributes ) );
|
|
|
|
SMOKE_ASSERT( psa_export_key( handle,
|
|
buffer, sizeof( buffer ), &length ) );
|
|
SMOKE_ASSERT( psa_export_public_key( handle,
|
|
buffer, sizeof( buffer ), &length ) );
|
|
|
|
SMOKE_ASSERT( psa_copy_key( handle, &attributes, &handle2 ) );
|
|
if( handle2 != 0 )
|
|
PSA_ASSERT( psa_close_key( handle2 ) );
|
|
|
|
SMOKE_ASSERT( psa_mac_sign_setup( &mac_operation, handle, PSA_ALG_CMAC ) );
|
|
PSA_ASSERT( psa_mac_abort( &mac_operation ) );
|
|
SMOKE_ASSERT( psa_mac_verify_setup( &mac_operation, handle,
|
|
PSA_ALG_HMAC( PSA_ALG_SHA_256 ) ) );
|
|
PSA_ASSERT( psa_mac_abort( &mac_operation ) );
|
|
|
|
SMOKE_ASSERT( psa_cipher_encrypt_setup( &cipher_operation, handle,
|
|
PSA_ALG_CTR ) );
|
|
PSA_ASSERT( psa_cipher_abort( &cipher_operation ) );
|
|
SMOKE_ASSERT( psa_cipher_decrypt_setup( &cipher_operation, handle,
|
|
PSA_ALG_CTR ) );
|
|
PSA_ASSERT( psa_cipher_abort( &cipher_operation ) );
|
|
|
|
SMOKE_ASSERT( psa_aead_encrypt( handle, PSA_ALG_CCM,
|
|
buffer, sizeof( buffer ),
|
|
NULL, 0,
|
|
buffer, sizeof( buffer),
|
|
buffer, sizeof( buffer), &length ) );
|
|
SMOKE_ASSERT( psa_aead_decrypt( handle, PSA_ALG_CCM,
|
|
buffer, sizeof( buffer ),
|
|
NULL, 0,
|
|
buffer, sizeof( buffer),
|
|
buffer, sizeof( buffer), &length ) );
|
|
|
|
SMOKE_ASSERT( psa_asymmetric_sign( handle, PSA_ALG_ECDSA_ANY,
|
|
buffer, 32,
|
|
buffer, sizeof( buffer ), &length ) );
|
|
SMOKE_ASSERT( psa_asymmetric_verify( handle, PSA_ALG_ECDSA_ANY,
|
|
buffer, 32,
|
|
buffer, sizeof( buffer ) ) );
|
|
|
|
SMOKE_ASSERT( psa_asymmetric_encrypt( handle, PSA_ALG_RSA_PKCS1V15_CRYPT,
|
|
buffer, 10, NULL, 0,
|
|
buffer, sizeof( buffer ), &length ) );
|
|
SMOKE_ASSERT( psa_asymmetric_decrypt( handle, PSA_ALG_RSA_PKCS1V15_CRYPT,
|
|
buffer, sizeof( buffer ), NULL, 0,
|
|
buffer, sizeof( buffer ), &length ) );
|
|
|
|
#if defined(MBEDTLS_SHA256_C)
|
|
/* Try the key in a plain key derivation. */
|
|
PSA_ASSERT( psa_key_derivation_setup( &derivation_operation,
|
|
PSA_ALG_HKDF( PSA_ALG_SHA_256 ) ) );
|
|
PSA_ASSERT( psa_key_derivation_input_bytes( &derivation_operation,
|
|
PSA_KEY_DERIVATION_INPUT_SALT,
|
|
NULL, 0 ) );
|
|
SMOKE_ASSERT( psa_key_derivation_input_key( &derivation_operation,
|
|
PSA_KEY_DERIVATION_INPUT_SECRET,
|
|
handle ) );
|
|
PSA_ASSERT( psa_key_derivation_abort( &derivation_operation ) );
|
|
|
|
/* If the key is asymmetric, try it in a key agreement, both as
|
|
* part of a derivation operation and standalone. */
|
|
if( psa_export_public_key( handle, buffer, sizeof( buffer ), &length ) ==
|
|
PSA_SUCCESS )
|
|
{
|
|
psa_algorithm_t alg =
|
|
PSA_ALG_KEY_AGREEMENT( PSA_ALG_ECDH,
|
|
PSA_ALG_HKDF( PSA_ALG_SHA_256 ) );
|
|
PSA_ASSERT( psa_key_derivation_setup( &derivation_operation, alg ) );
|
|
PSA_ASSERT( psa_key_derivation_input_bytes(
|
|
&derivation_operation, PSA_KEY_DERIVATION_INPUT_SALT,
|
|
NULL, 0 ) );
|
|
SMOKE_ASSERT( psa_key_derivation_key_agreement(
|
|
&derivation_operation,
|
|
PSA_KEY_DERIVATION_INPUT_SECRET,
|
|
handle, buffer, length ) );
|
|
PSA_ASSERT( psa_key_derivation_abort( &derivation_operation ) );
|
|
|
|
SMOKE_ASSERT( psa_raw_key_agreement(
|
|
alg, handle, buffer, length,
|
|
buffer, sizeof( buffer ), &length ) );
|
|
}
|
|
#endif /* MBEDTLS_SHA256_C */
|
|
|
|
ok = 1;
|
|
|
|
exit:
|
|
psa_reset_key_attributes( &attributes );
|
|
return( ok );
|
|
}
|
|
|
|
#define MAX_KEY_ID_FOR_TEST 10
|
|
static void psa_purge_storage( void )
|
|
{
|
|
psa_key_id_t id;
|
|
psa_key_lifetime_t lifetime;
|
|
/* 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( id );
|
|
/* Purge the transaction file. */
|
|
psa_crypto_stop_transaction( );
|
|
/* Purge driver persistent data. */
|
|
for( lifetime = 0; lifetime < PSA_MAX_SE_LIFETIME; lifetime++ )
|
|
psa_destroy_se_persistent_data( lifetime );
|
|
}
|
|
|
|
/* END_HEADER */
|
|
|
|
/* BEGIN_DEPENDENCIES
|
|
* depends_on:MBEDTLS_PSA_CRYPTO_SE_C
|
|
* END_DEPENDENCIES
|
|
*/
|
|
|
|
/* BEGIN_CASE */
|
|
void register_one( int lifetime, int version, int expected_status_arg )
|
|
{
|
|
psa_status_t expected_status = expected_status_arg;
|
|
psa_drv_se_t driver;
|
|
|
|
memset( &driver, 0, sizeof( driver ) );
|
|
driver.hal_version = version;
|
|
|
|
TEST_EQUAL( psa_register_se_driver( lifetime, &driver ),
|
|
expected_status );
|
|
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
exit:
|
|
PSA_DONE( );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void register_twice( int count )
|
|
{
|
|
psa_drv_se_t driver;
|
|
psa_key_lifetime_t lifetime;
|
|
psa_key_lifetime_t max = MIN_DRIVER_LIFETIME + count;
|
|
|
|
memset( &driver, 0, sizeof( driver ) );
|
|
driver.hal_version = PSA_DRV_SE_HAL_VERSION;
|
|
|
|
for( lifetime = MIN_DRIVER_LIFETIME; lifetime < max; lifetime++ )
|
|
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
|
|
for( lifetime = MIN_DRIVER_LIFETIME; lifetime < max; lifetime++ )
|
|
TEST_EQUAL( psa_register_se_driver( lifetime, &driver ),
|
|
PSA_ERROR_ALREADY_EXISTS );
|
|
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
exit:
|
|
PSA_DONE( );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void register_max( )
|
|
{
|
|
psa_drv_se_t driver;
|
|
psa_key_lifetime_t lifetime;
|
|
psa_key_lifetime_t max = MIN_DRIVER_LIFETIME + PSA_MAX_SE_DRIVERS;
|
|
|
|
memset( &driver, 0, sizeof( driver ) );
|
|
driver.hal_version = PSA_DRV_SE_HAL_VERSION;
|
|
|
|
for( lifetime = MIN_DRIVER_LIFETIME; lifetime < max; lifetime++ )
|
|
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
|
|
|
|
TEST_EQUAL( psa_register_se_driver( lifetime, &driver ),
|
|
PSA_ERROR_INSUFFICIENT_MEMORY );
|
|
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
exit:
|
|
PSA_DONE( );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void key_creation_import_export( int min_slot, int restart )
|
|
{
|
|
psa_drv_se_t driver;
|
|
psa_drv_se_key_management_t key_management;
|
|
psa_key_lifetime_t lifetime = 2;
|
|
psa_key_id_t id = 1;
|
|
psa_key_handle_t handle = 0;
|
|
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;
|
|
|
|
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.persistent_data_size = sizeof( ram_slot_usage_t );
|
|
key_management.p_allocate = ram_allocate;
|
|
key_management.p_import = ram_import;
|
|
key_management.p_destroy = ram_destroy;
|
|
key_management.p_export = ram_export;
|
|
ram_min_slot = min_slot;
|
|
|
|
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
/* Create a key. */
|
|
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 ),
|
|
&handle ) );
|
|
|
|
/* Maybe restart, to check that the information is saved correctly. */
|
|
if( restart )
|
|
{
|
|
mbedtls_psa_crypto_free( );
|
|
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
PSA_ASSERT( psa_open_key( id, &handle ) );
|
|
}
|
|
|
|
/* Test that the key was created in the expected slot. */
|
|
TEST_ASSERT( ram_slots[min_slot].type == PSA_KEY_TYPE_RAW_DATA );
|
|
|
|
/* Test the key attributes, including the reported slot number. */
|
|
psa_set_key_bits( &attributes,
|
|
PSA_BYTES_TO_BITS( sizeof( key_material ) ) );
|
|
psa_set_key_slot_number( &attributes, min_slot );
|
|
if( ! check_key_attributes( handle, &attributes ) )
|
|
goto exit;
|
|
|
|
/* Test the key data. */
|
|
PSA_ASSERT( psa_export_key( handle,
|
|
exported, sizeof( exported ),
|
|
&exported_length ) );
|
|
ASSERT_COMPARE( key_material, sizeof( key_material ),
|
|
exported, exported_length );
|
|
|
|
PSA_ASSERT( psa_destroy_key( handle ) );
|
|
|
|
/* Test that the key has been erased from the designated slot. */
|
|
TEST_ASSERT( ram_slots[min_slot].type == 0 );
|
|
|
|
exit:
|
|
PSA_DONE( );
|
|
ram_slots_reset( );
|
|
psa_purge_storage( );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void key_creation_in_chosen_slot( int slot_arg,
|
|
int restart,
|
|
int expected_status_arg )
|
|
{
|
|
psa_key_slot_number_t wanted_slot = slot_arg;
|
|
psa_status_t expected_status = expected_status_arg;
|
|
psa_status_t status;
|
|
psa_drv_se_t driver;
|
|
psa_drv_se_key_management_t key_management;
|
|
psa_key_lifetime_t lifetime = 2;
|
|
psa_key_id_t id = 1;
|
|
psa_key_handle_t handle = 0;
|
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
const uint8_t key_material[3] = {0xfa, 0xca, 0xde};
|
|
|
|
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.persistent_data_size = sizeof( ram_slot_usage_t );
|
|
key_management.p_validate_slot_number = ram_validate_slot_number;
|
|
key_management.p_import = ram_import;
|
|
key_management.p_destroy = ram_destroy;
|
|
key_management.p_export = ram_export;
|
|
|
|
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
/* Create a key. */
|
|
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_slot_number( &attributes, wanted_slot );
|
|
status = psa_import_key( &attributes,
|
|
key_material, sizeof( key_material ),
|
|
&handle );
|
|
TEST_EQUAL( status, expected_status );
|
|
|
|
if( status != PSA_SUCCESS )
|
|
goto exit;
|
|
|
|
/* Maybe restart, to check that the information is saved correctly. */
|
|
if( restart )
|
|
{
|
|
mbedtls_psa_crypto_free( );
|
|
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
PSA_ASSERT( psa_open_key( id, &handle ) );
|
|
}
|
|
|
|
/* Test that the key was created in the expected slot. */
|
|
TEST_EQUAL( ram_slots[wanted_slot].type, PSA_KEY_TYPE_RAW_DATA );
|
|
|
|
/* Test that the key is reported with the correct attributes,
|
|
* including the expected slot. */
|
|
PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
|
|
|
|
PSA_ASSERT( psa_destroy_key( handle ) );
|
|
|
|
exit:
|
|
PSA_DONE( );
|
|
ram_slots_reset( );
|
|
psa_purge_storage( );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void key_creation_smoke( int type_arg, int alg_arg,
|
|
data_t *key_material )
|
|
{
|
|
psa_key_type_t type = type_arg;
|
|
psa_algorithm_t alg = alg_arg;
|
|
psa_drv_se_t driver;
|
|
psa_drv_se_key_management_t key_management;
|
|
psa_key_lifetime_t lifetime = 2;
|
|
psa_key_id_t id = 1;
|
|
psa_key_handle_t handle = 0;
|
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
|
|
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.persistent_data_size = sizeof( psa_key_slot_number_t );
|
|
key_management.p_allocate = counter_allocate;
|
|
key_management.p_import = null_import;
|
|
|
|
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
/* Create a key. */
|
|
psa_set_key_id( &attributes, id );
|
|
psa_set_key_lifetime( &attributes, lifetime );
|
|
psa_set_key_usage_flags( &attributes,
|
|
PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY |
|
|
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT |
|
|
PSA_KEY_USAGE_EXPORT );
|
|
psa_set_key_algorithm( &attributes, alg );
|
|
psa_set_key_type( &attributes, type );
|
|
PSA_ASSERT( psa_import_key( &attributes,
|
|
key_material->x, key_material->len,
|
|
&handle ) );
|
|
|
|
/* Do stuff with the key. */
|
|
if( ! smoke_test_key( handle ) )
|
|
goto exit;
|
|
|
|
/* Restart and try again. */
|
|
mbedtls_psa_crypto_free( );
|
|
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
PSA_ASSERT( psa_open_key( id, &handle ) );
|
|
if( ! smoke_test_key( handle ) )
|
|
goto exit;
|
|
|
|
/* We're done. */
|
|
PSA_ASSERT( psa_destroy_key( handle ) );
|
|
|
|
exit:
|
|
PSA_DONE( );
|
|
ram_slots_reset( );
|
|
psa_purge_storage( );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void generate_key_not_supported( int type_arg, int bits_arg )
|
|
{
|
|
psa_key_type_t type = type_arg;
|
|
size_t bits = bits_arg;
|
|
psa_drv_se_t driver;
|
|
psa_drv_se_key_management_t key_management;
|
|
psa_key_lifetime_t lifetime = 2;
|
|
psa_key_id_t id = 1;
|
|
psa_key_handle_t handle = 0;
|
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
|
|
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.persistent_data_size = sizeof( psa_key_slot_number_t );
|
|
key_management.p_allocate = counter_allocate;
|
|
|
|
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
|
|
psa_set_key_id( &attributes, id );
|
|
psa_set_key_lifetime( &attributes, lifetime );
|
|
psa_set_key_type( &attributes, type );
|
|
psa_set_key_bits( &attributes, bits );
|
|
TEST_EQUAL( psa_generate_key( &attributes, &handle ),
|
|
PSA_ERROR_NOT_SUPPORTED );
|
|
|
|
exit:
|
|
PSA_DONE( );
|
|
ram_slots_reset( );
|
|
psa_purge_storage( );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void register_key_smoke_test( int lifetime_arg,
|
|
int validate,
|
|
int expected_status_arg )
|
|
{
|
|
psa_key_lifetime_t lifetime = lifetime_arg;
|
|
psa_status_t expected_status = expected_status_arg;
|
|
psa_drv_se_t driver;
|
|
psa_drv_se_key_management_t key_management;
|
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
psa_key_id_t id = 1;
|
|
size_t bit_size = 48;
|
|
psa_key_slot_number_t wanted_slot = 0x123456789;
|
|
psa_key_handle_t handle = 0;
|
|
psa_status_t status;
|
|
|
|
memset( &driver, 0, sizeof( driver ) );
|
|
driver.hal_version = PSA_DRV_SE_HAL_VERSION;
|
|
if( validate >= 0 )
|
|
{
|
|
memset( &key_management, 0, sizeof( key_management ) );
|
|
driver.key_management = &key_management;
|
|
key_management.p_validate_slot_number = validate_slot_number_as_directed;
|
|
validate_slot_number_directions.slot_number = wanted_slot;
|
|
validate_slot_number_directions.method = PSA_KEY_CREATION_REGISTER;
|
|
validate_slot_number_directions.status =
|
|
( validate > 0 ? PSA_SUCCESS : PSA_ERROR_NOT_PERMITTED );
|
|
}
|
|
|
|
PSA_ASSERT( psa_register_se_driver( MIN_DRIVER_LIFETIME, &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, bit_size );
|
|
psa_set_key_slot_number( &attributes, wanted_slot );
|
|
|
|
status = mbedtls_psa_register_se_key( &attributes );
|
|
TEST_EQUAL( status, expected_status );
|
|
|
|
if( status != PSA_SUCCESS )
|
|
goto exit;
|
|
|
|
/* Test that the key exists and has the expected attributes. */
|
|
PSA_ASSERT( psa_open_key( id, &handle ) );
|
|
if( ! check_key_attributes( handle, &attributes ) )
|
|
goto exit;
|
|
PSA_ASSERT( psa_close_key( handle ) );
|
|
|
|
/* Restart and try again. */
|
|
PSA_DONE( );
|
|
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
|
|
PSA_ASSERT( psa_crypto_init( ) );
|
|
PSA_ASSERT( psa_open_key( id, &handle ) );
|
|
if( ! check_key_attributes( handle, &attributes ) )
|
|
goto exit;
|
|
/* This time, destroy the key. */
|
|
PSA_ASSERT( psa_destroy_key( handle ) );
|
|
|
|
exit:
|
|
psa_reset_key_attributes( &attributes );
|
|
psa_destroy_key( handle );
|
|
PSA_DONE( );
|
|
psa_purge_storage( );
|
|
memset( &validate_slot_number_directions, 0,
|
|
sizeof( validate_slot_number_directions ) );
|
|
}
|
|
/* END_CASE */
|