From d7dc7ff91cc5c2638d7ee41b61fa5af25668c25e Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Thu, 21 Dec 2023 16:40:43 +0000 Subject: [PATCH 01/20] Update psa_key_slot_t Remove the `status` field and replace with the `state` field. Remove the `lock_count` field and replace with the `registered_readers` field. Add documentation which describes how and why these fields are to be used. Signed-off-by: Ryan Everett --- library/psa_crypto_core.h | 50 ++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index 46c57755e..9ea482da2 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -35,8 +35,10 @@ int psa_can_do_hash(psa_algorithm_t hash_alg); typedef enum { PSA_SLOT_EMPTY = 0, - PSA_SLOT_OCCUPIED, -} psa_key_slot_status_t; + PSA_SLOT_FILLING, + PSA_SLOT_FULL, + PSA_SLOT_PENDING_DELETION, +} psa_key_slot_state_t; /** The data structure representing a key slot, containing key material * and metadata for one key. @@ -44,18 +46,39 @@ typedef enum { typedef struct { psa_core_key_attributes_t attr; - psa_key_slot_status_t status; + /* + * The current state of the key slot, as described in + * docs/architecture/psa-thread-safety/psa-thread-safety.md. + * + * Library functions can modify the state of a key slot by calling + * psa_key_slot_state_transition. + * + * The state variable is used to help determine whether library functions + * which operate on the slot succeed. For example, psa_finish_key_creation, + * which transfers the state of a slot from PSA_SLOT_FILLING to + * PSA_SLOT_FULL, must fail with error code PSA_ERROR_BAD_STATE + * if the state of the slot is not PSA_SLOT_FILLING. + * + * Library functions which traverse the array of key slots only consider + * slots that are in a suitable state for the function. + * For example, psa_get_and_lock_key_slot_in_memory, which finds a slot + * containing a given key ID, will only check slots whose state variable is + * PSA_SLOT_FULL. */ + psa_key_slot_state_t state; /* - * Number of locks on the key slot held by the library. + * Number of functions registered as reading the material in the key slot. * - * This counter is incremented by one each time a library function - * retrieves through one of the dedicated internal API a pointer to the - * key slot. + * Library functions must not write directly to registered_readers + * (unless the slot's state is PSA_SLOT_FILLING and the slot needs to be + * wiped following a failed key creation). * - * This counter is decremented by one each time a library function stops - * accessing the key slot and states it by calling the - * psa_unlock_key_slot() API. + * A function must call psa_register_read(slot) before reading the current + * contents of the slot for an operation. + * They then must call psa_unregister_read(slot) once they have finished + * reading the current contents of the slot. + * A function must call psa_key_slot_has_readers(slot) to check if + * the slot is in use for reading. * * This counter is used to prevent resetting the key slot while the library * may access it. For example, such control is needed in the following @@ -66,10 +89,9 @@ typedef struct { * the library cannot be reclaimed to free a key slot to load the * persistent key. * . In case of a multi-threaded application where one thread asks to close - * or purge or destroy a key while it is in used by the library through - * another thread. - */ - size_t lock_count; + * or purge or destroy a key while it is in use by the library through + * another thread. */ + size_t registered_readers; /* Dynamically allocated key data buffer. * Format as specified in psa_export_key(). */ From aa33c512cc489d18cbb48b6b64aa959046a83dd1 Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Thu, 21 Dec 2023 17:32:07 +0000 Subject: [PATCH 02/20] Update psa_wipe_key_slot Change psa_wipe_key_slot to use the new state system. Signed-off-by: Ryan Everett --- library/psa_crypto.c | 16 +++++++++++----- library/psa_crypto_core.h | 9 ++++++--- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 10d17b6df..7a76c0bbf 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -981,18 +981,23 @@ psa_status_t psa_remove_key_data_from_memory(psa_key_slot_t *slot) * Persistent storage is not affected. */ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot) { + if (slot->state != PSA_SLOT_PENDING_DELETION) { + return PSA_ERROR_BAD_STATE; + } + psa_status_t status = psa_remove_key_data_from_memory(slot); /* * As the return error code may not be handled in case of multiple errors, - * do our best to report an unexpected lock counter. Assert with - * MBEDTLS_TEST_HOOK_TEST_ASSERT that the lock counter is equal to one: + * do our best to report an unexpected amount of registered readers. + * Assert with MBEDTLS_TEST_HOOK_TEST_ASSERT that registered_readers is + * equal to one: * if the MBEDTLS_TEST_HOOKS configuration option is enabled and the * function is called as part of the execution of a test suite, the * execution of the test suite is stopped in error if the assertion fails. */ - if (slot->lock_count != 1) { - MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->lock_count == 1); + if (slot->registered_readers != 1) { + MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->registered_readers == 1); status = PSA_ERROR_CORRUPTION_DETECTED; } @@ -1003,7 +1008,8 @@ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot) * key material can linger until all operations are completed. */ /* At this point, key material and other type-specific content has * been wiped. Clear remaining metadata. We can call memset and not - * zeroize because the metadata is not particularly sensitive. */ + * zeroize because the metadata is not particularly sensitive. + * This memset also sets the slot's state to PSA_SLOT_EMPTY. */ memset(slot, 0, sizeof(*slot)); return status; } diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index 9ea482da2..5c1edafe7 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -200,13 +200,16 @@ static inline psa_key_slot_number_t psa_key_slot_get_slot_number( /** Completely wipe a slot in memory, including its policy. * * Persistent storage is not affected. + * Sets the slot's state to PSA_SLOT_EMPTY. * * \param[in,out] slot The key slot to wipe. * * \retval #PSA_SUCCESS - * Success. This includes the case of a key slot that was - * already fully wiped. - * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * The slot has been successfully wiped. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * The amount of registered readers was not equal to 1. + * \retval #PSA_ERROR_BAD_STATE + * The slot's state was not PSA_SLOT_PENDING_DELETION. */ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot); From 62aa79ac5c4dd4623af9a04a0caa96bcb6c23580 Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Tue, 2 Jan 2024 16:21:03 +0000 Subject: [PATCH 03/20] Implement psa_key_slot_has_readers and remove psa_is_key_slot_occupied Remove psa_is_key_slot_occupied, any function which calls this can just check the state variable instead. Replace psa_is_key_slot_locked with psa_key_slot_has_readers. References to the now removed functions are changed in future commits. Signed-off-by: Ryan Everett --- library/psa_crypto_core.h | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index 5c1edafe7..3b5c63497 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -106,31 +106,15 @@ typedef struct { #define PSA_KA_MASK_INTERNAL_ONLY ( \ 0) -/** Test whether a key slot is occupied. - * - * A key slot is occupied iff the key type is nonzero. This works because - * no valid key can have 0 as its key type. +/** Test whether a key slot has any registered readers. * * \param[in] slot The key slot to test. * - * \return 1 if the slot is occupied, 0 otherwise. + * \return 1 if the slot has any registered readers, 0 otherwise. */ -static inline int psa_is_key_slot_occupied(const psa_key_slot_t *slot) +static inline int psa_key_slot_has_readers(const psa_key_slot_t *slot) { - return slot->status == PSA_SLOT_OCCUPIED; -} - -/** Test whether a key slot is locked. - * - * A key slot is locked iff its lock counter is strictly greater than 0. - * - * \param[in] slot The key slot to test. - * - * \return 1 if the slot is locked, 0 otherwise. - */ -static inline int psa_is_key_slot_locked(const psa_key_slot_t *slot) -{ - return slot->lock_count > 0; + return slot->registered_readers > 0; } /** Retrieve flags from psa_key_slot_t::attr::core::flags. From 39cc9d755e20827cb7ebc3cde53065def94e2ef6 Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Thu, 21 Dec 2023 17:57:14 +0000 Subject: [PATCH 04/20] Implement psa_register_read and psa_unregister_read Replaces psa_lock_key_slot and psa_unlock_key_slot. Future commits will remove the calls to locking/unlocking functions, and add calls to registering/unregistering functions. Signed-off-by: Ryan Everett --- library/psa_crypto_slot_management.c | 25 ++++++++++++----- library/psa_crypto_slot_management.h | 40 +++++++++++++++++----------- 2 files changed, 43 insertions(+), 22 deletions(-) diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index 5ecc3a76c..32881e5e9 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -394,26 +394,37 @@ psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key, #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ } -psa_status_t psa_unlock_key_slot(psa_key_slot_t *slot) +psa_status_t psa_unregister_read(psa_key_slot_t *slot) { if (slot == NULL) { return PSA_SUCCESS; } + if ((slot->state != PSA_SLOT_FULL) && + (slot->state != PSA_SLOT_PENDING_DELETION)) { + return PSA_ERROR_BAD_STATE; + } - if (slot->lock_count > 0) { - slot->lock_count--; + /* If we are the last reader and the slot is marked for deletion, + * we must wipe the slot here. */ + if ((slot->state == PSA_SLOT_PENDING_DELETION) && + (slot->registered_readers == 1)) { + return psa_wipe_key_slot(slot); + } + + if (psa_key_slot_has_readers(slot)) { + slot->registered_readers--; return PSA_SUCCESS; } /* * As the return error code may not be handled in case of multiple errors, - * do our best to report if the lock counter is equal to zero. Assert with - * MBEDTLS_TEST_HOOK_TEST_ASSERT that the lock counter is strictly greater - * than zero: if the MBEDTLS_TEST_HOOKS configuration option is enabled and + * do our best to report if there are no registered readers. Assert with + * MBEDTLS_TEST_HOOK_TEST_ASSERT that there are registered readers: + * if the MBEDTLS_TEST_HOOKS configuration option is enabled and * the function is called as part of the execution of a test suite, the * execution of the test suite is stopped in error if the assertion fails. */ - MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->lock_count > 0); + MBEDTLS_TEST_HOOK_TEST_ASSERT(psa_key_slot_has_readers(slot)); return PSA_ERROR_CORRUPTION_DETECTED; } diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h index 6041a3528..c38876d3d 100644 --- a/library/psa_crypto_slot_management.h +++ b/library/psa_crypto_slot_management.h @@ -113,32 +113,39 @@ void psa_wipe_all_key_slots(void); psa_status_t psa_get_empty_key_slot(psa_key_id_t *volatile_key_id, psa_key_slot_t **p_slot); -/** Lock a key slot. +/** Register as a reader of a key slot. * - * This function increments the key slot lock counter by one. + * This function increments the key slot registered reader counter by one. * * \param[in] slot The key slot. * * \retval #PSA_SUCCESS - The key slot lock counter was incremented. + The key slot registered reader counter was incremented. * \retval #PSA_ERROR_CORRUPTION_DETECTED - * The lock counter already reached its maximum value and was not + * The reader counter already reached its maximum value and was not * increased. + * \retval #PSA_ERROR_BAD_STATE + * The slot's state was not PSA_SLOT_FULL. */ -static inline psa_status_t psa_lock_key_slot(psa_key_slot_t *slot) +static inline psa_status_t psa_register_read(psa_key_slot_t *slot) { - if (slot->lock_count >= SIZE_MAX) { + if (slot->state != PSA_SLOT_FULL) { + return PSA_ERROR_BAD_STATE; + } + if (slot->registered_readers >= SIZE_MAX) { return PSA_ERROR_CORRUPTION_DETECTED; } - - slot->lock_count++; + slot->registered_readers++; return PSA_SUCCESS; } -/** Unlock a key slot. +/** Unregister from reading a key slot. * - * This function decrements the key slot lock counter by one. + * This function decrements the key slot registered reader counter by one. + * If the state of the slot is PSA_SLOT_PENDING_DELETION, + * and there is only one registered reader (the caller), + * this function will call psa_wipe_slot(). * * \note To ease the handling of errors in retrieving a key slot * a NULL input pointer is valid, and the function returns @@ -146,13 +153,16 @@ static inline psa_status_t psa_lock_key_slot(psa_key_slot_t *slot) * * \param[in] slot The key slot. * \retval #PSA_SUCCESS - * \p slot is NULL or the key slot lock counter has been - * decremented successfully. + * \p slot is NULL or the key slot reader counter has been + * decremented (and potentially wiped) successfully. * \retval #PSA_ERROR_CORRUPTION_DETECTED - * The lock counter was equal to 0. - * + * registered_readers was equal to 0. + * \retval #PSA_ERROR_BAD_STATE + * The slot's state was neither PSA_SLOT_FULL nor + * PSA_SLOT_PENDING_DELETION, or a wipe was attempted and + * the slot's state was not PSA_SLOT_PENDING_DELETION. */ -psa_status_t psa_unlock_key_slot(psa_key_slot_t *slot); +psa_status_t psa_unregister_read(psa_key_slot_t *slot); /** Test whether a lifetime designates a key in an external cryptoprocessor. * From 4a78277cb2684ca0e9615ba390ecee87d27dde06 Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Thu, 4 Jan 2024 10:53:26 +0000 Subject: [PATCH 05/20] Implement psa_key_slot_state_transition This inline function is used in every case we want to change the state of a slot, except for where we do not care about what the state of the slot was before. Signed-off-by: Ryan Everett --- library/psa_crypto_slot_management.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h index c38876d3d..f0bbed98f 100644 --- a/library/psa_crypto_slot_management.h +++ b/library/psa_crypto_slot_management.h @@ -112,6 +112,31 @@ void psa_wipe_all_key_slots(void); */ psa_status_t psa_get_empty_key_slot(psa_key_id_t *volatile_key_id, psa_key_slot_t **p_slot); +/** Change the state of a key slot. + * + * This function changes the state of the key slot from expected_state to + * new state. If the state of the slot was not expected_state, the state is + * unchanged. + * + * \param[in] slot The key slot. + * \param[in] expected_state The current state of the slot. + * \param[in] new_state The new state of the slot. + * + * \retval #PSA_SUCCESS + The key slot's state variable is new_state. + * \retval #PSA_ERROR_BAD_STATE + * The slot's state was not expected_state. + */ +static inline psa_status_t psa_key_slot_state_transition( + psa_key_slot_t *slot, psa_key_slot_state_t expected_state, + psa_key_slot_state_t new_state) +{ + if (slot->state != expected_state) { + return PSA_ERROR_BAD_STATE; + } + slot->state = new_state; + return PSA_SUCCESS; +} /** Register as a reader of a key slot. * From 2afb5160110f54a5d89e968723b3dbb940de42b7 Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Fri, 22 Dec 2023 15:59:45 +0000 Subject: [PATCH 06/20] Update and rename psa_get_empty_key_slot Rename to psa_reserve_free_key_slot, as this function reserves a slot which is free (not always empty) for filling. Implement necessary state transitions and state checks. Rename unlocked_persistent_key_slot to unused_persistent_key_slot. Signed-off-by: Ryan Everett --- library/psa_crypto_slot_management.c | 39 +++++++++++++++++----------- library/psa_crypto_slot_management.h | 24 ++++++++++------- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index 32881e5e9..0f480fb09 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -147,30 +147,31 @@ void psa_wipe_all_key_slots(void) global_data.key_slots_initialized = 0; } -psa_status_t psa_get_empty_key_slot(psa_key_id_t *volatile_key_id, - psa_key_slot_t **p_slot) +psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id, + psa_key_slot_t **p_slot) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t slot_idx; - psa_key_slot_t *selected_slot, *unlocked_persistent_key_slot; + psa_key_slot_t *selected_slot, *unused_persistent_key_slot; if (!global_data.key_slots_initialized) { status = PSA_ERROR_BAD_STATE; goto error; } - selected_slot = unlocked_persistent_key_slot = NULL; + selected_slot = unused_persistent_key_slot = NULL; for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) { psa_key_slot_t *slot = &global_data.key_slots[slot_idx]; - if (!psa_is_key_slot_occupied(slot)) { + if (slot->state == PSA_SLOT_EMPTY) { selected_slot = slot; break; } - if ((unlocked_persistent_key_slot == NULL) && - (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) && - (!psa_is_key_slot_locked(slot))) { - unlocked_persistent_key_slot = slot; + if ((unused_persistent_key_slot == NULL) && + (slot->state == PSA_SLOT_FULL) && + (!psa_key_slot_has_readers(slot)) && + (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime))) { + unused_persistent_key_slot = slot; } } @@ -182,16 +183,24 @@ psa_status_t psa_get_empty_key_slot(psa_key_id_t *volatile_key_id, * storage. */ if ((selected_slot == NULL) && - (unlocked_persistent_key_slot != NULL)) { - selected_slot = unlocked_persistent_key_slot; - selected_slot->lock_count = 1; - psa_wipe_key_slot(selected_slot); + (unused_persistent_key_slot != NULL)) { + selected_slot = unused_persistent_key_slot; + psa_register_read(selected_slot); + /* If the state is not changed then psa_wipe_key_slot + * will report an error. */ + psa_key_slot_state_transition(selected_slot, PSA_SLOT_FULL, + PSA_SLOT_PENDING_DELETION); + status = psa_wipe_key_slot(selected_slot); + if (status != PSA_SUCCESS) { + goto error; + } } if (selected_slot != NULL) { - status = psa_lock_key_slot(selected_slot); + status = psa_key_slot_state_transition(selected_slot, PSA_SLOT_EMPTY, + PSA_SLOT_FILLING); if (status != PSA_SUCCESS) { - goto error; + return status; } *volatile_key_id = PSA_KEY_ID_VOLATILE_MIN + diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h index f0bbed98f..b2cf57011 100644 --- a/library/psa_crypto_slot_management.h +++ b/library/psa_crypto_slot_management.h @@ -95,23 +95,29 @@ psa_status_t psa_initialize_key_slots(void); * This does not affect persistent storage. */ void psa_wipe_all_key_slots(void); -/** Find a free key slot. +/** Find a free key slot and reserve it to be filled with a key. * - * This function returns a key slot that is available for use and is in its - * ground state (all-bits-zero). On success, the key slot is locked. It is - * the responsibility of the caller to unlock the key slot when it does not - * access it anymore. + * This function finds a key slot that is free, + * sets its state to PSA_SLOT_FILLING and then returns the slot. + * + * On success, the key slot's state is PSA_SLOT_FILLING. + * It is the responsibility of the caller to change the slot's state to + * PSA_SLOT_EMPTY/FULL once key creation has finished. * * \param[out] volatile_key_id On success, volatile key identifier * associated to the returned slot. * \param[out] p_slot On success, a pointer to the slot. * * \retval #PSA_SUCCESS \emptydescription - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription - * \retval #PSA_ERROR_BAD_STATE \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * There were no free key slots. + * \retval #PSA_ERROR_BAD_STATE + * This function attempted to operate on a key slot which was in an + * unexpected state. */ -psa_status_t psa_get_empty_key_slot(psa_key_id_t *volatile_key_id, - psa_key_slot_t **p_slot); +psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id, + psa_key_slot_t **p_slot); + /** Change the state of a key slot. * * This function changes the state of the key slot from expected_state to From b69118ebd0b7aa63d5b7c9b2c17f295aa4c854f8 Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Tue, 2 Jan 2024 15:54:32 +0000 Subject: [PATCH 07/20] Update key creation functions to use the new key slot states Update psa_start_key_creation, psa_finish_key_creation and psa_fail_key_creation. Signed-off-by: Ryan Everett --- library/psa_crypto.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 7a76c0bbf..3c5bbbdf6 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1576,8 +1576,9 @@ static psa_status_t psa_validate_key_attributes( * In case of failure at any step, stop the sequence and call * psa_fail_key_creation(). * - * On success, the key slot is locked. It is the responsibility of the caller - * to unlock the key slot when it does not access it anymore. + * On success, the key slot's state is PSA_SLOT_FILLING. + * It is the responsibility of the caller to change the slot's state to + * PSA_SLOT_EMPTY/FULL once key creation has finished. * * \param method An identification of the calling function. * \param[in] attributes Key attributes for the new key. @@ -1608,7 +1609,7 @@ static psa_status_t psa_start_key_creation( return status; } - status = psa_get_empty_key_slot(&volatile_key_id, p_slot); + status = psa_reserve_free_key_slot(&volatile_key_id, p_slot); if (status != PSA_SUCCESS) { return status; } @@ -1634,7 +1635,7 @@ static psa_status_t psa_start_key_creation( /* Erase external-only flags from the internal copy. To access * external-only flags, query `attributes`. Thanks to the check * in psa_validate_key_attributes(), this leaves the dual-use - * flags and any internal flag that psa_get_empty_key_slot() + * flags and any internal flag that psa_reserve_free_key_slot() * may have set. */ slot->attr.flags &= ~MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY; @@ -1686,8 +1687,6 @@ static psa_status_t psa_start_key_creation( } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - slot->status = PSA_SLOT_OCCUPIED; - return PSA_SUCCESS; } @@ -1699,9 +1698,9 @@ static psa_status_t psa_start_key_creation( * See the documentation of psa_start_key_creation() for the intended use * of this function. * - * If the finalization succeeds, the function unlocks the key slot (it was - * locked by psa_start_key_creation()) and the key slot cannot be accessed - * anymore as part of the key creation process. + * If the finalization succeeds, the function sets the key slot's state to + * PSA_SLOT_FULL, and the key slot can no longer be accessed as part of the + * key creation process. * * \param[in,out] slot Pointer to the slot with key material. * \param[in] driver The secure element driver for the key, @@ -1717,6 +1716,7 @@ static psa_status_t psa_start_key_creation( * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_BAD_STATE \emptydescription * * \return If this function fails, the key slot is an invalid state. * You must call psa_fail_key_creation() to wipe and free the slot. @@ -1777,7 +1777,8 @@ static psa_status_t psa_finish_key_creation( if (status == PSA_SUCCESS) { *key = slot->attr.id; - status = psa_unlock_key_slot(slot); + status = psa_key_slot_state_transition(slot, PSA_SLOT_FILLING, + PSA_SLOT_FULL); if (status != PSA_SUCCESS) { *key = MBEDTLS_SVC_KEY_ID_INIT; } @@ -1792,7 +1793,7 @@ static psa_status_t psa_finish_key_creation( * or after psa_finish_key_creation() fails. In other circumstances, this * function may not clean up persistent storage. * See the documentation of psa_start_key_creation() for the intended use - * of this function. + * of this function. Sets the slot's state to PSA_SLOT_EMPTY. * * \param[in,out] slot Pointer to the slot with key material. * \param[in] driver The secure element driver for the key, @@ -1824,6 +1825,11 @@ static void psa_fail_key_creation(psa_key_slot_t *slot, (void) psa_crypto_stop_transaction(); #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + /* Prepare the key slot to be wiped, and then wipe it. */ + slot->registered_readers = 1; + psa_key_slot_state_transition(slot, PSA_SLOT_FILLING, + PSA_SLOT_PENDING_DELETION); + psa_wipe_key_slot(slot); } From 098c6659ada1a89194caddcf8bc7334a463f502b Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Wed, 3 Jan 2024 13:03:36 +0000 Subject: [PATCH 08/20] Update psa_get_and_lock_key_slot_X functions Signed-off-by: Ryan Everett --- library/psa_crypto.c | 14 ++++++++------ library/psa_crypto_slot_management.c | 19 ++++++++++++++++--- library/psa_crypto_slot_management.h | 9 ++++++--- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 3c5bbbdf6..a27fd42c4 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -881,8 +881,9 @@ static psa_status_t psa_restrict_key_policy( * In case of a persistent key, the function loads the description of the key * into a key slot if not already done. * - * On success, the returned key slot is locked. It is the responsibility of - * the caller to unlock the key slot when it does not access it anymore. + * On success, the returned key slot has been registered for reading. + * It is the responsibility of the caller to call psa_unregister_read(slot) + * when they have finished reading the contents of the slot. */ static psa_status_t psa_get_and_lock_key_slot_with_policy( mbedtls_svc_key_id_t key, @@ -926,7 +927,7 @@ static psa_status_t psa_get_and_lock_key_slot_with_policy( error: *p_slot = NULL; - psa_unlock_key_slot(slot); + psa_unregister_read(slot); return status; } @@ -941,8 +942,9 @@ error: * psa_get_and_lock_key_slot_with_policy() when there is no opaque key support * for a cryptographic operation. * - * On success, the returned key slot is locked. It is the responsibility of the - * caller to unlock the key slot when it does not access it anymore. + * On success, the returned key slot has been registered for reading. + * It is the responsibility of the caller to call psa_unregister_read(slot) + * when they have finished reading the contents of the slot. */ static psa_status_t psa_get_and_lock_transparent_key_slot_with_policy( mbedtls_svc_key_id_t key, @@ -957,7 +959,7 @@ static psa_status_t psa_get_and_lock_transparent_key_slot_with_policy( } if (psa_key_lifetime_is_external((*p_slot)->attr.lifetime)) { - psa_unlock_key_slot(*p_slot); + psa_unregister_read(*p_slot); *p_slot = NULL; return PSA_ERROR_NOT_SUPPORTED; } diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index 0f480fb09..4846e33ea 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -108,7 +108,9 @@ static psa_status_t psa_get_and_lock_key_slot_in_memory( for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) { slot = &global_data.key_slots[slot_idx]; - if (mbedtls_svc_key_id_equal(key, slot->attr.id)) { + /* Only consider slots which are in a full state. */ + if ((slot->state == PSA_SLOT_FULL) && + (mbedtls_svc_key_id_equal(key, slot->attr.id))) { break; } } @@ -117,7 +119,7 @@ static psa_status_t psa_get_and_lock_key_slot_in_memory( } if (status == PSA_SUCCESS) { - status = psa_lock_key_slot(slot); + status = psa_register_read(slot); if (status == PSA_SUCCESS) { *p_slot = slot; } @@ -367,7 +369,7 @@ psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key, defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) psa_key_id_t volatile_key_id; - status = psa_get_empty_key_slot(&volatile_key_id, p_slot); + status = psa_reserve_free_key_slot(&volatile_key_id, p_slot); if (status != PSA_SUCCESS) { return status; } @@ -388,13 +390,24 @@ psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key, #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ if (status != PSA_SUCCESS) { + /* Prepare the key slot to be wiped, and then wipe it. + * Don't overwrite status as a BAD_STATE error here + * can be reported in the psa_wipe_key_slot call. */ + (*p_slot)->registered_readers = 1; + psa_key_slot_state_transition((*p_slot), PSA_SLOT_FILLING, + PSA_SLOT_PENDING_DELETION); psa_wipe_key_slot(*p_slot); + if (status == PSA_ERROR_DOES_NOT_EXIST) { status = PSA_ERROR_INVALID_HANDLE; } } else { /* Add implicit usage flags. */ psa_extend_key_usage_flags(&(*p_slot)->attr.policy.usage); + + psa_key_slot_state_transition((*p_slot), PSA_SLOT_FILLING, + PSA_SLOT_FULL); + status = psa_register_read(*p_slot); } return status; diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h index b2cf57011..5858b1851 100644 --- a/library/psa_crypto_slot_management.h +++ b/library/psa_crypto_slot_management.h @@ -54,8 +54,9 @@ static inline int psa_key_id_is_volatile(psa_key_id_t key_id) * In case of a persistent key, the function loads the description of the key * into a key slot if not already done. * - * On success, the returned key slot is locked. It is the responsibility of - * the caller to unlock the key slot when it does not access it anymore. + * On success, the returned key slot has been registered for reading. + * It is the responsibility of the caller to call psa_unregister_read(slot) + * when they have finished reading the contents of the slot. * * \param key Key identifier to query. * \param[out] p_slot On success, `*p_slot` contains a pointer to the @@ -67,7 +68,9 @@ static inline int psa_key_id_is_volatile(psa_key_id_t key_id) * description of the key identified by \p key. * The key slot counter has been incremented. * \retval #PSA_ERROR_BAD_STATE - * The library has not been initialized. + * The library has not been initialized. Or, + * this call was operating on a key slot and found the slot in + * an invalid state for the operation. * \retval #PSA_ERROR_INVALID_HANDLE * \p key is not a valid key identifier. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY From c70ce576bd8856a8efa99d4353700bd3130d000b Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Wed, 3 Jan 2024 16:04:33 +0000 Subject: [PATCH 09/20] Update psa_destroy_key, psa_purge_key and psa_close_key This does not yet implement destruction while a key is in use for psa_destroy_key; that will be implemented in a separate pr. (I am not sure if I am allowed to change the documentation in the include files.) Signed-off-by: Ryan Everett --- include/psa/crypto.h | 8 ++++++-- include/psa/crypto_compat.h | 4 +++- library/psa_crypto.c | 8 +++++--- library/psa_crypto_slot_management.c | 19 +++++++++++-------- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index fe10ee0e4..fd1928a65 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -415,7 +415,9 @@ void psa_reset_key_attributes(psa_key_attributes_t *attributes); * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize - * results in this error code. + * results in this error code. Or, + * this call was operating on a key slot and found the slot in + * an invalid state for the operation. */ psa_status_t psa_purge_key(mbedtls_svc_key_id_t key); @@ -555,7 +557,9 @@ psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key, * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize - * results in this error code. + * results in this error code. Or, + * this call was operating on a key slot and found the slot in + * an invalid state for the operation. */ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key); diff --git a/include/psa/crypto_compat.h b/include/psa/crypto_compat.h index f896fae1c..bfc00164b 100644 --- a/include/psa/crypto_compat.h +++ b/include/psa/crypto_compat.h @@ -142,7 +142,9 @@ psa_status_t psa_open_key(mbedtls_svc_key_id_t key, * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize - * results in this error code. + * results in this error code. Or, + * this call was operating on a key slot and found the slot in + * an invalid state for the operation. */ psa_status_t psa_close_key(psa_key_handle_t handle); diff --git a/library/psa_crypto.c b/library/psa_crypto.c index a27fd42c4..3e49d0a75 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1048,11 +1048,13 @@ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key) * implemented), the key should be destroyed when all accesses have * stopped. */ - if (slot->lock_count > 1) { - psa_unlock_key_slot(slot); + if (slot->registered_readers > 1) { + psa_unregister_read(slot); return PSA_ERROR_GENERIC_ERROR; } + slot->state = PSA_SLOT_PENDING_DELETION; + if (PSA_KEY_LIFETIME_IS_READ_ONLY(slot->attr.lifetime)) { /* Refuse the destruction of a read-only key (which may or may not work * if we attempt it, depending on whether the key is merely read-only @@ -1126,7 +1128,7 @@ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key) exit: status = psa_wipe_key_slot(slot); - /* Prioritize CORRUPTION_DETECTED from wiping over a storage error */ + /* Prioritize an error from wiping over a storage error */ if (status != PSA_SUCCESS) { overall_status = status; } diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index 4846e33ea..a21388a0b 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -539,11 +539,14 @@ psa_status_t psa_close_key(psa_key_handle_t handle) return status; } - if (slot->lock_count <= 1) { - return psa_wipe_key_slot(slot); - } else { - return psa_unlock_key_slot(slot); + if (slot->registered_readers == 1) { + status = psa_key_slot_state_transition(slot, PSA_SLOT_FULL, + PSA_SLOT_PENDING_DELETION); + if (status != PSA_SUCCESS) { + return status; + } } + return psa_unregister_read(slot); } psa_status_t psa_purge_key(mbedtls_svc_key_id_t key) @@ -557,11 +560,11 @@ psa_status_t psa_purge_key(mbedtls_svc_key_id_t key) } if ((!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) && - (slot->lock_count <= 1)) { - return psa_wipe_key_slot(slot); - } else { - return psa_unlock_key_slot(slot); + (slot->registered_readers == 1)) { + psa_key_slot_state_transition(slot, PSA_SLOT_FULL, + PSA_SLOT_PENDING_DELETION); } + return psa_unregister_read(slot); } void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats) From eb27dc0f3a95e0c75b45a3366e862324b90bc742 Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Wed, 3 Jan 2024 16:19:12 +0000 Subject: [PATCH 10/20] Update psa_load_X_key_into_slot These functions (on success) take a slot from PSA_SLOT_FILLING to PSA_SLOT_FULL. Signed-off-by: Ryan Everett --- library/psa_crypto_slot_management.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index a21388a0b..3d997a50c 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -250,7 +250,8 @@ static psa_status_t psa_load_persistent_key_into_slot(psa_key_slot_t *slot) slot, data->slot_number, sizeof(data->slot_number)); if (status == PSA_SUCCESS) { - slot->status = PSA_SLOT_OCCUPIED; + status = psa_key_slot_state_transition(slot, PSA_SLOT_FILLING, + PSA_SLOT_FULL); } goto exit; } @@ -261,7 +262,8 @@ static psa_status_t psa_load_persistent_key_into_slot(psa_key_slot_t *slot) goto exit; } - slot->status = PSA_SLOT_OCCUPIED; + status = psa_key_slot_state_transition(slot, PSA_SLOT_FILLING, + PSA_SLOT_FULL); exit: psa_free_persistent_key_data(key_data, key_data_length); @@ -335,8 +337,9 @@ static psa_status_t psa_load_builtin_key_into_slot(psa_key_slot_t *slot) /* Copy actual key length and core attributes into the slot on success */ slot->key.bytes = key_buffer_length; slot->attr = attributes.core; - slot->status = PSA_SLOT_OCCUPIED; + status = psa_key_slot_state_transition(slot, PSA_SLOT_FILLING, + PSA_SLOT_FULL); exit: if (status != PSA_SUCCESS) { psa_remove_key_data_from_memory(slot); From 1b70a07eca5bd44bef32203c59ecf5f033246f64 Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Thu, 4 Jan 2024 10:32:49 +0000 Subject: [PATCH 11/20] Replace psa_unlock_key_slot calls in operations which act on FULL slots Replaces calls to psa_unlock_key_slot with calls to psa_unregister_read. All instances follow a pattern of a call to psa_get_and_lock_key_slot_X, followed by some code which reads from a slot, followed by a call to psa_unregister_read. Signed-off-by: Ryan Everett --- library/psa_crypto.c | 44 ++++++++++++++-------------- library/psa_crypto_slot_management.c | 2 +- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 3e49d0a75..da5e5be77 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1253,7 +1253,7 @@ psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key, psa_reset_key_attributes(attributes); } - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -1349,7 +1349,7 @@ psa_status_t psa_export_key(mbedtls_svc_key_id_t key, slot->key.data, slot->key.bytes, data, data_size, data_length); - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -1463,7 +1463,7 @@ psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key, data, data_size, data_length); exit: - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -2141,7 +2141,7 @@ exit: psa_fail_key_creation(target_slot, driver); } - unlock_status = psa_unlock_key_slot(source_slot); + unlock_status = psa_unregister_read(source_slot); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -2462,7 +2462,7 @@ exit: psa_mac_abort(operation); } - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -2648,7 +2648,7 @@ exit: psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length); - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -2792,7 +2792,7 @@ exit: psa_wipe_tag_output_buffer(signature, status, signature_size, *signature_length); - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -2840,7 +2840,7 @@ static psa_status_t psa_verify_internal(mbedtls_svc_key_id_t key, signature, signature_length); } - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); return (status == PSA_SUCCESS) ? unlock_status : status; @@ -3107,7 +3107,7 @@ psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key, alg, input, input_length, salt, salt_length, output, output_size, output_length); exit: - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -3159,7 +3159,7 @@ psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, output, output_size, output_length); exit: - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -3268,7 +3268,7 @@ exit: psa_sign_hash_abort_internal(operation); } - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); if (unlock_status != PSA_SUCCESS) { operation->error_occurred = 1; @@ -3413,7 +3413,7 @@ psa_status_t psa_verify_hash_start( psa_verify_hash_abort_internal(operation); } - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); if (unlock_status != PSA_SUCCESS) { operation->error_occurred = 1; @@ -3985,7 +3985,7 @@ exit: psa_cipher_abort(operation); } - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -4230,7 +4230,7 @@ psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key, output_size - default_iv_length, output_length); exit: - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); if (status == PSA_SUCCESS) { status = unlock_status; } @@ -4291,7 +4291,7 @@ psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, output, output_size, output_length); exit: - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); if (status == PSA_SUCCESS) { status = unlock_status; } @@ -4417,7 +4417,7 @@ psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key, } exit: - psa_unlock_key_slot(slot); + psa_unregister_read(slot); return status; } @@ -4472,7 +4472,7 @@ psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key, } exit: - psa_unlock_key_slot(slot); + psa_unregister_read(slot); return status; } @@ -4584,7 +4584,7 @@ static psa_status_t psa_aead_setup(psa_aead_operation_t *operation, operation->key_type = psa_get_key_type(&attributes); exit: - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); if (status == PSA_SUCCESS) { status = unlock_status; @@ -6907,7 +6907,7 @@ psa_status_t psa_key_derivation_input_key( slot->key.data, slot->key.bytes); - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -7064,7 +7064,7 @@ psa_status_t psa_key_derivation_key_agreement(psa_key_derivation_operation_t *op } } - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -7125,7 +7125,7 @@ exit: *output_length = output_size; } - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } @@ -7799,7 +7799,7 @@ exit: if (status != PSA_SUCCESS) { psa_pake_abort(operation); } - unlock_status = psa_unlock_key_slot(slot); + unlock_status = psa_unregister_read(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index 3d997a50c..3c16de334 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -516,7 +516,7 @@ psa_status_t psa_open_key(mbedtls_svc_key_id_t key, psa_key_handle_t *handle) *handle = key; - return psa_unlock_key_slot(slot); + return psa_unregister_read(slot); #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ (void) key; From 6cd2b8db960e30cdd858a695b8618731c3225cc0 Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Thu, 4 Jan 2024 12:10:18 +0000 Subject: [PATCH 12/20] Update psa_wipe_all_key_slots This will still wipe the slot regardless of state/readers. Signed-off-by: Ryan Everett --- library/psa_crypto_slot_management.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index 3c16de334..a8be912b7 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -143,7 +143,8 @@ void psa_wipe_all_key_slots(void) for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) { psa_key_slot_t *slot = &global_data.key_slots[slot_idx]; - slot->lock_count = 1; + slot->registered_readers = 1; + slot->state = PSA_SLOT_PENDING_DELETION; (void) psa_wipe_key_slot(slot); } global_data.key_slots_initialized = 0; From 6a9c14b918da52d614fcff92df382b03aa366ff9 Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Thu, 4 Jan 2024 12:13:45 +0000 Subject: [PATCH 13/20] Update mbedtls_psa_get_stats Uses readers to report "locked_slots", and slot state empty to report "empty_slots". Signed-off-by: Ryan Everett --- library/psa_crypto_slot_management.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index a8be912b7..ef76dcb89 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -579,10 +579,10 @@ void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats) for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) { const psa_key_slot_t *slot = &global_data.key_slots[slot_idx]; - if (psa_is_key_slot_locked(slot)) { + if (psa_key_slot_has_readers(slot)) { ++stats->locked_slots; } - if (!psa_is_key_slot_occupied(slot)) { + if (slot->state == PSA_SLOT_EMPTY) { ++stats->empty_slots; continue; } From 4755e6bda47e8722ade10b0a86d1e94e89c312f1 Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Fri, 12 Jan 2024 16:35:59 +0000 Subject: [PATCH 14/20] Relax psa_wipe_key_slot to allow states other than SLOT_PENDING_DELETION psa_wipe_key_slot can now be called on a slot in any state, if the slot's state is PSA_SLOT_FULL or PSA_SLOT_PENDING_DELETION then there must be exactly 1 registered reader. Remove the state changing calls that are no longer necessary. Signed-off-by: Ryan Everett --- library/psa_crypto.c | 14 +++----------- library/psa_crypto_core.h | 7 ++----- library/psa_crypto_slot_management.c | 25 ++++++------------------- library/psa_crypto_slot_management.h | 2 +- 4 files changed, 12 insertions(+), 36 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index da5e5be77..1f6450025 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -983,10 +983,6 @@ psa_status_t psa_remove_key_data_from_memory(psa_key_slot_t *slot) * Persistent storage is not affected. */ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot) { - if (slot->state != PSA_SLOT_PENDING_DELETION) { - return PSA_ERROR_BAD_STATE; - } - psa_status_t status = psa_remove_key_data_from_memory(slot); /* @@ -998,7 +994,9 @@ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot) * function is called as part of the execution of a test suite, the * execution of the test suite is stopped in error if the assertion fails. */ - if (slot->registered_readers != 1) { + if (((slot->state == PSA_SLOT_FULL) || + (slot->state == PSA_SLOT_PENDING_DELETION)) && + (slot->registered_readers != 1)) { MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->registered_readers == 1); status = PSA_ERROR_CORRUPTION_DETECTED; } @@ -1828,12 +1826,6 @@ static void psa_fail_key_creation(psa_key_slot_t *slot, * itself. */ (void) psa_crypto_stop_transaction(); #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - - /* Prepare the key slot to be wiped, and then wipe it. */ - slot->registered_readers = 1; - psa_key_slot_state_transition(slot, PSA_SLOT_FILLING, - PSA_SLOT_PENDING_DELETION); - psa_wipe_key_slot(slot); } diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index 3b5c63497..f11df9f36 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -70,8 +70,6 @@ typedef struct { * Number of functions registered as reading the material in the key slot. * * Library functions must not write directly to registered_readers - * (unless the slot's state is PSA_SLOT_FILLING and the slot needs to be - * wiped following a failed key creation). * * A function must call psa_register_read(slot) before reading the current * contents of the slot for an operation. @@ -191,9 +189,8 @@ static inline psa_key_slot_number_t psa_key_slot_get_slot_number( * \retval #PSA_SUCCESS * The slot has been successfully wiped. * \retval #PSA_ERROR_CORRUPTION_DETECTED - * The amount of registered readers was not equal to 1. - * \retval #PSA_ERROR_BAD_STATE - * The slot's state was not PSA_SLOT_PENDING_DELETION. + * The slot's state was PSA_SLOT_FULL or PSA_SLOT_PENDING_DELETION, and + * the amount of registered readers was not equal to 1. */ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot); diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index ef76dcb89..e7ea8efb4 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -189,10 +189,6 @@ psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id, (unused_persistent_key_slot != NULL)) { selected_slot = unused_persistent_key_slot; psa_register_read(selected_slot); - /* If the state is not changed then psa_wipe_key_slot - * will report an error. */ - psa_key_slot_state_transition(selected_slot, PSA_SLOT_FULL, - PSA_SLOT_PENDING_DELETION); status = psa_wipe_key_slot(selected_slot); if (status != PSA_SUCCESS) { goto error; @@ -394,12 +390,6 @@ psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key, #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ if (status != PSA_SUCCESS) { - /* Prepare the key slot to be wiped, and then wipe it. - * Don't overwrite status as a BAD_STATE error here - * can be reported in the psa_wipe_key_slot call. */ - (*p_slot)->registered_readers = 1; - psa_key_slot_state_transition((*p_slot), PSA_SLOT_FILLING, - PSA_SLOT_PENDING_DELETION); psa_wipe_key_slot(*p_slot); if (status == PSA_ERROR_DOES_NOT_EXIST) { @@ -544,13 +534,10 @@ psa_status_t psa_close_key(psa_key_handle_t handle) return status; } if (slot->registered_readers == 1) { - status = psa_key_slot_state_transition(slot, PSA_SLOT_FULL, - PSA_SLOT_PENDING_DELETION); - if (status != PSA_SUCCESS) { - return status; - } + return psa_wipe_key_slot(slot); + } else { + return psa_unregister_read(slot); } - return psa_unregister_read(slot); } psa_status_t psa_purge_key(mbedtls_svc_key_id_t key) @@ -565,10 +552,10 @@ psa_status_t psa_purge_key(mbedtls_svc_key_id_t key) if ((!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) && (slot->registered_readers == 1)) { - psa_key_slot_state_transition(slot, PSA_SLOT_FULL, - PSA_SLOT_PENDING_DELETION); + return psa_wipe_key_slot(slot); + } else { + return psa_unregister_read(slot); } - return psa_unregister_read(slot); } void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats) diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h index 5858b1851..9b8e89132 100644 --- a/library/psa_crypto_slot_management.h +++ b/library/psa_crypto_slot_management.h @@ -179,7 +179,7 @@ static inline psa_status_t psa_register_read(psa_key_slot_t *slot) * This function decrements the key slot registered reader counter by one. * If the state of the slot is PSA_SLOT_PENDING_DELETION, * and there is only one registered reader (the caller), - * this function will call psa_wipe_slot(). + * this function will call psa_wipe_key_slot(). * * \note To ease the handling of errors in retrieving a key slot * a NULL input pointer is valid, and the function returns From dfe8bf86a8957cf93795584cba2eb5603d40f84c Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Fri, 12 Jan 2024 17:45:05 +0000 Subject: [PATCH 15/20] Return CORRUPTION_DETECTED instead of BAD_SLOT when the slot's state is wrong These error codes are only returned if the program has been tampered with, so they should be CORRUPTION_DETECTED. Signed-off-by: Ryan Everett --- include/psa/crypto.h | 8 ++------ include/psa/crypto_compat.h | 4 +--- library/psa_crypto.c | 1 - library/psa_crypto_core.h | 2 +- library/psa_crypto_slot_management.c | 2 +- library/psa_crypto_slot_management.h | 29 ++++++++++++---------------- 6 files changed, 17 insertions(+), 29 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index fd1928a65..fe10ee0e4 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -415,9 +415,7 @@ void psa_reset_key_attributes(psa_key_attributes_t *attributes); * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize - * results in this error code. Or, - * this call was operating on a key slot and found the slot in - * an invalid state for the operation. + * results in this error code. */ psa_status_t psa_purge_key(mbedtls_svc_key_id_t key); @@ -557,9 +555,7 @@ psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key, * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize - * results in this error code. Or, - * this call was operating on a key slot and found the slot in - * an invalid state for the operation. + * results in this error code. */ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key); diff --git a/include/psa/crypto_compat.h b/include/psa/crypto_compat.h index bfc00164b..f896fae1c 100644 --- a/include/psa/crypto_compat.h +++ b/include/psa/crypto_compat.h @@ -142,9 +142,7 @@ psa_status_t psa_open_key(mbedtls_svc_key_id_t key, * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize - * results in this error code. Or, - * this call was operating on a key slot and found the slot in - * an invalid state for the operation. + * results in this error code. */ psa_status_t psa_close_key(psa_key_handle_t handle); diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 1f6450025..2a8183e04 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1718,7 +1718,6 @@ static psa_status_t psa_start_key_creation( * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription - * \retval #PSA_ERROR_BAD_STATE \emptydescription * * \return If this function fails, the key slot is an invalid state. * You must call psa_fail_key_creation() to wipe and free the slot. diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index f11df9f36..376337e16 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -56,7 +56,7 @@ typedef struct { * The state variable is used to help determine whether library functions * which operate on the slot succeed. For example, psa_finish_key_creation, * which transfers the state of a slot from PSA_SLOT_FILLING to - * PSA_SLOT_FULL, must fail with error code PSA_ERROR_BAD_STATE + * PSA_SLOT_FULL, must fail with error code PSA_ERROR_CORRUPTION_DETECTED * if the state of the slot is not PSA_SLOT_FILLING. * * Library functions which traverse the array of key slots only consider diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index e7ea8efb4..3accacff0 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -417,7 +417,7 @@ psa_status_t psa_unregister_read(psa_key_slot_t *slot) } if ((slot->state != PSA_SLOT_FULL) && (slot->state != PSA_SLOT_PENDING_DELETION)) { - return PSA_ERROR_BAD_STATE; + return PSA_ERROR_CORRUPTION_DETECTED; } /* If we are the last reader and the slot is marked for deletion, diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h index 9b8e89132..0b0d7b320 100644 --- a/library/psa_crypto_slot_management.h +++ b/library/psa_crypto_slot_management.h @@ -68,9 +68,7 @@ static inline int psa_key_id_is_volatile(psa_key_id_t key_id) * description of the key identified by \p key. * The key slot counter has been incremented. * \retval #PSA_ERROR_BAD_STATE - * The library has not been initialized. Or, - * this call was operating on a key slot and found the slot in - * an invalid state for the operation. + * The library has not been initialized. * \retval #PSA_ERROR_INVALID_HANDLE * \p key is not a valid key identifier. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY @@ -114,7 +112,8 @@ void psa_wipe_all_key_slots(void); * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * There were no free key slots. - * \retval #PSA_ERROR_BAD_STATE + * \retval #PSA_ERROR_BAD_STATE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED * This function attempted to operate on a key slot which was in an * unexpected state. */ @@ -133,7 +132,7 @@ psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id, * * \retval #PSA_SUCCESS The key slot's state variable is new_state. - * \retval #PSA_ERROR_BAD_STATE + * \retval #PSA_ERROR_CORRUPTION_DETECTED * The slot's state was not expected_state. */ static inline psa_status_t psa_key_slot_state_transition( @@ -141,7 +140,7 @@ static inline psa_status_t psa_key_slot_state_transition( psa_key_slot_state_t new_state) { if (slot->state != expected_state) { - return PSA_ERROR_BAD_STATE; + return PSA_ERROR_CORRUPTION_DETECTED; } slot->state = new_state; return PSA_SUCCESS; @@ -157,16 +156,12 @@ static inline psa_status_t psa_key_slot_state_transition( The key slot registered reader counter was incremented. * \retval #PSA_ERROR_CORRUPTION_DETECTED * The reader counter already reached its maximum value and was not - * increased. - * \retval #PSA_ERROR_BAD_STATE - * The slot's state was not PSA_SLOT_FULL. + * increased, or the slot's state was not PSA_SLOT_FULL. */ static inline psa_status_t psa_register_read(psa_key_slot_t *slot) { - if (slot->state != PSA_SLOT_FULL) { - return PSA_ERROR_BAD_STATE; - } - if (slot->registered_readers >= SIZE_MAX) { + if ((slot->state != PSA_SLOT_FULL) || + (slot->registered_readers >= SIZE_MAX)) { return PSA_ERROR_CORRUPTION_DETECTED; } slot->registered_readers++; @@ -190,11 +185,11 @@ static inline psa_status_t psa_register_read(psa_key_slot_t *slot) * \p slot is NULL or the key slot reader counter has been * decremented (and potentially wiped) successfully. * \retval #PSA_ERROR_CORRUPTION_DETECTED - * registered_readers was equal to 0. - * \retval #PSA_ERROR_BAD_STATE * The slot's state was neither PSA_SLOT_FULL nor - * PSA_SLOT_PENDING_DELETION, or a wipe was attempted and - * the slot's state was not PSA_SLOT_PENDING_DELETION. + * PSA_SLOT_PENDING_DELETION. + * Or a wipe was attempted and the slot's state was not + * PSA_SLOT_PENDING_DELETION. + * Or registered_readers was equal to 0. */ psa_status_t psa_unregister_read(psa_key_slot_t *slot); From 709120a9ceb73dd02578d487caebee0a51491767 Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Mon, 15 Jan 2024 11:19:03 +0000 Subject: [PATCH 16/20] Revert change to return behaviour in psa_reserve_free_key_slot This change was a mistake, we still need to wipe the pointers here. Signed-off-by: Ryan Everett --- library/psa_crypto_slot_management.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index 3accacff0..8d7ff908e 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -199,7 +199,7 @@ psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id, status = psa_key_slot_state_transition(selected_slot, PSA_SLOT_EMPTY, PSA_SLOT_FILLING); if (status != PSA_SUCCESS) { - return status; + goto error; } *volatile_key_id = PSA_KEY_ID_VOLATILE_MIN + From 1d32a577645cc188793ffd1401d84a05fa39e0ca Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Mon, 15 Jan 2024 11:27:58 +0000 Subject: [PATCH 17/20] Revert change to psa_destroy_key documentation Signed-off-by: Ryan Everett --- library/psa_crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 2a8183e04..d15ace559 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1126,7 +1126,7 @@ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key) exit: status = psa_wipe_key_slot(slot); - /* Prioritize an error from wiping over a storage error */ + /* Prioritize CORRUPTION_DETECTED from wiping over a storage error */ if (status != PSA_SUCCESS) { overall_status = status; } From 7ed542e0f1aea1673f2b8bb3079c294e04777558 Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Wed, 17 Jan 2024 11:39:09 +0000 Subject: [PATCH 18/20] Implement delayed deletion in psa_destroy_key and some cleanup Signed-off-by: Ryan Everett --- library/psa_crypto.c | 80 +++++++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 27 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index d15ace559..565b5e14c 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -987,18 +987,41 @@ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot) /* * As the return error code may not be handled in case of multiple errors, - * do our best to report an unexpected amount of registered readers. - * Assert with MBEDTLS_TEST_HOOK_TEST_ASSERT that registered_readers is - * equal to one: + * do our best to report an unexpected amount of registered readers or + * an unexpected state. + * Assert with MBEDTLS_TEST_HOOK_TEST_ASSERT that the slot is valid for + * wiping. * if the MBEDTLS_TEST_HOOKS configuration option is enabled and the * function is called as part of the execution of a test suite, the * execution of the test suite is stopped in error if the assertion fails. */ - if (((slot->state == PSA_SLOT_FULL) || - (slot->state == PSA_SLOT_PENDING_DELETION)) && - (slot->registered_readers != 1)) { - MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->registered_readers == 1); - status = PSA_ERROR_CORRUPTION_DETECTED; + switch (slot->state) { + case PSA_SLOT_FULL: + /* In this state psa_wipe_key_slot() must only be called if the + * caller is the last reader. */ + case PSA_SLOT_PENDING_DELETION: + /* In this state psa_wipe_key_slot() must only be called if the + * caller is the last reader. */ + if (slot->registered_readers != 1) { + MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->registered_readers == 1); + status = PSA_ERROR_CORRUPTION_DETECTED; + } + break; + case PSA_SLOT_FILLING: + /* In this state registered_readers must be 0. */ + if (slot->registered_readers != 0) { + MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->registered_readers == 0); + status = PSA_ERROR_CORRUPTION_DETECTED; + } + break; + case PSA_SLOT_EMPTY: + /* The slot is already empty, it cannot be wiped. */ + MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->state != PSA_SLOT_EMPTY); + status = PSA_ERROR_CORRUPTION_DETECTED; + break; + default: + /* The slot's state is invalid. */ + status = PSA_ERROR_CORRUPTION_DETECTED; } /* Multipart operations may still be using the key. This is safe @@ -1028,29 +1051,25 @@ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key) } /* - * Get the description of the key in a key slot. In case of a persistent - * key, this will load the key description from persistent memory if not - * done yet. We cannot avoid this loading as without it we don't know if + * Get the description of the key in a key slot, and register to read it. + * In the case of a persistent key, this will load the key description + * from persistent memory if not done yet. + * We cannot avoid this loading as without it we don't know if * the key is operated by an SE or not and this information is needed by - * the current implementation. - */ + * the current implementation. */ status = psa_get_and_lock_key_slot(key, &slot); if (status != PSA_SUCCESS) { return status; } - /* - * If the key slot containing the key description is under access by the - * library (apart from the present access), the key cannot be destroyed - * yet. For the time being, just return in error. Eventually (to be - * implemented), the key should be destroyed when all accesses have - * stopped. - */ - if (slot->registered_readers > 1) { - psa_unregister_read(slot); - return PSA_ERROR_GENERIC_ERROR; - } - + /* Set the key slot containing the key description's state to + * PENDING_DELETION. This stops new operations from registering + * to read the slot. Current readers can safely continue to access + * the key within the slot; the last registered reader will + * automatically wipe the slot when they call psa_unregister_read(). + * If the key is persistent, we can now delete the copy of the key + * from memory. If the key is opaque, we require the driver to + * deal with the deletion. */ slot->state = PSA_SLOT_PENDING_DELETION; if (PSA_KEY_LIFETIME_IS_READ_ONLY(slot->attr.lifetime)) { @@ -1099,6 +1118,9 @@ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key) #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) { + /* Destroy the copy of the persistent key from memory. + * The slot will still hold a copy of the key until the last reader + * unregisters. */ status = psa_destroy_persistent_key(slot->attr.id); if (overall_status == PSA_SUCCESS) { overall_status = status; @@ -1125,8 +1147,11 @@ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key) #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ exit: - status = psa_wipe_key_slot(slot); - /* Prioritize CORRUPTION_DETECTED from wiping over a storage error */ + /* Unregister from reading the slot. If we are the last active reader + * then this will wipe the slot. */ + status = psa_unregister_read(slot); + /* Prioritize CORRUPTION_DETECTED from unregistering over + * a storage error. */ if (status != PSA_SUCCESS) { overall_status = status; } @@ -1825,6 +1850,7 @@ static void psa_fail_key_creation(psa_key_slot_t *slot, * itself. */ (void) psa_crypto_stop_transaction(); #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + psa_wipe_key_slot(slot); } From 38a2b7a6a3215b2d062da23b9945bbecd889e277 Mon Sep 17 00:00:00 2001 From: Ryan Everett Date: Wed, 17 Jan 2024 11:45:44 +0000 Subject: [PATCH 19/20] Extend psa_wipe_key_slot documentation Signed-off-by: Ryan Everett --- library/psa_crypto_core.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index 376337e16..b5b9c5451 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -190,7 +190,10 @@ static inline psa_key_slot_number_t psa_key_slot_get_slot_number( * The slot has been successfully wiped. * \retval #PSA_ERROR_CORRUPTION_DETECTED * The slot's state was PSA_SLOT_FULL or PSA_SLOT_PENDING_DELETION, and - * the amount of registered readers was not equal to 1. + * the amount of registered readers was not equal to 1. Or, + * the slot's state was PSA_SLOT_EMPTY. Or, + * the slot's state was PSA_SLOT_FILLING, and the amount + * of registered readers was not equal to 0. */ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot); From 4a0ba80bdbf9b2ef1f44071cdabc733962870d69 Mon Sep 17 00:00:00 2001 From: Ryan Everett <144035422+Ryan-Everett-arm@users.noreply.github.com> Date: Wed, 17 Jan 2024 14:12:33 +0000 Subject: [PATCH 20/20] Clarify psa_destroy_key documentation Co-authored-by: Janos Follath Signed-off-by: Ryan Everett <144035422+Ryan-Everett-arm@users.noreply.github.com> --- library/psa_crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 565b5e14c..56265c197 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1118,7 +1118,7 @@ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key) #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) { - /* Destroy the copy of the persistent key from memory. + /* Destroy the copy of the persistent key from storage. * The slot will still hold a copy of the key until the last reader * unregisters. */ status = psa_destroy_persistent_key(slot->attr.id);