Skip to content

Commit bbdf310

Browse files
Merge pull request #221 from gilles-peskine-arm/annotate_todo_comments-20190813
SE keys: fix psa_destroy_key; add Github issue numbers for missing code
2 parents 30e13eb + c9d7f94 commit bbdf310

File tree

3 files changed

+102
-34
lines changed

3 files changed

+102
-34
lines changed

include/psa/crypto_struct.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,26 @@
1212
* In implementations with isolation between the application and the
1313
* cryptography module, it is expected that the front-end and the back-end
1414
* would have different versions of this file.
15+
*
16+
* <h3>Design notes about multipart operation structures</h3>
17+
*
18+
* Each multipart operation structure contains a `psa_algorithm_t alg`
19+
* field which indicates which specific algorithm the structure is for.
20+
* When the structure is not in use, `alg` is 0. Most of the structure
21+
* consists of a union which is discriminated by `alg`.
22+
*
23+
* Note that when `alg` is 0, the content of other fields is undefined.
24+
* In particular, it is not guaranteed that a freshly-initialized structure
25+
* is all-zero: we initialize structures to something like `{0, 0}`, which
26+
* is only guaranteed to initializes the first member of the union;
27+
* GCC and Clang initialize the whole structure to 0 (at the time of writing),
28+
* but MSVC and CompCert don't.
29+
*
30+
* In Mbed Crypto, multipart operation structures live independently from
31+
* the key. This allows Mbed Crypto to free the key objects when destroying
32+
* a key slot. If a multipart operation needs to remember the key after
33+
* the setup function returns, the operation structure needs to contain a
34+
* copy of the key.
1535
*/
1636
/*
1737
* Copyright (C) 2018, ARM Limited, All Rights Reserved

library/psa_crypto.c

Lines changed: 51 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -994,18 +994,16 @@ static psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot )
994994
return( PSA_SUCCESS );
995995
}
996996

997-
static void psa_abort_operations_using_key( psa_key_slot_t *slot )
998-
{
999-
/*FIXME how to implement this?*/
1000-
(void) slot;
1001-
}
1002-
1003997
/** Completely wipe a slot in memory, including its policy.
1004998
* Persistent storage is not affected. */
1005999
psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot )
10061000
{
10071001
psa_status_t status = psa_remove_key_data_from_memory( slot );
1008-
psa_abort_operations_using_key( slot );
1002+
/* Multipart operations may still be using the key. This is safe
1003+
* because all multipart operation objects are independent from
1004+
* the key slot: if they need to access the key after the setup
1005+
* phase, they have a copy of the key. Note that this means that
1006+
* key material can linger until all operations are completed. */
10091007
/* At this point, key material and other type-specific content has
10101008
* been wiped. Clear remaining metadata. We can call memset and not
10111009
* zeroize because the metadata is not particularly sensitive. */
@@ -1016,8 +1014,8 @@ psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot )
10161014
psa_status_t psa_destroy_key( psa_key_handle_t handle )
10171015
{
10181016
psa_key_slot_t *slot;
1019-
psa_status_t status = PSA_SUCCESS;
1020-
psa_status_t storage_status = PSA_SUCCESS;
1017+
psa_status_t status; /* status of the last operation */
1018+
psa_status_t overall_status = PSA_SUCCESS;
10211019
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
10221020
psa_se_drv_table_entry_t *driver;
10231021
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
@@ -1043,42 +1041,57 @@ psa_status_t psa_destroy_key( psa_key_handle_t handle )
10431041
if( status != PSA_SUCCESS )
10441042
{
10451043
(void) psa_crypto_stop_transaction( );
1046-
/* TOnogrepDO: destroy what can be destroyed anyway */
1047-
return( status );
1044+
/* We should still try to destroy the key in the secure
1045+
* element and the key metadata in storage. This is especially
1046+
* important if the error is that the storage is full.
1047+
* But how to do it exactly without risking an inconsistent
1048+
* state after a reset?
1049+
* https://github.com/ARMmbed/mbed-crypto/issues/215
1050+
*/
1051+
overall_status = status;
1052+
goto exit;
10481053
}
10491054

10501055
status = psa_destroy_se_key( driver, slot->data.se.slot_number );
1056+
if( overall_status == PSA_SUCCESS )
1057+
overall_status = status;
10511058
}
10521059
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
10531060

10541061
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
1055-
if( slot->attr.lifetime == PSA_KEY_LIFETIME_PERSISTENT )
1062+
if( slot->attr.lifetime != PSA_KEY_LIFETIME_VOLATILE )
10561063
{
1057-
storage_status =
1058-
psa_destroy_persistent_key( slot->attr.id );
1064+
status = psa_destroy_persistent_key( slot->attr.id );
1065+
if( overall_status == PSA_SUCCESS )
1066+
overall_status = status;
1067+
1068+
/* TODO: other slots may have a copy of the same key. We should
1069+
* invalidate them.
1070+
* https://github.com/ARMmbed/mbed-crypto/issues/214
1071+
*/
10591072
}
10601073
#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
10611074

10621075
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
10631076
if( driver != NULL )
10641077
{
1065-
psa_status_t status2;
10661078
status = psa_save_se_persistent_data( driver );
1067-
status2 = psa_crypto_stop_transaction( );
1068-
if( status == PSA_SUCCESS )
1069-
status = status2;
1070-
if( status != PSA_SUCCESS )
1071-
{
1072-
/* TOnogrepDO: destroy what can be destroyed anyway */
1073-
return( status );
1074-
}
1079+
if( overall_status == PSA_SUCCESS )
1080+
overall_status = status;
1081+
status = psa_crypto_stop_transaction( );
1082+
if( overall_status == PSA_SUCCESS )
1083+
overall_status = status;
10751084
}
10761085
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
10771086

1087+
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
1088+
exit:
1089+
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
10781090
status = psa_wipe_key_slot( slot );
1079-
if( status != PSA_SUCCESS )
1080-
return( status );
1081-
return( storage_status );
1091+
/* Prioritize CORRUPTION_DETECTED from wiping over a storage error */
1092+
if( overall_status == PSA_SUCCESS )
1093+
overall_status = status;
1094+
return( overall_status );
10821095
}
10831096

10841097
void psa_reset_key_attributes( psa_key_attributes_t *attributes )
@@ -1201,8 +1214,10 @@ psa_status_t psa_get_key_attributes( psa_key_handle_t handle,
12011214
case PSA_KEY_TYPE_RSA_KEY_PAIR:
12021215
case PSA_KEY_TYPE_RSA_PUBLIC_KEY:
12031216
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
1204-
/* TOnogrepDO: reporting the public exponent for opaque keys
1205-
* is not yet implemented. */
1217+
/* TODO: reporting the public exponent for opaque keys
1218+
* is not yet implemented.
1219+
* https://github.com/ARMmbed/mbed-crypto/issues/216
1220+
*/
12061221
if( psa_key_slot_is_external( slot ) )
12071222
break;
12081223
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
@@ -1722,10 +1737,12 @@ static void psa_fail_key_creation( psa_key_slot_t *slot,
17221737
return;
17231738

17241739
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
1725-
/* TOnogrepDO: If the key has already been created in the secure
1740+
/* TODO: If the key has already been created in the secure
17261741
* element, and the failure happened later (when saving metadata
17271742
* to internal storage), we need to destroy the key in the secure
1728-
* element. */
1743+
* element.
1744+
* https://github.com/ARMmbed/mbed-crypto/issues/217
1745+
*/
17291746

17301747
/* Abort the ongoing transaction if any (there may not be one if
17311748
* the creation process failed before starting one, or if the
@@ -6075,8 +6092,10 @@ static psa_status_t psa_crypto_recover_transaction(
60756092
{
60766093
case PSA_CRYPTO_TRANSACTION_CREATE_KEY:
60776094
case PSA_CRYPTO_TRANSACTION_DESTROY_KEY:
6078-
/* TOnogrepDO - fall through to the failure case until this
6079-
* is implemented */
6095+
/* TODO - fall through to the failure case until this
6096+
* is implemented.
6097+
* https://github.com/ARMmbed/mbed-crypto/issues/218
6098+
*/
60806099
default:
60816100
/* We found an unsupported transaction in the storage.
60826101
* We don't know what state the storage is in. Give up. */

tests/suites/test_suite_psa_crypto_se_driver_hal.function

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,17 @@ static psa_status_t null_generate( psa_drv_se_context_t *context,
162162
return( PSA_SUCCESS );
163163
}
164164

165+
/* Null destroy: do nothing, but pretend it worked. */
166+
static psa_status_t null_destroy( psa_drv_se_context_t *context,
167+
void *persistent_data,
168+
psa_key_slot_number_t slot_number )
169+
{
170+
(void) context;
171+
(void) persistent_data;
172+
(void) slot_number;
173+
return( PSA_SUCCESS );
174+
}
175+
165176

166177

167178
/****************************************************************/
@@ -793,6 +804,9 @@ void key_creation_import_export( int min_slot, int restart )
793804
exported, exported_length );
794805

795806
PSA_ASSERT( psa_destroy_key( handle ) );
807+
handle = 0;
808+
TEST_EQUAL( psa_open_key( id, &handle ),
809+
PSA_ERROR_DOES_NOT_EXIST );
796810

797811
/* Test that the key has been erased from the designated slot. */
798812
TEST_ASSERT( ram_slots[min_slot].type == 0 );
@@ -864,6 +878,9 @@ void key_creation_in_chosen_slot( int slot_arg,
864878
PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
865879

866880
PSA_ASSERT( psa_destroy_key( handle ) );
881+
handle = 0;
882+
TEST_EQUAL( psa_open_key( id, &handle ),
883+
PSA_ERROR_DOES_NOT_EXIST );
867884

868885
exit:
869886
PSA_DONE( );
@@ -892,6 +909,7 @@ void import_key_smoke( int type_arg, int alg_arg,
892909
driver.persistent_data_size = sizeof( psa_key_slot_number_t );
893910
key_management.p_allocate = counter_allocate;
894911
key_management.p_import = null_import;
912+
key_management.p_destroy = null_destroy;
895913

896914
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
897915
PSA_ASSERT( psa_crypto_init( ) );
@@ -923,6 +941,9 @@ void import_key_smoke( int type_arg, int alg_arg,
923941

924942
/* We're done. */
925943
PSA_ASSERT( psa_destroy_key( handle ) );
944+
handle = 0;
945+
TEST_EQUAL( psa_open_key( id, &handle ),
946+
PSA_ERROR_DOES_NOT_EXIST );
926947

927948
exit:
928949
PSA_DONE( );
@@ -986,6 +1007,7 @@ void generate_key_smoke( int type_arg, int bits_arg, int alg_arg )
9861007
driver.persistent_data_size = sizeof( psa_key_slot_number_t );
9871008
key_management.p_allocate = counter_allocate;
9881009
key_management.p_generate = null_generate;
1010+
key_management.p_destroy = null_destroy;
9891011

9901012
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
9911013
PSA_ASSERT( psa_crypto_init( ) );
@@ -1016,6 +1038,9 @@ void generate_key_smoke( int type_arg, int bits_arg, int alg_arg )
10161038

10171039
/* We're done. */
10181040
PSA_ASSERT( psa_destroy_key( handle ) );
1041+
handle = 0;
1042+
TEST_EQUAL( psa_open_key( id, &handle ),
1043+
PSA_ERROR_DOES_NOT_EXIST );
10191044

10201045
exit:
10211046
PSA_DONE( );
@@ -1208,10 +1233,11 @@ void register_key_smoke_test( int lifetime_arg,
12081233

12091234
memset( &driver, 0, sizeof( driver ) );
12101235
driver.hal_version = PSA_DRV_SE_HAL_VERSION;
1236+
memset( &key_management, 0, sizeof( key_management ) );
1237+
driver.key_management = &key_management;
1238+
key_management.p_destroy = null_destroy;
12111239
if( validate >= 0 )
12121240
{
1213-
memset( &key_management, 0, sizeof( key_management ) );
1214-
driver.key_management = &key_management;
12151241
key_management.p_validate_slot_number = validate_slot_number_as_directed;
12161242
validate_slot_number_directions.slot_number = wanted_slot;
12171243
validate_slot_number_directions.method = PSA_KEY_CREATION_REGISTER;
@@ -1250,6 +1276,9 @@ void register_key_smoke_test( int lifetime_arg,
12501276
goto exit;
12511277
/* This time, destroy the key. */
12521278
PSA_ASSERT( psa_destroy_key( handle ) );
1279+
handle = 0;
1280+
TEST_EQUAL( psa_open_key( id, &handle ),
1281+
PSA_ERROR_DOES_NOT_EXIST );
12531282

12541283
exit:
12551284
psa_reset_key_attributes( &attributes );

0 commit comments

Comments
 (0)