From 80b39ae753e3126da94298d1d27c182d0c766195 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 15 May 2019 16:09:46 +0200 Subject: [PATCH 1/6] Remove obsolete use of key policy structure in API text --- include/psa/crypto_values.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index eddf63262a..c0d35f4001 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -663,10 +663,8 @@ * Then you may create and use a key as follows: * - Set the key usage field using #PSA_ALG_ANY_HASH, for example: * ``` - * psa_key_policy_set_usage(&policy, - * PSA_KEY_USAGE_SIGN, //or PSA_KEY_USAGE_VERIFY - * PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH)); - * psa_set_key_policy(handle, &policy); + * psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN); // or VERIFY + * psa_set_key_algorithm(&attributes, PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH)); * ``` * - Import or generate key material. * - Call psa_asymmetric_sign() or psa_asymmetric_verify(), passing From dc8219a10da08964ab4127219dce776c7da4850c Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 15 May 2019 16:11:15 +0200 Subject: [PATCH 2/6] Replace psa_make_key_persistent by id/lifetime setters Use individual setters for the id and lifetime fields of an attribute structure, like the other attributes. This commit updates the specification and adds an implementation of the new setters. --- include/psa/crypto.h | 46 ++++++++++++++++++++++++++++--------- include/psa/crypto_struct.h | 16 +++++++++++++ 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 77ade6c897..0d0de2e0a5 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -132,7 +132,8 @@ psa_status_t psa_crypto_init(void); * psa_reset_key_attributes() on an attribute structure is optional if * the structure has only been modified by the following functions * since it was initialized or last reset with psa_reset_key_attributes(): - * - psa_make_key_persistent() + * - psa_set_key_id() + * - psa_set_key_lifetime() * - psa_set_key_type() * - psa_set_key_bits() * - psa_set_key_usage_flags() @@ -173,7 +174,9 @@ psa_status_t psa_crypto_init(void); * * A typical sequence to create a key is as follows: * -# Create and initialize an attribute structure. - * -# If the key is persistent, call psa_make_key_persistent(). + * -# If the key is persistent, call psa_set_key_id(). + * Also call psa_set_key_lifetime() to place the key in a non-default + * location. * -# Set the key policy with psa_set_key_usage_flags() and * psa_set_key_algorithm(). * -# Set the key type with psa_set_key_type(). If the key type requires @@ -203,30 +206,51 @@ psa_status_t psa_crypto_init(void); */ typedef struct psa_key_attributes_s psa_key_attributes_t; -/** Declare a key as persistent. +/** Declare a key as persistent and set its key identifier. + * + * If the attribute structure declares the key as volatile (which is + * the default content of an attribute structure), this function sets + * the lifetime attribute to #PSA_KEY_LIFETIME_PERSISTENT. * * This function does not access storage, it merely fills the attribute - * structure with given values. The persistent key will be written to + * structure with given value. The persistent key will be written to * storage when the attribute structure is passed to a key creation * function such as psa_import_key(), psa_generate_random_key(), * psa_generate_derived_key() or psa_copy_key(). * - * This function overwrites any identifier and lifetime values - * previously set in \p attributes. - * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate each of its arguments exactly once. * * \param[out] attributes The attribute structure to write to. * \param id The persistent identifier for the key. + */ +static void psa_set_key_id(psa_key_attributes_t *attributes, + psa_key_id_t id); + +/** Set the location of a persistent key. + * + * To make a key persistent, you must give it a persistent key identifier + * with psa_set_key_id(). + * + * This function does not access storage, it merely fills the attribute + * structure with given value. The persistent key will be written to + * storage when the attribute structure is passed to a key creation + * function such as psa_import_key(), psa_generate_random_key(), + * psa_generate_derived_key() or psa_copy_key(). + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. * \param lifetime The lifetime for the key. * If this is #PSA_KEY_LIFETIME_VOLATILE, the - * key will be volatile, and \p id is ignored. + * key will be volatile, and the key identifier + * attribute is reset to 0. */ -static void psa_make_key_persistent(psa_key_attributes_t *attributes, - psa_key_id_t id, - psa_key_lifetime_t lifetime); +static void psa_set_key_lifetime(psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime); /** Retrieve the key identifier from key attributes. * diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index f6bec2cf5f..91adc85f6a 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -287,12 +287,28 @@ static inline void psa_make_key_persistent(psa_key_attributes_t *attributes, attributes->lifetime = lifetime; } +static inline void psa_set_key_id(psa_key_attributes_t *attributes, + psa_key_id_t id) +{ + attributes->id = id; + if( attributes->lifetime == PSA_KEY_LIFETIME_VOLATILE ) + attributes->lifetime = PSA_KEY_LIFETIME_PERSISTENT; +} + static inline psa_key_id_t psa_get_key_id( const psa_key_attributes_t *attributes) { return( attributes->id ); } +static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime) +{ + attributes->lifetime = lifetime; + if( lifetime == PSA_KEY_LIFETIME_VOLATILE ) + attributes->id = 0; +} + static inline psa_key_lifetime_t psa_get_key_lifetime( const psa_key_attributes_t *attributes) { From c87af66325f55db15c72671e47f4800a67bb16ef Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 15 May 2019 16:12:22 +0200 Subject: [PATCH 3/6] Replace psa_make_key_persistent by id/lifetime setters in tests Remove all internal uses of psa_make_key_persistent. --- tests/suites/test_suite_psa_crypto.function | 7 ++-- ...t_suite_psa_crypto_persistent_key.function | 10 +++--- ..._suite_psa_crypto_slot_management.function | 33 ++++++++++++------- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 6002da0881..4ae9deb094 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -1096,7 +1096,7 @@ static int test_operations_on_invalid_handle( psa_key_handle_t handle ) size_t length; int ok = 0; - psa_make_key_persistent( &attributes, 0x6964, PSA_KEY_LIFETIME_PERSISTENT ); + psa_set_key_id( &attributes, 0x6964 ); psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT ); psa_set_key_algorithm( &attributes, PSA_ALG_CTR ); psa_set_key_type( &attributes, PSA_KEY_TYPE_AES ); @@ -1179,7 +1179,8 @@ void attributes_set_get( int id_arg, int lifetime_arg, TEST_EQUAL( psa_get_key_type( &attributes ), 0 ); TEST_EQUAL( psa_get_key_bits( &attributes ), 0 ); - psa_make_key_persistent( &attributes, id, lifetime ); + psa_set_key_id( &attributes, id ); + psa_set_key_lifetime( &attributes, lifetime ); psa_set_key_usage_flags( &attributes, usage_flags ); psa_set_key_algorithm( &attributes, alg ); psa_set_key_type( &attributes, type ); @@ -4883,7 +4884,7 @@ void persistent_key_load_key_from_storage( data_t *data, PSA_ASSERT( psa_crypto_init() ); - psa_make_key_persistent( &attributes, key_id, PSA_KEY_LIFETIME_PERSISTENT ); + psa_set_key_id( &attributes, key_id ); psa_set_key_usage_flags( &attributes, usage_flags ); psa_set_key_algorithm( &attributes, alg ); psa_set_key_type( &attributes, type ); diff --git a/tests/suites/test_suite_psa_crypto_persistent_key.function b/tests/suites/test_suite_psa_crypto_persistent_key.function index a2f4f779b7..38893f7c6d 100644 --- a/tests/suites/test_suite_psa_crypto_persistent_key.function +++ b/tests/suites/test_suite_psa_crypto_persistent_key.function @@ -96,7 +96,7 @@ void save_large_persistent_key( int data_too_large, int expected_status ) PSA_ASSERT( psa_crypto_init() ); - psa_make_key_persistent( &attributes, key_id, PSA_KEY_LIFETIME_PERSISTENT ); + psa_set_key_id( &attributes, key_id ); psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA ); TEST_EQUAL( psa_import_key( &attributes, &handle, @@ -123,7 +123,7 @@ void persistent_key_destroy( int key_id_arg, int restart, PSA_ASSERT( psa_crypto_init() ); - psa_make_key_persistent( &attributes, key_id, PSA_KEY_LIFETIME_PERSISTENT ); + psa_set_key_id( &attributes, key_id ); psa_set_key_type( &attributes, first_type ); PSA_ASSERT( psa_import_key( &attributes, &handle, @@ -153,7 +153,7 @@ void persistent_key_destroy( int key_id_arg, int restart, PSA_ASSERT( psa_crypto_init() ); /* Create another key in the same slot */ - psa_make_key_persistent( &attributes, key_id, PSA_KEY_LIFETIME_PERSISTENT ); + psa_set_key_id( &attributes, key_id ); psa_set_key_type( &attributes, second_type ); PSA_ASSERT( psa_import_key( &attributes, &handle, second_data->x, second_data->len ) ); @@ -175,7 +175,7 @@ void persistent_key_import( int key_id_arg, int type_arg, data_t *data, PSA_ASSERT( psa_crypto_init() ); - psa_make_key_persistent( &attributes, key_id, PSA_KEY_LIFETIME_PERSISTENT ); + psa_set_key_id( &attributes, key_id ); psa_set_key_type( &attributes, type ); TEST_EQUAL( psa_import_key( &attributes, &handle, data->x, data->len ), expected_status ); @@ -228,7 +228,7 @@ void import_export_persistent_key( data_t *data, int type_arg, PSA_ASSERT( psa_crypto_init( ) ); - psa_make_key_persistent( &attributes, key_id, PSA_KEY_LIFETIME_PERSISTENT ); + psa_set_key_id( &attributes, key_id ); psa_set_key_type( &attributes, type ); psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT ); diff --git a/tests/suites/test_suite_psa_crypto_slot_management.function b/tests/suites/test_suite_psa_crypto_slot_management.function index 03b7197a65..f037768956 100644 --- a/tests/suites/test_suite_psa_crypto_slot_management.function +++ b/tests/suites/test_suite_psa_crypto_slot_management.function @@ -127,7 +127,8 @@ void persistent_slot_lifecycle( int lifetime_arg, int id_arg, PSA_ASSERT( psa_crypto_init( ) ); /* Get a handle and import a key. */ - psa_make_key_persistent( &attributes, id, lifetime ); + 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 ); @@ -205,7 +206,8 @@ void create_existent( int lifetime_arg, int id_arg, PSA_ASSERT( psa_crypto_init( ) ); /* Create a key. */ - psa_make_key_persistent( &attributes, id, lifetime ); + 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 ); @@ -283,7 +285,8 @@ void create_fail( int lifetime_arg, int id_arg, PSA_ASSERT( psa_crypto_init( ) ); - psa_make_key_persistent( &attributes, id, lifetime ); + 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, &handle, material, sizeof( material ) ), @@ -330,8 +333,10 @@ void copy_across_lifetimes( int source_lifetime_arg, int source_id_arg, /* Populate the source slot. */ if( source_lifetime != PSA_KEY_LIFETIME_VOLATILE ) - psa_make_key_persistent( &source_attributes, - source_id, source_lifetime ); + { + 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 ); @@ -342,8 +347,10 @@ void copy_across_lifetimes( int source_lifetime_arg, int source_id_arg, /* Prepare the target slot. */ if( target_lifetime != PSA_KEY_LIFETIME_VOLATILE ) - psa_make_key_persistent( &target_attributes, - target_id, target_lifetime ); + { + 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 ); @@ -434,8 +441,10 @@ void copy_to_occupied( int source_lifetime_arg, int source_id_arg, /* Populate the source slot. */ if( source_lifetime != PSA_KEY_LIFETIME_VOLATILE ) - psa_make_key_persistent( &attributes, - source_id, source_lifetime ); + { + 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 ); @@ -449,7 +458,8 @@ void copy_to_occupied( int source_lifetime_arg, int source_id_arg, } else { - psa_make_key_persistent( &attributes1, target_id, target_lifetime ); + 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 ); @@ -459,7 +469,8 @@ void copy_to_occupied( int source_lifetime_arg, int source_id_arg, PSA_ASSERT( psa_get_key_attributes( target_handle, &attributes1 ) ); /* Make a copy attempt. */ - psa_make_key_persistent( &attributes, target_id, target_lifetime ); + 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 ); From 9de5eb0a2f56654be2c88565bad7ca62a4d6e606 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 15 May 2019 16:14:48 +0200 Subject: [PATCH 4/6] Remove psa_make_key_persistent --- include/psa/crypto_struct.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index 91adc85f6a..df765711cb 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -279,14 +279,6 @@ static inline struct psa_key_attributes_s psa_key_attributes_init( void ) return( v ); } -static inline void psa_make_key_persistent(psa_key_attributes_t *attributes, - psa_key_id_t id, - psa_key_lifetime_t lifetime) -{ - attributes->id = id; - attributes->lifetime = lifetime; -} - static inline void psa_set_key_id(psa_key_attributes_t *attributes, psa_key_id_t id) { From dd835cbea6d8788dcc2f662bf65c30f85f73bcb0 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 15 May 2019 16:14:57 +0200 Subject: [PATCH 5/6] Add a few tests for persistent attributes psa_set_key_lifetime and psa_set_key_id aren't pure setters: they also set the other attribute in some conditions. Add dedicated tests for this behavior. --- tests/suites/test_suite_psa_crypto.data | 15 ++++++++++++++ tests/suites/test_suite_psa_crypto.function | 23 +++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 4a1a04fc4f..1d3e3cfe2b 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -4,6 +4,21 @@ static_checks: PSA key attributes structure attributes_set_get:0x6963:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:128 +PSA key attributes: id only +persistence_attributes:0x1234:-1:-1:0x1234:PSA_KEY_LIFETIME_PERSISTENT + +PSA key attributes: lifetime=3 only +persistence_attributes:-1:3:-1:0:3 + +PSA key attributes: id then back to volatile +persistence_attributes:0x1234:PSA_KEY_LIFETIME_VOLATILE:-1:0:PSA_KEY_LIFETIME_VOLATILE + +PSA key attributes: id then lifetime +persistence_attributes:0x1234:3:-1:0x1234:3 + +PSA key attributes: lifetime then id +persistence_attributes:0x1234:3:0x1235:0x1235:3 + PSA import/export raw: 0 bytes import_export:"":PSA_KEY_TYPE_RAW_DATA:0:PSA_KEY_USAGE_EXPORT:0:0:PSA_SUCCESS:1 diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 4ae9deb094..cbe6616fdd 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -1204,6 +1204,29 @@ void attributes_set_get( int id_arg, int lifetime_arg, } /* END_CASE */ +/* BEGIN_CASE */ +void persistence_attributes( int id1_arg, int lifetime_arg, int id2_arg, + int expected_id_arg, int expected_lifetime_arg ) +{ + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t id1 = id1_arg; + psa_key_lifetime_t lifetime = lifetime_arg; + psa_key_id_t id2 = id2_arg; + psa_key_id_t expected_id = expected_id_arg; + psa_key_lifetime_t expected_lifetime = expected_lifetime_arg; + + if( id1_arg != -1 ) + psa_set_key_id( &attributes, id1 ); + if( lifetime_arg != -1 ) + psa_set_key_lifetime( &attributes, lifetime ); + if( id2_arg != -1 ) + psa_set_key_id( &attributes, id2 ); + + TEST_EQUAL( psa_get_key_id( &attributes ), expected_id ); + TEST_EQUAL( psa_get_key_lifetime( &attributes ), expected_lifetime ); +} +/* END_CASE */ + /* BEGIN_CASE */ void import( data_t *data, int type_arg, int attr_bits_arg, From f1b7694768048f653179ece50234c08204927bf6 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 16 May 2019 16:10:59 +0200 Subject: [PATCH 6/6] Minor documentation improvements --- include/psa/crypto.h | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 0d0de2e0a5..e43a301a0a 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -208,14 +208,15 @@ typedef struct psa_key_attributes_s psa_key_attributes_t; /** Declare a key as persistent and set its key identifier. * - * If the attribute structure declares the key as volatile (which is - * the default content of an attribute structure), this function sets + * If the attribute structure currently declares the key as volatile (which + * is the default content of an attribute structure), this function sets * the lifetime attribute to #PSA_KEY_LIFETIME_PERSISTENT. * - * This function does not access storage, it merely fills the attribute - * structure with given value. The persistent key will be written to - * storage when the attribute structure is passed to a key creation - * function such as psa_import_key(), psa_generate_random_key(), + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_random_key(), * psa_generate_derived_key() or psa_copy_key(). * * This function may be declared as `static` (i.e. without external @@ -231,12 +232,16 @@ static void psa_set_key_id(psa_key_attributes_t *attributes, /** Set the location of a persistent key. * * To make a key persistent, you must give it a persistent key identifier - * with psa_set_key_id(). + * with psa_set_key_id(). By default, a key that has a persistent identifier + * is stored in the default storage area identifier by + * #PSA_KEY_LIFETIME_PERSISTENT. Call this function to choose a storage + * area, or to explicitly declare the key as volatile. * - * This function does not access storage, it merely fills the attribute - * structure with given value. The persistent key will be written to - * storage when the attribute structure is passed to a key creation - * function such as psa_import_key(), psa_generate_random_key(), + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_random_key(), * psa_generate_derived_key() or psa_copy_key(). * * This function may be declared as `static` (i.e. without external