From 3cac8c4d7839c11b5742ecb282f20aa19c2eab19 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 30 Nov 2018 14:07:45 +0100 Subject: [PATCH 01/35] Move declarations related to lifetimes further up in crypto.h No content change. This is in preparation for declaring the slot management functions, which need the type psa_key_lifetime_t. --- include/psa/crypto.h | 180 ++++++++++++++++++++++--------------------- 1 file changed, 92 insertions(+), 88 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 1ca64922e..282f90965 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -1401,6 +1401,98 @@ typedef uint32_t psa_algorithm_t; * @{ */ +/** Encoding of key lifetimes. + */ +typedef uint32_t psa_key_lifetime_t; + +/** Encoding of identifiers of persistent keys. + */ +typedef uint32_t psa_key_id_t; + +/** A volatile key slot retains its content as long as the application is + * running. It is guaranteed to be erased on a power reset. + */ +#define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t)0x00000000) + +/** A persistent key slot retains its content as long as it is not explicitly + * destroyed. + */ +#define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001) + +/** A write-once key slot may not be modified once a key has been set. + * It will retain its content as long as the device remains operational. + */ +#define PSA_KEY_LIFETIME_WRITE_ONCE ((psa_key_lifetime_t)0x7fffffff) + +/** \brief Retrieve the lifetime of a key slot. + * + * The assignment of lifetimes to slots is implementation-dependent. + * + * \param key Slot to query. + * \param[out] lifetime On success, the lifetime value. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key slot is invalid. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + * \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. + */ +psa_status_t psa_get_key_lifetime(psa_key_slot_t key, + psa_key_lifetime_t *lifetime); + +/** \brief Change the lifetime of a key slot. + * + * Whether the lifetime of a key slot can be changed at all, and if so + * whether the lifetime of an occupied key slot can be changed, is + * implementation-dependent. + * + * When creating a persistent key, you must call this function before creating + * the key material with psa_import_key(), psa_generate_key() or + * psa_generator_import_key(). To open an existing persistent key, you must + * call this function with the correct lifetime value before using the slot + * for a cryptographic operation. Once a slot's lifetime has been set, + * the lifetime remains associated with the slot until a subsequent call to + * psa_set_key_lifetime(), until the key is wiped with psa_destroy_key or + * until the application terminates (or disconnects from the cryptography + * service, if the implementation offers such a possibility). + * + * \param key Slot whose lifetime is to be changed. + * \param lifetime The lifetime value to set for the given key slot. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key slot is invalid, + * or the lifetime value is invalid. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The implementation does not support the specified lifetime value, + * at least for the specified key slot. + * \retval #PSA_ERROR_OCCUPIED_SLOT + * The slot contains a key, and the implementation does not support + * changing the lifetime of an occupied slot. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + * \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. + */ +psa_status_t psa_set_key_lifetime(psa_key_slot_t key, + psa_key_lifetime_t lifetime); + +/**@}*/ + +/** \defgroup import_export Key import and export + * @{ + */ + /** * \brief Import a key in binary format. * @@ -1872,94 +1964,6 @@ psa_status_t psa_get_key_policy(psa_key_slot_t key, /**@}*/ -/** \defgroup persistence Key lifetime - * @{ - */ - -/** Encoding of key lifetimes. - */ -typedef uint32_t psa_key_lifetime_t; - -/** A volatile key slot retains its content as long as the application is - * running. It is guaranteed to be erased on a power reset. - */ -#define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t)0x00000000) - -/** A persistent key slot retains its content as long as it is not explicitly - * destroyed. - */ -#define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001) - -/** A write-once key slot may not be modified once a key has been set. - * It will retain its content as long as the device remains operational. - */ -#define PSA_KEY_LIFETIME_WRITE_ONCE ((psa_key_lifetime_t)0x7fffffff) - -/** \brief Retrieve the lifetime of a key slot. - * - * The assignment of lifetimes to slots is implementation-dependent. - * - * \param key Slot to query. - * \param[out] lifetime On success, the lifetime value. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key slot is invalid. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED - * \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. - */ -psa_status_t psa_get_key_lifetime(psa_key_slot_t key, - psa_key_lifetime_t *lifetime); - -/** \brief Change the lifetime of a key slot. - * - * Whether the lifetime of a key slot can be changed at all, and if so - * whether the lifetime of an occupied key slot can be changed, is - * implementation-dependent. - * - * When creating a persistent key, you must call this function before creating - * the key material with psa_import_key(), psa_generate_key() or - * psa_generator_import_key(). To open an existing persistent key, you must - * call this function with the correct lifetime value before using the slot - * for a cryptographic operation. Once a slot's lifetime has been set, - * the lifetime remains associated with the slot until a subsequent call to - * psa_set_key_lifetime(), until the key is wiped with psa_destroy_key or - * until the application terminates (or disconnects from the cryptography - * service, if the implementation offers such a possibility). - * - * \param key Slot whose lifetime is to be changed. - * \param lifetime The lifetime value to set for the given key slot. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key slot is invalid, - * or the lifetime value is invalid. - * \retval #PSA_ERROR_NOT_SUPPORTED - * The implementation does not support the specified lifetime value, - * at least for the specified key slot. - * \retval #PSA_ERROR_OCCUPIED_SLOT - * The slot contains a key, and the implementation does not support - * changing the lifetime of an occupied slot. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED - * \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. - */ -psa_status_t psa_set_key_lifetime(psa_key_slot_t key, - psa_key_lifetime_t lifetime); - -/**@}*/ - /** \defgroup hash Message digests * @{ */ From f535eb2e616593807cf879914ba926a97cbe92cb Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 30 Nov 2018 14:08:36 +0100 Subject: [PATCH 02/35] Declare the new slot management functions in crypto.h No changes to existing functions. --- include/psa/crypto.h | 125 ++++++++++++++++++++++++++++++++++ include/psa/crypto_platform.h | 3 + 2 files changed, 128 insertions(+) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 282f90965..432ce6a8e 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -314,6 +314,10 @@ typedef int32_t psa_status_t; * generator will always return this error. */ #define PSA_ERROR_INSUFFICIENT_CAPACITY ((psa_status_t)18) +/** The key handle is not valid. + */ +#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)19) + /** * \brief Library initialization. * @@ -1487,6 +1491,127 @@ psa_status_t psa_get_key_lifetime(psa_key_slot_t key, psa_status_t psa_set_key_lifetime(psa_key_slot_t key, psa_key_lifetime_t lifetime); +/** Allocate a key slot for a transient key, i.e. a key which is only stored + * in volatile memory. + * + * The allocated key slot and its handle remain valid until the + * application calls psa_close_key() or psa_destroy_key() or until the + * application terminates. + * + * This function takes a key type and maximum size as arguments so that + * the implementation can reserve a corresponding amount of memory. + * Implementations are not required to enforce this limit: if the application + * later tries to create a larger key or a key of a different type, it + * is implementation-defined whether this may succeed. + * + * \param type The type of key that the slot will contain. + * \param max_bits The maximum key size that the slot will contain. + * \param[out] handle On success, a handle to a volatile key slot. + * + * \retval #PSA_SUCCESS + * Success. The application can now use the value of `*handle` + * to access the newly allocated key slot. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * There was not enough memory, or the maximum number of key slots + * has been reached. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * This implementation does not support this key type. + */ + +psa_status_t psa_allocate_key(psa_key_type_t type, + size_t max_bits, + psa_key_handle_t *handle); + +/** Open a handle to an existing persistent key. + * + * Open a handle to a key which was previously created with psa_create_key(). + * + * \param lifetime The lifetime of the key. This designates a storage + * area where the key material is stored. This must not + * be #PSA_KEY_LIFETIME_VOLATILE. + * \param id The persistent identifier of the key. + * \param[out] handle On success, a handle to a key slot which contains + * the data and metadata loaded from the specified + * persistent location. + * + * \retval #PSA_SUCCESS + * Success. The application can now use the value of `*handle` + * to access the newly allocated key slot. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_EMPTY_SLOT + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p lifetime is invalid, for example #PSA_KEY_LIFETIME_VOLATILE. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p id is invalid for the specified lifetime. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p lifetime is not supported. + * \retval #PSA_ERROR_NOT_PERMITTED + * The specified key exists, but the application does not have the + * permission to access it. Note that this specification does not + * define any way to create such a key, but it may be possible + * through implementation-specific means. + */ +psa_status_t psa_open_key(psa_key_lifetime_t lifetime, + psa_key_id_t id, + psa_key_handle_t *handle); + +/** Create a new persistent key slot. + * + * Create a new persistent key slot and return a handle to it. The handle + * remains valid until the application calls psa_close_key() or terminates. + * The application can open the key again with psa_open_key() until it + * removes the key by calling psa_destroy_key(). + * + * \param lifetime The lifetime of the key. This designates a storage + * area where the key material is stored. This must not + * be #PSA_KEY_LIFETIME_VOLATILE. + * \param id The persistent identifier of the key. + * \param type The type of key that the slot will contain. + * \param max_bits The maximum key size that the slot will contain. + * \param[out] handle On success, a handle to the newly created key slot. + * When key material is later created in this key slot, + * it will be saved to the specified persistent location. + * + * \retval #PSA_SUCCESS + * Success. The application can now use the value of `*handle` + * to access the newly allocated key slot. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_OCCUPIED_SLOT + * There is already a key with the identifier \p id in the storage + * area designated by \p lifetime. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p lifetime is invalid, for example #PSA_KEY_LIFETIME_VOLATILE. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p id is invalid for the specified lifetime. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p lifetime is not supported. + * \retval #PSA_ERROR_NOT_PERMITTED + * \p lifetime is valid, but the application does not have the + * permission to create a key there. + */ +psa_status_t psa_create_key(psa_key_lifetime_t lifetime, + psa_key_id_t id, + psa_key_type_t type, + size_t max_bits, + psa_key_handle_t *handle); + +/** Close a key handle. + * + * If the handle designates a volatile key, destroy the key material and + * free all associated resources, just like psa_destroy_key(). + * + * If the handle designates a persistent key, free all resources associated + * with the key in volatile memory. The key slot in persistent storage is + * not affected and can be opened again later with psa_open_key(). + * + * \param handle The key handle to close. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + */ +psa_status_t psa_close_key(psa_key_handle_t handle); + /**@}*/ /** \defgroup import_export Key import and export diff --git a/include/psa/crypto_platform.h b/include/psa/crypto_platform.h index 9af320d1e..c20396619 100644 --- a/include/psa/crypto_platform.h +++ b/include/psa/crypto_platform.h @@ -49,4 +49,7 @@ /* Integral type representing a key slot number. */ typedef uint16_t psa_key_slot_t; +/* Integral type representing a key handle. */ +typedef uint16_t psa_key_handle_t; + #endif /* PSA_CRYPTO_PLATFORM_H */ From 644cd5fd8977ed0a0eaa8dbd1cc6f66dc4865446 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 11 Dec 2018 16:47:35 +0100 Subject: [PATCH 03/35] Linkify some macros that were just typeset as text --- include/psa/crypto.h | 52 ++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 432ce6a8e..0e57972cc 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -3266,9 +3266,9 @@ static psa_crypto_generator_t psa_crypto_generator_init(void); * \param[in] generator The generator to query. * \param[out] capacity On success, the capacity of the generator. * - * \retval PSA_SUCCESS - * \retval PSA_ERROR_BAD_STATE - * \retval PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BAD_STATE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE */ psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator, size_t *capacity); @@ -3284,19 +3284,19 @@ psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator, * written. * \param output_length Number of bytes to output. * - * \retval PSA_SUCCESS - * \retval PSA_ERROR_INSUFFICIENT_CAPACITY + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_CAPACITY * There were fewer than \p output_length bytes * in the generator. Note that in this case, no * output is written to the output buffer. * The generator's capacity is set to 0, thus * subsequent calls to this function will not * succeed, even with a smaller output buffer. - * \retval PSA_ERROR_BAD_STATE - * \retval PSA_ERROR_INSUFFICIENT_MEMORY - * \retval PSA_ERROR_COMMUNICATION_FAILURE - * \retval PSA_ERROR_HARDWARE_FAILURE - * \retval PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED */ psa_status_t psa_generator_read(psa_crypto_generator_t *generator, uint8_t *output, @@ -3322,28 +3322,28 @@ psa_status_t psa_generator_read(psa_crypto_generator_t *generator, * \param bits Key size in bits. * \param[in,out] generator The generator object to read from. * - * \retval PSA_SUCCESS + * \retval #PSA_SUCCESS * Success. - * \retval PSA_ERROR_INSUFFICIENT_CAPACITY + * \retval #PSA_ERROR_INSUFFICIENT_CAPACITY * There were fewer than \p output_length bytes * in the generator. Note that in this case, no * output is written to the output buffer. * The generator's capacity is set to 0, thus * subsequent calls to this function will not * succeed, even with a smaller output buffer. - * \retval PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_NOT_SUPPORTED * The key type or key size is not supported, either by the * implementation in general or in this particular slot. - * \retval PSA_ERROR_BAD_STATE - * \retval PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_BAD_STATE + * \retval #PSA_ERROR_INVALID_ARGUMENT * The key slot is invalid. - * \retval PSA_ERROR_OCCUPIED_SLOT + * \retval #PSA_ERROR_OCCUPIED_SLOT * There is already a key in the specified slot. - * \retval PSA_ERROR_INSUFFICIENT_MEMORY - * \retval PSA_ERROR_INSUFFICIENT_STORAGE - * \retval PSA_ERROR_COMMUNICATION_FAILURE - * \retval PSA_ERROR_HARDWARE_FAILURE - * \retval PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED * \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 @@ -3370,11 +3370,11 @@ psa_status_t psa_generator_import_key(psa_key_slot_t key, * * \param[in,out] generator The generator to abort. * - * \retval PSA_SUCCESS - * \retval PSA_ERROR_BAD_STATE - * \retval PSA_ERROR_COMMUNICATION_FAILURE - * \retval PSA_ERROR_HARDWARE_FAILURE - * \retval PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BAD_STATE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED */ psa_status_t psa_generator_abort(psa_crypto_generator_t *generator); From ae32aac48e7181f1e2bddb5bac77d6270a56a825 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 30 Nov 2018 14:39:32 +0100 Subject: [PATCH 04/35] Switch function declarations from key slots to key handles Replace `psa_key_slot_t key` by `psa_key_handle_t` in function declarations. This is a transition period during which handles are key slot numbers and the whole library can still be used by accessing a key slot number without allocating a handle. --- include/psa/crypto.h | 173 ++++++++++++++++++++++++------------------- 1 file changed, 97 insertions(+), 76 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 0e57972cc..6807c73f3 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -36,19 +36,15 @@ * @{ */ -/** \brief Key slot number. +/** \brief Key handle. * - * This type represents key slots. It must be an unsigned integral + * This type represents open handles to keys. It must be an unsigned integral * type. The choice of type is implementation-dependent. + * * 0 is not a valid key slot number. The meaning of other values is * implementation dependent. - * - * At any given point in time, each key slot either contains a - * cryptographic object, or is empty. Key slots are persistent: - * once set, the cryptographic object remains in the key slot until - * explicitly destroyed. */ -typedef _unsigned_integral_type_ psa_key_slot_t; +typedef _unsigned_integral_type_ psa_key_handle_t; /**@}*/ #endif /* __DOXYGEN_ONLY__ */ @@ -1428,17 +1424,14 @@ typedef uint32_t psa_key_id_t; */ #define PSA_KEY_LIFETIME_WRITE_ONCE ((psa_key_lifetime_t)0x7fffffff) -/** \brief Retrieve the lifetime of a key slot. +/** \brief Retrieve the lifetime of an open key. * - * The assignment of lifetimes to slots is implementation-dependent. - * - * \param key Slot to query. + * \param handle Handle to query. * \param[out] lifetime On success, the lifetime value. * * \retval #PSA_SUCCESS * Success. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key slot is invalid. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE * \retval #PSA_ERROR_TAMPERING_DETECTED @@ -1447,7 +1440,7 @@ typedef uint32_t psa_key_id_t; * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_get_key_lifetime(psa_key_slot_t key, +psa_status_t psa_get_key_lifetime(psa_key_handle_t handle, psa_key_lifetime_t *lifetime); /** \brief Change the lifetime of a key slot. @@ -1488,7 +1481,7 @@ psa_status_t psa_get_key_lifetime(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_set_key_lifetime(psa_key_slot_t key, +psa_status_t psa_set_key_lifetime(psa_key_handle_t key, psa_key_lifetime_t lifetime); /** Allocate a key slot for a transient key, i.e. a key which is only stored @@ -1609,6 +1602,7 @@ psa_status_t psa_create_key(psa_key_lifetime_t lifetime, * * \retval #PSA_SUCCESS * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE */ psa_status_t psa_close_key(psa_key_handle_t handle); @@ -1633,9 +1627,12 @@ psa_status_t psa_close_key(psa_key_handle_t handle); * minimize the risk that an invalid input is accidentally interpreted * according to a different format. * - * \param key Slot where the key will be stored. This must be a - * valid slot for a key of the chosen type. It must - * be unoccupied. + * \param handle Handle to the slot where the key will be stored. + * This must be a valid slot for a key of the chosen + * type: it must have been obtained by calling + * psa_allocate_key() or psa_create_key() with the + * correct \p type and with a maximum size that is + * compatible with \p data. * \param type Key type (a \c PSA_KEY_TYPE_XXX value). On a successful * import, the key slot will contain a key of this type. * \param[in] data Buffer containing the key data. The content of this @@ -1647,6 +1644,7 @@ psa_status_t psa_close_key(psa_key_handle_t handle); * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_NOT_SUPPORTED * The key type or key size is not supported, either by the * implementation in general or in this particular slot. @@ -1666,31 +1664,30 @@ psa_status_t psa_close_key(psa_key_handle_t handle); * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_import_key(psa_key_slot_t key, +psa_status_t psa_import_key(psa_key_handle_t handle, psa_key_type_t type, const uint8_t *data, size_t data_length); /** - * \brief Destroy a key and restore the slot to its default state. + * \brief Destroy a key. * * This function destroys the content of the key slot from both volatile * memory and, if applicable, non-volatile storage. Implementations shall * make a best effort to ensure that any previous content of the slot is * unrecoverable. * - * This function also erases any metadata such as policies. It returns the - * specified slot to its default state. + * This function also erases any metadata such as policies and frees all + * resources associated with the key. * - * \param key The key slot to erase. + * \param handle Handle to the key slot to erase. * * \retval #PSA_SUCCESS * The slot's content, if any, has been erased. * \retval #PSA_ERROR_NOT_PERMITTED * The slot holds content and cannot be erased because it is * read-only, either due to a policy or due to physical restrictions. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The specified slot number does not designate a valid slot. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_COMMUNICATION_FAILURE * There was an failure in communication with the cryptoprocessor. * The key material may still be present in the cryptoprocessor. @@ -1708,13 +1705,12 @@ psa_status_t psa_import_key(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_destroy_key(psa_key_slot_t key); +psa_status_t psa_destroy_key(psa_key_handle_t handle); /** * \brief Get basic metadata about a key. * - * \param key Slot whose content is queried. This must - * be an occupied key slot. + * \param handle Handle to the key slot to query. * \param[out] type On success, the key type (a \c PSA_KEY_TYPE_XXX value). * This may be a null pointer, in which case the key type * is not written. @@ -1723,7 +1719,9 @@ psa_status_t psa_destroy_key(psa_key_slot_t key); * is not written. * * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT + * The handle is to a key slot which does not contain key material yet. * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE * \retval #PSA_ERROR_TAMPERING_DETECTED @@ -1732,7 +1730,7 @@ psa_status_t psa_destroy_key(psa_key_slot_t key); * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_get_key_information(psa_key_slot_t key, +psa_status_t psa_get_key_information(psa_key_handle_t handle, psa_key_type_t *type, size_t *bits); @@ -1798,14 +1796,14 @@ psa_status_t psa_get_key_information(psa_key_slot_t key, * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is * true), the format is the same as for psa_export_public_key(). * - * \param key Slot whose content is to be exported. This must - * be an occupied key slot. + * \param handle Handle to the key to export. * \param[out] data Buffer where the key data is to be written. * \param data_size Size of the \p data buffer in bytes. * \param[out] data_length On success, the number of bytes * that make up the key data. * * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_NOT_SUPPORTED @@ -1823,7 +1821,7 @@ psa_status_t psa_get_key_information(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_export_key(psa_key_slot_t key, +psa_status_t psa_export_key(psa_key_handle_t handle, uint8_t *data, size_t data_size, size_t *data_length); @@ -1900,14 +1898,14 @@ psa_status_t psa_export_key(psa_key_slot_t key, * namedCurve OBJECT IDENTIFIER } * ``` * - * \param key Slot whose content is to be exported. This must - * be an occupied key slot. + * \param handle Handle to the key to export. * \param[out] data Buffer where the key data is to be written. * \param data_size Size of the \p data buffer in bytes. * \param[out] data_length On success, the number of bytes * that make up the key data. * * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_INVALID_ARGUMENT * The key is neither a public key nor a key pair. @@ -1926,7 +1924,7 @@ psa_status_t psa_export_key(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_export_public_key(psa_key_slot_t key, +psa_status_t psa_export_public_key(psa_key_handle_t handle, uint8_t *data, size_t data_size, size_t *data_length); @@ -2052,10 +2050,11 @@ psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy); * Implementations may set restrictions on supported key policies * depending on the key type and the key slot. * - * \param key The key slot whose policy is to be changed. + * \param handle Handle to the key whose policy is to be changed. * \param[in] policy The policy object to query. * * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_OCCUPIED_SLOT * \retval #PSA_ERROR_NOT_SUPPORTED * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -2067,15 +2066,16 @@ psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy); * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_set_key_policy(psa_key_slot_t key, +psa_status_t psa_set_key_policy(psa_key_handle_t handle, const psa_key_policy_t *policy); /** \brief Get the usage policy for a key slot. * - * \param key The key slot whose policy is being queried. + * \param handle Handle to the key slot whose policy is being queried. * \param[out] policy On success, the key's policy. * * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE * \retval #PSA_ERROR_TAMPERING_DETECTED @@ -2084,7 +2084,7 @@ psa_status_t psa_set_key_policy(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_get_key_policy(psa_key_slot_t key, +psa_status_t psa_get_key_policy(psa_key_handle_t handle, psa_key_policy_t *policy); /**@}*/ @@ -2341,12 +2341,13 @@ typedef struct psa_mac_operation_s psa_mac_operation_t; * - A call to psa_mac_sign_finish() or psa_mac_abort(). * * \param[out] operation The operation object to use. - * \param key Slot containing the key to use for the operation. + * \param handle Handle to the key to use for the operation. * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(alg) is true). * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -2363,7 +2364,7 @@ typedef struct psa_mac_operation_s psa_mac_operation_t; * results in this error code. */ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg); /** Start a multipart MAC verification operation. @@ -2393,12 +2394,13 @@ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, * - A call to psa_mac_verify_finish() or psa_mac_abort(). * * \param[out] operation The operation object to use. - * \param key Slot containing the key to use for the operation. + * \param handle Handle to the key to use for the operation. * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(\p alg) is true). * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -2415,7 +2417,7 @@ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, * results in this error code. */ psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg); /** Add a message fragment to a multipart MAC operation. @@ -2592,13 +2594,14 @@ typedef struct psa_cipher_operation_s psa_cipher_operation_t; * - A call to psa_cipher_finish() or psa_cipher_abort(). * * \param[out] operation The operation object to use. - * \param key Slot containing the key to use for the operation. + * \param handle Handle to the key to use for the operation. * \param alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -2615,7 +2618,7 @@ typedef struct psa_cipher_operation_s psa_cipher_operation_t; * results in this error code. */ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg); /** Set the key for a multipart symmetric decryption operation. @@ -2645,13 +2648,14 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, * - A call to psa_cipher_finish() or psa_cipher_abort(). * * \param[out] operation The operation object to use. - * \param key Slot containing the key to use for the operation. + * \param handle Handle to the key to use for the operation. * \param alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -2668,7 +2672,7 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, * results in this error code. */ psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg); /** Generate an IV for a symmetric encryption operation. @@ -2871,7 +2875,7 @@ psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); /** Process an authenticated encryption operation. * - * \param key Slot containing the key to use. + * \param handle Handle to the key to use for the operation. * \param alg The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). @@ -2899,6 +2903,7 @@ psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -2914,7 +2919,7 @@ psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_aead_encrypt(psa_key_slot_t key, +psa_status_t psa_aead_encrypt(psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, @@ -2928,7 +2933,7 @@ psa_status_t psa_aead_encrypt(psa_key_slot_t key, /** Process an authenticated decryption operation. * - * \param key Slot containing the key to use. + * \param handle Handle to the key to use for the operation. * \param alg The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). @@ -2954,6 +2959,7 @@ psa_status_t psa_aead_encrypt(psa_key_slot_t key, * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_INVALID_SIGNATURE * The ciphertext is not authentic. @@ -2971,7 +2977,7 @@ psa_status_t psa_aead_encrypt(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_aead_decrypt(psa_key_slot_t key, +psa_status_t psa_aead_decrypt(psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, @@ -3009,7 +3015,8 @@ psa_status_t psa_aead_decrypt(psa_key_slot_t key, * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) * to determine the hash algorithm to use. * - * \param key Key slot containing an asymmetric key pair. + * \param handle Handle to the key to use for the operation. + * It must be an asymmetric key pair. * \param alg A signature algorithm that is compatible with * the type of \p key. * \param[in] hash The hash or message to sign. @@ -3038,7 +3045,7 @@ psa_status_t psa_aead_decrypt(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_asymmetric_sign(psa_key_slot_t key, +psa_status_t psa_asymmetric_sign(psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, @@ -3055,8 +3062,8 @@ psa_status_t psa_asymmetric_sign(psa_key_slot_t key, * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) * to determine the hash algorithm to use. * - * \param key Key slot containing a public key or an - * asymmetric key pair. + * \param handle Handle to the key to use for the operation. + * It must be a public key or an asymmetric key pair. * \param alg A signature algorithm that is compatible with * the type of \p key. * \param[in] hash The hash or message whose signature is to be @@ -3081,7 +3088,7 @@ psa_status_t psa_asymmetric_sign(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_asymmetric_verify(psa_key_slot_t key, +psa_status_t psa_asymmetric_verify(psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, @@ -3096,8 +3103,9 @@ psa_status_t psa_asymmetric_verify(psa_key_slot_t key, /** * \brief Encrypt a short message with a public key. * - * \param key Key slot containing a public key or an - * asymmetric key pair. + * \param handle Handle to the key to use for the operation. + * It must be a public key or an asymmetric + * key pair. * \param alg An asymmetric encryption algorithm that is * compatible with the type of \p key. * \param[in] input The message to encrypt. @@ -3139,7 +3147,7 @@ psa_status_t psa_asymmetric_verify(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_asymmetric_encrypt(psa_key_slot_t key, +psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *input, size_t input_length, @@ -3152,7 +3160,8 @@ psa_status_t psa_asymmetric_encrypt(psa_key_slot_t key, /** * \brief Decrypt a short message with a private key. * - * \param key Key slot containing an asymmetric key pair. + * \param handle Handle to the key to use for the operation. + * It must be an asymmetric key pair. * \param alg An asymmetric encryption algorithm that is * compatible with the type of \p key. * \param[in] input The message to decrypt. @@ -3195,7 +3204,7 @@ psa_status_t psa_asymmetric_encrypt(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_asymmetric_decrypt(psa_key_slot_t key, +psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *input, size_t input_length, @@ -3314,9 +3323,13 @@ psa_status_t psa_generator_read(psa_crypto_generator_t *generator, * if the implementation provides an isolation boundary then * the key material is not exposed outside the isolation boundary. * - * \param key Slot where the key will be stored. This must be a - * valid slot for a key of the chosen type. It must - * be unoccupied. + * \param handle Handle to the slot where the key will be stored. + * This must be a valid slot for a key of the chosen + * type: it must have been obtained by calling + * psa_allocate_key() or psa_create_key() with the + * correct \p type and with a maximum size that is + * compatible with \p bits. + * It must not contain any key material yet. * \param type Key type (a \c PSA_KEY_TYPE_XXX value). * This must be a symmetric key type. * \param bits Key size in bits. @@ -3335,8 +3348,7 @@ psa_status_t psa_generator_read(psa_crypto_generator_t *generator, * The key type or key size is not supported, either by the * implementation in general or in this particular slot. * \retval #PSA_ERROR_BAD_STATE - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key slot is invalid. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_OCCUPIED_SLOT * There is already a key in the specified slot. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY @@ -3349,7 +3361,7 @@ psa_status_t psa_generator_read(psa_crypto_generator_t *generator, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_generator_import_key(psa_key_slot_t key, +psa_status_t psa_generator_import_key(psa_key_handle_t handle, psa_key_type_t type, size_t bits, psa_crypto_generator_t *generator); @@ -3409,7 +3421,7 @@ psa_status_t psa_generator_abort(psa_crypto_generator_t *generator); * a logical zero (`{0}`), * \c PSA_CRYPTO_GENERATOR_INIT or * psa_crypto_generator_init(). - * \param key Slot containing the secret key to use. + * \param handle Handle to the secret key. * \param alg The key derivation algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true). @@ -3422,6 +3434,7 @@ psa_status_t psa_generator_abort(psa_crypto_generator_t *generator); * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -3439,7 +3452,7 @@ psa_status_t psa_generator_abort(psa_crypto_generator_t *generator); * results in this error code. */ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *salt, size_t salt_length, @@ -3462,7 +3475,7 @@ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator, * a logical zero (`{0}`), * \c PSA_CRYPTO_GENERATOR_INIT or * psa_crypto_generator_init(). - * \param private_key Slot containing the private key to use. + * \param private_key Handle to the private key to use. * \param[in] peer_key Public key of the peer. It must be * in the same format that psa_import_key() * accepts. The standard formats for public @@ -3475,6 +3488,7 @@ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator, * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -3489,7 +3503,7 @@ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator, * \retval #PSA_ERROR_TAMPERING_DETECTED */ psa_status_t psa_key_agreement(psa_crypto_generator_t *generator, - psa_key_slot_t private_key, + psa_key_handle_t private_key, const uint8_t *peer_key, size_t peer_key_length, psa_algorithm_t alg); @@ -3538,9 +3552,13 @@ typedef struct { /** * \brief Generate a key or key pair. * - * \param key Slot where the key will be stored. This must be a - * valid slot for a key of the chosen type. It must - * be unoccupied. + * \param handle Handle to the slot where the key will be stored. + * This must be a valid slot for a key of the chosen + * type: it must have been obtained by calling + * psa_allocate_key() or psa_create_key() with the + * correct \p type and with a maximum size that is + * compatible with \p bits. + * It must not contain any key material yet. * \param type Key type (a \c PSA_KEY_TYPE_XXX value). * \param bits Key size in bits. * \param[in] extra Extra parameters for key generation. The @@ -3569,6 +3587,9 @@ typedef struct { * \c NULL then \p extra_size must be zero. * * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_OCCUPIED_SLOT + * There is already a key in the specified slot. * \retval #PSA_ERROR_NOT_SUPPORTED * \retval #PSA_ERROR_INVALID_ARGUMENT * \retval #PSA_ERROR_INSUFFICIENT_MEMORY @@ -3581,7 +3602,7 @@ typedef struct { * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_generate_key(psa_key_slot_t key, +psa_status_t psa_generate_key(psa_key_handle_t handle, psa_key_type_t type, size_t bits, const void *extra, From 69f976b1d6cf55801e5a268296131ffabef5219b Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 30 Nov 2018 18:46:56 +0100 Subject: [PATCH 05/35] Distinguish in-memory slot number from in-storage slot identifier At the moment, the in-storage slot identifier is the in-memory slot number. But track them separately, to prepare for API changes that will let them be different (psa_open_key, psa_create_key). --- library/psa_crypto.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 7415a9a4f..24ad06d38 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -126,6 +126,7 @@ typedef struct psa_key_type_t type; psa_key_policy_t policy; psa_key_lifetime_t lifetime; + psa_key_id_t persistent_storage_id; union { struct raw_data @@ -720,14 +721,14 @@ static psa_status_t psa_import_key_into_slot( key_slot_t *slot, } #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) -static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t key, - key_slot_t *p_slot ) +static psa_status_t psa_load_persistent_key_into_slot( key_slot_t *p_slot ) { psa_status_t status = PSA_SUCCESS; uint8_t *key_data = NULL; size_t key_data_length = 0; - status = psa_load_persistent_key( key, &( p_slot )->type, + status = psa_load_persistent_key( p_slot->persistent_storage_id, + &( p_slot )->type, &( p_slot )->policy, &key_data, &key_data_length ); if( status != PSA_SUCCESS ) @@ -763,7 +764,7 @@ static psa_status_t psa_get_key_slot( psa_key_slot_t key, if( ( *p_slot )->type == PSA_KEY_TYPE_NONE ) { psa_status_t status = PSA_SUCCESS; - status = psa_load_persistent_key_into_slot( key, *p_slot ); + status = psa_load_persistent_key_into_slot( *p_slot ); if( status != PSA_ERROR_EMPTY_SLOT ) return( status ); } @@ -889,7 +890,8 @@ psa_status_t psa_import_key( psa_key_slot_t key, if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT ) { /* Store in file location */ - status = psa_save_persistent_key( key, slot->type, &slot->policy, data, + status = psa_save_persistent_key( slot->persistent_storage_id, + slot->type, &slot->policy, data, data_length ); if( status != PSA_SUCCESS ) { @@ -914,7 +916,8 @@ psa_status_t psa_destroy_key( psa_key_slot_t key ) #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT ) { - storage_status = psa_destroy_persistent_key( key ); + storage_status = + psa_destroy_persistent_key( slot->persistent_storage_id ); } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ status = psa_remove_key_data_from_memory( slot ); @@ -1121,8 +1124,7 @@ psa_status_t psa_export_public_key( psa_key_slot_t key, } #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) -static psa_status_t psa_save_generated_persistent_key( psa_key_slot_t key, - key_slot_t *slot, +static psa_status_t psa_save_generated_persistent_key( key_slot_t *slot, size_t bits ) { psa_status_t status; @@ -1140,7 +1142,8 @@ static psa_status_t psa_save_generated_persistent_key( psa_key_slot_t key, goto exit; } /* Store in file location */ - status = psa_save_persistent_key( key, slot->type, &slot->policy, + status = psa_save_persistent_key( slot->persistent_storage_id, + slot->type, &slot->policy, data, key_length ); if( status != PSA_SUCCESS ) { @@ -3119,6 +3122,7 @@ psa_status_t psa_set_key_lifetime( psa_key_slot_t key, #endif slot->lifetime = lifetime; + slot->persistent_storage_id = key; return( PSA_SUCCESS ); } @@ -4437,7 +4441,7 @@ psa_status_t psa_generate_key( psa_key_slot_t key, #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT ) { - return( psa_save_generated_persistent_key( key, slot, bits ) ); + return( psa_save_generated_persistent_key( slot, bits ) ); } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ From 7f6e3a868af6c7aba1a16032017b15aca616eb3b Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 30 Nov 2018 18:51:45 +0100 Subject: [PATCH 06/35] Change ASSERT_ALLOC to take a size in elements, not bytes `ASSERT_ALLOC(p, length)` now allocates `length` elements, i.e. `length * sizeof(*p)` bytes. --- tests/suites/helpers.function | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function index f416b3035..cbe3fa0d4 100644 --- a/tests/suites/helpers.function +++ b/tests/suites/helpers.function @@ -95,7 +95,7 @@ typedef struct data_tag * You must set \p pointer to \c NULL before calling this macro and * put `mbedtls_free( pointer )` in the test's cleanup code. * - * If \p size is zero, the resulting \p pointer will be \c NULL. + * If \p length is zero, the resulting \p pointer will be \c NULL. * This is usually what we want in tests since API functions are * supposed to accept null pointers when a buffer size is zero. * @@ -105,20 +105,21 @@ typedef struct data_tag * \param pointer An lvalue where the address of the allocated buffer * will be stored. * This expression may be evaluated multiple times. - * \param size Buffer size to allocate in bytes. + * \param length Number of elements to allocate. * This expression may be evaluated multiple times. * */ -#define ASSERT_ALLOC( pointer, size ) \ - do \ - { \ - TEST_ASSERT( ( pointer ) == NULL ); \ - if( ( size ) != 0 ) \ - { \ - ( pointer ) = mbedtls_calloc( 1, ( size ) ); \ - TEST_ASSERT( ( pointer ) != NULL ); \ - } \ - } \ +#define ASSERT_ALLOC( pointer, length ) \ + do \ + { \ + TEST_ASSERT( ( pointer ) == NULL ); \ + if( ( length ) != 0 ) \ + { \ + ( pointer ) = mbedtls_calloc( sizeof( *( pointer ) ), \ + ( length ) ); \ + TEST_ASSERT( ( pointer ) != NULL ); \ + } \ + } \ while( 0 ) /** Compare two buffers and fail the test case if they differ. From 5ec7b078ea0f35c16403cbac3896e158919c0a83 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 30 Nov 2018 18:53:28 +0100 Subject: [PATCH 07/35] Add tests for the new slot management mechanism Add unit tests for handle allocation and release. --- tests/CMakeLists.txt | 1 + ...test_suite_psa_crypto_slot_management.data | 59 +++ ..._suite_psa_crypto_slot_management.function | 391 ++++++++++++++++++ 3 files changed, 451 insertions(+) create mode 100644 tests/suites/test_suite_psa_crypto_slot_management.data create mode 100644 tests/suites/test_suite_psa_crypto_slot_management.function diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 56ce9338a..21cdfaba2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -116,6 +116,7 @@ add_test_suite(psa_crypto_hash) add_test_suite(psa_crypto_init) add_test_suite(psa_crypto_metadata) add_test_suite(psa_crypto_persistent_key) +add_test_suite(psa_crypto_slot_management) add_test_suite(psa_crypto_storage_file) add_test_suite(shax) add_test_suite(ssl) diff --git a/tests/suites/test_suite_psa_crypto_slot_management.data b/tests/suites/test_suite_psa_crypto_slot_management.data new file mode 100644 index 000000000..133f4c873 --- /dev/null +++ b/tests/suites/test_suite_psa_crypto_slot_management.data @@ -0,0 +1,59 @@ +Transient slot, check after closing +transient_slot_lifecycle:PSA_KEY_TYPE_RAW_DATA:128:0:0:"0123456789abcdef0123456789abcdef":CLOSE_BY_CLOSE + +Transient slot, check after destroying +transient_slot_lifecycle:PSA_KEY_TYPE_RAW_DATA:128:0:0:"0123456789abcdef0123456789abcdef":CLOSE_BY_DESTROY + +Transient slot, check after restart +transient_slot_lifecycle:PSA_KEY_TYPE_RAW_DATA:128:0:0:"0123456789abcdef0123456789abcdef":CLOSE_BY_SHUTDOWN + +Persistent slot, check after closing +persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_RAW_DATA:128:0:0:"0123456789abcdef0123456789abcdef":CLOSE_BY_CLOSE + +Persistent slot, check after destroying +persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_RAW_DATA:128:0:0:"0123456789abcdef0123456789abcdef":CLOSE_BY_DESTROY + +Persistent slot, check after restart +persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_RAW_DATA:128:0:0:"0123456789abcdef0123456789abcdef":CLOSE_BY_SHUTDOWN + +Attempt to overwrite: close before, same type +create_existent:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_RAW_DATA:CLOSE_BEFORE + +Attempt to overwrite: close before, different type +depends_on:MBEDTLS_AES_C +create_existent:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_AES:CLOSE_BEFORE + +Attempt to overwrite: close after, same type +create_existent:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_RAW_DATA:CLOSE_AFTER + +Attempt to overwrite: close after, different type +depends_on:MBEDTLS_AES_C +create_existent:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_AES:CLOSE_AFTER + +Attempt to overwrite: keep open, same type +create_existent:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_RAW_DATA:KEEP_OPEN + +Attempt to overwrite: keep open, different type +depends_on:MBEDTLS_AES_C +create_existent:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_AES:KEEP_OPEN + +Open failure: non-existent identifier +open_fail:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_ERROR_EMPTY_SLOT + +Open failure: volatile lifetime +open_fail:PSA_KEY_LIFETIME_VOLATILE:1:PSA_ERROR_INVALID_ARGUMENT + +Open failure: invalid lifetime +open_fail:0x7fffffff:0:PSA_ERROR_INVALID_ARGUMENT + +Create failure: volatile lifetime +create_fail:PSA_KEY_LIFETIME_VOLATILE:1:PSA_KEY_TYPE_RAW_DATA:8:PSA_ERROR_INVALID_ARGUMENT + +Create failure: invalid lifetime +create_fail:0x7fffffff:0:PSA_KEY_TYPE_RAW_DATA:8:PSA_ERROR_INVALID_ARGUMENT + +Close/destroy invalid handle +invalid_handle: + +Open many transient handles +many_transient_handles:42 diff --git a/tests/suites/test_suite_psa_crypto_slot_management.function b/tests/suites/test_suite_psa_crypto_slot_management.function new file mode 100644 index 000000000..1f1984e3f --- /dev/null +++ b/tests/suites/test_suite_psa_crypto_slot_management.function @@ -0,0 +1,391 @@ +/* BEGIN_HEADER */ +#include + +#if defined(MBEDTLS_PSA_CRYPTO_SPM) +#include "spm/psa_defs.h" +#endif +#include "psa/crypto.h" + +#include "psa_crypto_storage.h" + +#define PSA_ASSERT( expr ) TEST_ASSERT( ( expr ) == PSA_SUCCESS ) + +typedef enum +{ + CLOSE_BY_CLOSE, + CLOSE_BY_DESTROY, + CLOSE_BY_SHUTDOWN, +} close_method_t; + +typedef enum +{ + KEEP_OPEN, + CLOSE_BEFORE, + CLOSE_AFTER, +} reopen_policy_t; + +/* All test functions that create persistent keys must call + * `TEST_MAX_KEY_ID( key_id )` before creating a persistent key with this + * identifier, and must call psa_purge_key_storage() in their cleanup + * code. */ + +/* There is no API to purge all keys. For this test suite, require that + * all key IDs be less than a certain maximum. */ +#define MAX_KEY_ID_FOR_TEST 32 +#define TEST_MAX_KEY_ID( key_id ) \ + TEST_ASSERT( ( key_id ) <= MAX_KEY_ID_FOR_TEST ) +void psa_purge_key_storage( void ) +{ + psa_key_id_t i; + /* The tests may have potentially created key ids from 1 to + * MAX_KEY_ID_FOR_TEST. In addition, run the destroy function on key id + * 0, which file-based storage uses as a temporary file. */ + for( i = 0; i <= MAX_KEY_ID_FOR_TEST; i++ ) + psa_destroy_persistent_key( i ); +} + +static int psa_key_policy_equal( psa_key_policy_t *p1, + psa_key_policy_t *p2 ) +{ + return( psa_key_policy_get_usage( p1 ) == psa_key_policy_get_usage( p2 ) && + psa_key_policy_get_algorithm( p1 ) == psa_key_policy_get_algorithm( p2 ) ); +} + +/* END_HEADER */ + +/* BEGIN_DEPENDENCIES + * depends_on:MBEDTLS_PSA_CRYPTO_C + * END_DEPENDENCIES + */ + +/* BEGIN_CASE */ +void transient_slot_lifecycle( int type_arg, int max_bits_arg, + int alg_arg, int usage_arg, + data_t *key_data, + int close_method_arg ) +{ + psa_key_type_t type = type_arg; + size_t max_bits = max_bits_arg; + psa_algorithm_t alg = alg_arg; + psa_key_usage_t usage_flags = usage_arg; + close_method_t close_method = close_method_arg; + psa_key_type_t read_type; + psa_key_handle_t handle = 0; + psa_key_policy_t policy; + + PSA_ASSERT( psa_crypto_init( ) ); + + /* Get a handle and import a key. */ + PSA_ASSERT( psa_allocate_key( type, max_bits, &handle ) ); + TEST_ASSERT( handle != 0 ); + psa_key_policy_init( &policy ); + psa_key_policy_set_usage( &policy, usage_flags, alg ); + PSA_ASSERT( psa_set_key_policy( handle, &policy ) ); + PSA_ASSERT( psa_import_key( handle, type, key_data->x, key_data->len ) ); + PSA_ASSERT( psa_get_key_information( handle, &read_type, NULL ) ); + TEST_ASSERT( read_type == type ); + + /* Do something that invalidates the handle. */ + switch( close_method ) + { + case CLOSE_BY_CLOSE: + PSA_ASSERT( psa_close_key( handle ) ); + break; + case CLOSE_BY_DESTROY: + PSA_ASSERT( psa_destroy_key( handle ) ); + break; + case CLOSE_BY_SHUTDOWN: + mbedtls_psa_crypto_free( ); + PSA_ASSERT( psa_crypto_init( ) ); + break; + } + /* Test that the handle is now invalid. */ + TEST_ASSERT( psa_get_key_information( handle, &read_type, NULL ) == + PSA_ERROR_INVALID_HANDLE ); + TEST_ASSERT( psa_close_key( handle ) == PSA_ERROR_INVALID_HANDLE ); + +exit: + mbedtls_psa_crypto_free( ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void persistent_slot_lifecycle( int lifetime_arg, int id_arg, + int type_arg, int max_bits_arg, + int alg_arg, int usage_arg, + data_t *key_data, + int close_method_arg ) +{ + psa_key_lifetime_t lifetime = lifetime_arg; + psa_key_id_t id = id_arg; + psa_key_type_t type = type_arg; + size_t max_bits = max_bits_arg; + psa_algorithm_t alg = alg_arg; + psa_key_usage_t usage_flags = usage_arg; + close_method_t close_method = close_method_arg; + psa_key_type_t read_type; + psa_key_handle_t handle = 0; + psa_key_policy_t policy; + + TEST_MAX_KEY_ID( id ); + + PSA_ASSERT( psa_crypto_init( ) ); + + /* Get a handle and import a key. */ + PSA_ASSERT( psa_create_key( lifetime, id, type, max_bits, &handle ) ); + TEST_ASSERT( handle != 0 ); + psa_key_policy_init( &policy ); + psa_key_policy_set_usage( &policy, usage_flags, alg ); + PSA_ASSERT( psa_set_key_policy( handle, &policy ) ); + PSA_ASSERT( psa_import_key( handle, type, key_data->x, key_data->len ) ); + PSA_ASSERT( psa_get_key_information( handle, &read_type, NULL ) ); + TEST_ASSERT( read_type == type ); + + /* Close the key and reopen it. */ + PSA_ASSERT( psa_close_key( handle ) ); + PSA_ASSERT( psa_open_key( lifetime, id, &handle ) ); + PSA_ASSERT( psa_get_key_information( handle, &read_type, NULL ) ); + TEST_ASSERT( read_type == type ); + + /* Do something that invalidates the handle. */ + switch( close_method ) + { + case CLOSE_BY_CLOSE: + PSA_ASSERT( psa_close_key( handle ) ); + break; + case CLOSE_BY_DESTROY: + PSA_ASSERT( psa_destroy_key( handle ) ); + break; + case CLOSE_BY_SHUTDOWN: + mbedtls_psa_crypto_free( ); + PSA_ASSERT( psa_crypto_init( ) ); + break; + } + /* Test that the handle is now invalid. */ + TEST_ASSERT( psa_get_key_information( handle, &read_type, NULL ) == + PSA_ERROR_INVALID_HANDLE ); + TEST_ASSERT( psa_close_key( handle ) == PSA_ERROR_INVALID_HANDLE ); + + /* Try to reopen the key. If we destroyed it, check that it doesn't + * exist, otherwise check that it still exists. */ + switch( close_method ) + { + case CLOSE_BY_CLOSE: + case CLOSE_BY_SHUTDOWN: + PSA_ASSERT( psa_open_key( lifetime, id, &handle ) ); + PSA_ASSERT( psa_get_key_information( handle, &read_type, NULL ) ); + TEST_ASSERT( read_type == type ); + break; + case CLOSE_BY_DESTROY: + TEST_ASSERT( psa_open_key( lifetime, id, &handle ) == + PSA_ERROR_EMPTY_SLOT ); + break; + } + +exit: + mbedtls_psa_crypto_free( ); + psa_purge_key_storage( ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void create_existent( int lifetime_arg, int id_arg, + int new_type_arg, + int reopen_policy_arg ) +{ + psa_key_lifetime_t lifetime = lifetime_arg; + psa_key_id_t id = id_arg; + psa_key_handle_t handle1 = 0, handle2 = 0; + psa_key_policy_t policy1, read_policy; + psa_key_type_t type1 = PSA_KEY_TYPE_RAW_DATA; + psa_key_type_t type2 = new_type_arg; + psa_key_type_t read_type; + const uint8_t material1[16] = "test material #1"; + size_t bits1 = PSA_BYTES_TO_BITS( sizeof( material1 ) ); + size_t read_bits; + uint8_t reexported[sizeof( material1 )]; + size_t reexported_length; + reopen_policy_t reopen_policy = reopen_policy_arg; + + TEST_MAX_KEY_ID( id ); + + PSA_ASSERT( psa_crypto_init( ) ); + + /* Create a key. */ + PSA_ASSERT( psa_create_key( lifetime, id, type1, bits1, &handle1 ) ); + TEST_ASSERT( handle1 != 0 ); + psa_key_policy_init( &policy1 ); + psa_key_policy_set_usage( &policy1, PSA_KEY_USAGE_EXPORT, 0 ); + PSA_ASSERT( psa_set_key_policy( handle1, &policy1 ) ); + PSA_ASSERT( psa_import_key( handle1, type1, + material1, sizeof( material1 ) ) ); + + if( reopen_policy == CLOSE_BEFORE ) + PSA_ASSERT( psa_close_key( handle1 ) ); + + /* Attempt to create a new key in the same slot. */ + TEST_ASSERT( psa_create_key( lifetime, id, type2, bits1, &handle2 ) == + PSA_ERROR_OCCUPIED_SLOT ); + TEST_ASSERT( handle2 == 0 ); + + if( reopen_policy == CLOSE_AFTER ) + PSA_ASSERT( psa_close_key( handle1 ) ); + if( reopen_policy == CLOSE_BEFORE || reopen_policy == CLOSE_AFTER ) + PSA_ASSERT( psa_open_key( lifetime, id, &handle1 ) ); + + /* Check that the original key hasn't changed. */ + PSA_ASSERT( psa_get_key_policy( handle1, &read_policy ) ); + TEST_ASSERT( psa_key_policy_equal( &read_policy, &policy1 ) ); + PSA_ASSERT( psa_get_key_information( handle1, &read_type, &read_bits ) ); + TEST_ASSERT( read_type == type1 ); + TEST_ASSERT( read_bits == bits1 ); + PSA_ASSERT( psa_export_key( handle1, + reexported, sizeof( reexported ), + &reexported_length ) ); + ASSERT_COMPARE( material1, sizeof( material1 ), + reexported, reexported_length ); + +exit: + mbedtls_psa_crypto_free( ); + psa_purge_key_storage( ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void open_fail( int lifetime_arg, int id_arg, + int expected_status_arg ) +{ + psa_key_lifetime_t lifetime = lifetime_arg; + psa_key_id_t id = id_arg; + psa_status_t expected_status = expected_status_arg; + psa_key_handle_t handle = 0xdead; + + PSA_ASSERT( psa_crypto_init( ) ); + + TEST_ASSERT( psa_open_key( lifetime, id, &handle ) == expected_status ); + TEST_ASSERT( handle == 0 ); + +exit: + mbedtls_psa_crypto_free( ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void create_fail( int lifetime_arg, int id_arg, + int type_arg, int max_bits_arg, + int expected_status_arg ) +{ + psa_key_lifetime_t lifetime = lifetime_arg; + psa_key_id_t id = id_arg; + psa_key_type_t type = type_arg; + size_t max_bits = max_bits_arg; + psa_status_t expected_status = expected_status_arg; + psa_key_handle_t handle = 0xdead; + + TEST_MAX_KEY_ID( id ); + + PSA_ASSERT( psa_crypto_init( ) ); + + TEST_ASSERT( psa_create_key( lifetime, id, + type, max_bits, + &handle ) == expected_status ); + TEST_ASSERT( handle == 0 ); + +exit: + mbedtls_psa_crypto_free( ); + psa_purge_key_storage( ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void invalid_handle( ) +{ + psa_key_handle_t handle1 = 0; + psa_key_policy_t policy; + psa_key_type_t read_type; + size_t read_bits; + uint8_t material[1] = "a"; + + PSA_ASSERT( psa_crypto_init( ) ); + + /* Allocate a handle and store a key in it. */ + PSA_ASSERT( psa_allocate_key( PSA_KEY_TYPE_RAW_DATA, 1, &handle1 ) ); + TEST_ASSERT( handle1 != 0 ); + psa_key_policy_init( &policy ); + psa_key_policy_set_usage( &policy, 0, 0 ); + PSA_ASSERT( psa_set_key_policy( handle1, &policy ) ); + PSA_ASSERT( psa_import_key( handle1, PSA_KEY_TYPE_RAW_DATA, + material, sizeof( material ) ) ); + + /* Attempt to close and destroy some invalid handles. */ + TEST_ASSERT( psa_close_key( 0 ) == PSA_ERROR_INVALID_HANDLE ); + TEST_ASSERT( psa_close_key( handle1 - 1 ) == PSA_ERROR_INVALID_HANDLE ); + TEST_ASSERT( psa_close_key( handle1 + 1 ) == PSA_ERROR_INVALID_HANDLE ); + /* At the moment the implementation returns INVALID_ARGUMENT for 0 + * because of the transitional support for non-allocated slot numbers. + * When this is removed, the error will switch to INVALID_HANDLE. */ + TEST_ASSERT( psa_destroy_key( 0 ) == PSA_ERROR_INVALID_ARGUMENT ); + TEST_ASSERT( psa_destroy_key( handle1 - 1 ) == PSA_ERROR_INVALID_HANDLE ); + TEST_ASSERT( psa_destroy_key( handle1 + 1 ) == PSA_ERROR_INVALID_HANDLE ); + + /* After all this, check that the original handle is intact. */ + PSA_ASSERT( psa_get_key_information( handle1, &read_type, &read_bits ) ); + TEST_ASSERT( read_type == PSA_KEY_TYPE_RAW_DATA ); + TEST_ASSERT( read_bits == PSA_BYTES_TO_BITS( sizeof( material ) ) ); + PSA_ASSERT( psa_close_key( handle1 ) ); + +exit: + mbedtls_psa_crypto_free( ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void many_transient_handles( int max_handles_arg ) +{ + psa_key_handle_t *handles = NULL; + size_t max_handles = max_handles_arg; + size_t i, j; + psa_status_t status; + psa_key_policy_t policy; + uint8_t exported[sizeof( size_t )]; + size_t exported_length; + size_t max_bits = PSA_BITS_TO_BYTES( sizeof( exported ) ); + + ASSERT_ALLOC( handles, max_handles ); + PSA_ASSERT( psa_crypto_init( ) ); + psa_key_policy_init( &policy ); + psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, 0 ); + + for( i = 0; i < max_handles; i++ ) + { + status = psa_allocate_key( PSA_KEY_TYPE_RAW_DATA, max_bits, + &handles[i] ); + if( status == PSA_ERROR_INSUFFICIENT_MEMORY ) + break; + TEST_ASSERT( status == PSA_SUCCESS ); + TEST_ASSERT( handles[i] != 0 ); + for( j = 0; j < i; j++ ) + TEST_ASSERT( handles[i] != handles[j] ); + PSA_ASSERT( psa_set_key_policy( handles[i], &policy ) ); + PSA_ASSERT( psa_import_key( handles[i], PSA_KEY_TYPE_RAW_DATA, + (uint8_t *) &i, sizeof( i ) ) ); + } + max_handles = i; + + for( i = 1; i < max_handles; i++ ) + { + PSA_ASSERT( psa_close_key( handles[i - 1] ) ); + PSA_ASSERT( psa_export_key( handles[i], + exported, sizeof( exported ), + &exported_length ) ); + ASSERT_COMPARE( exported, exported_length, + (uint8_t *) &i, sizeof( i ) ); + } + PSA_ASSERT( psa_close_key( handles[i - 1] ) ); + +exit: + mbedtls_psa_crypto_free( ); + mbedtls_free( handles ); +} +/* END_CASE */ + From 961849f6d189e5b796625bb80b6663c0398b0473 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 30 Nov 2018 18:54:54 +0100 Subject: [PATCH 08/35] Implement slot allocation Implement psa_allocate_key, psa_open_key, psa_create_key, psa_close_key. Add support for keys designated to handles to psa_get_key_slot, and thereby to the whole API. Allocated and non-allocated keys can coexist. This is a temporary stage in order to transition from the use of direct slot numbers to allocated handles only. Once all the tests and sample programs have been migrated to use handles, the implementation will be simplified and made more robust with support for handles only. --- library/CMakeLists.txt | 1 + library/Makefile | 1 + library/psa_crypto.c | 107 ++++++++++++++++++++-- library/psa_crypto_slot_management.c | 116 ++++++++++++++++++++++++ library/psa_crypto_slot_management.h | 80 ++++++++++++++++ tests/suites/test_suite_psa_crypto.data | 5 +- visualc/VS2010/mbedTLS.vcxproj | 2 + 7 files changed, 304 insertions(+), 8 deletions(-) create mode 100644 library/psa_crypto_slot_management.c create mode 100644 library/psa_crypto_slot_management.h diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index c8070bb27..3a3f61bcf 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -54,6 +54,7 @@ set(src_crypto platform_util.c poly1305.c psa_crypto.c + psa_crypto_slot_management.c psa_crypto_storage.c psa_crypto_storage_file.c psa_crypto_storage_its.c diff --git a/library/Makefile b/library/Makefile index 95faaaef3..1822a24af 100644 --- a/library/Makefile +++ b/library/Makefile @@ -83,6 +83,7 @@ OBJS_CRYPTO= aes.o aesni.o arc4.o \ pkcs5.o pkparse.o pkwrite.o \ platform.o platform_util.o poly1305.o \ psa_crypto.o \ + psa_crypto_slot_management.o \ psa_crypto_storage.o \ psa_crypto_storage_file.o \ psa_crypto_storage_its.o \ diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 24ad06d38..0d809cbaa 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -44,6 +44,7 @@ #include "psa/crypto.h" #include "psa_crypto_invasive.h" +#include "psa_crypto_slot_management.h" /* Include internal declarations that are useful for implementing persistently * stored keys. */ #include "psa_crypto_storage.h" @@ -117,16 +118,13 @@ static inline int safer_memcmp( const uint8_t *a, const uint8_t *b, size_t n ) /* Global data, support functions and library management */ /****************************************************************/ -/* Number of key slots (plus one because 0 is not used). - * The value is a compile-time constant for now, for simplicity. */ -#define PSA_KEY_SLOT_COUNT 32 - typedef struct { psa_key_type_t type; psa_key_policy_t policy; psa_key_lifetime_t lifetime; psa_key_id_t persistent_storage_id; + unsigned allocated : 1; union { struct raw_data @@ -742,21 +740,34 @@ exit: #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ /* Retrieve a key slot, occupied or not. */ -static psa_status_t psa_get_key_slot( psa_key_slot_t key, +static psa_status_t psa_get_key_slot( psa_key_slot_t key_or_handle, key_slot_t **p_slot ) { + psa_key_slot_t key = key_or_handle & ~PSA_KEY_HANDLE_ALLOCATED_FLAG; + int is_handle = ( key_or_handle & PSA_KEY_HANDLE_ALLOCATED_FLAG ) != 0; + psa_status_t error_if_invalid = + ( is_handle ? + PSA_ERROR_INVALID_HANDLE : + PSA_ERROR_INVALID_ARGUMENT ); + GUARD_MODULE_INITIALIZED; /* 0 is not a valid slot number under any circumstance. This * implementation provides slots number 1 to N where N is the * number of available slots. */ if( key == 0 || key > ARRAY_LENGTH( global_data.key_slots ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); + return( error_if_invalid ); *p_slot = &global_data.key_slots[key - 1]; + /* Allocated slots must only be accessed via a handle. + * Unallocated slots must only be accessed directly. */ + if( ( *p_slot )->allocated != is_handle ) + return( error_if_invalid ); + #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) - if( ( *p_slot )->lifetime == PSA_KEY_LIFETIME_PERSISTENT ) + if( ! ( *p_slot )->allocated && + ( *p_slot )->lifetime == PSA_KEY_LIFETIME_PERSISTENT ) { /* There are two circumstances this can occur: the key material has * not yet been created, or the key exists in storage but has not yet @@ -865,6 +876,88 @@ static psa_status_t psa_remove_key_data_from_memory( key_slot_t *slot ) return( PSA_SUCCESS ); } +/* A slot is available if nothing has been set in it: default lifetime + * and policy, no key type. */ +static int psa_internal_is_slot_available( key_slot_t *slot ) +{ + if( slot->allocated ) + return( 0 ); + if( slot->type != PSA_KEY_TYPE_NONE ) + return( 0 ); + if( slot->lifetime != PSA_KEY_LIFETIME_VOLATILE ) + return( 0 ); + if( slot->policy.usage != 0 || slot->policy.alg != 0 ) + return( 0 ); + return( 1 ); +} + +psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle ) +{ + psa_key_slot_t key; + for( key = PSA_KEY_SLOT_COUNT; key != 0; --( key ) ) + { + key_slot_t *slot = &global_data.key_slots[key - 1]; + if( psa_internal_is_slot_available( slot ) ) + { + slot->allocated = 1; + *handle = key | PSA_KEY_HANDLE_ALLOCATED_FLAG; + return( PSA_SUCCESS ); + } + } + return( PSA_ERROR_INSUFFICIENT_MEMORY ); +} + +psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle, + psa_key_id_t id ) +{ + key_slot_t *slot; + psa_status_t status; + + /* Reject id=0 because by general library conventions, 0 is an invalid + * value wherever possible. */ + if( id == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + /* Reject high values because the file names are reserved for the + * library's internal use. */ + if( id >= 0xffff0000 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + /* Reject values that don't fit in the key slot number type. + * This is a temporary limitation due to the library's internal + * plumbing. */ + if( id > (psa_key_slot_t)( -1 ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_get_key_slot( handle, &slot ); + if( status != PSA_SUCCESS ) + return( status ); + + slot->lifetime = PSA_KEY_LIFETIME_PERSISTENT; + slot->persistent_storage_id = id; + status = psa_load_persistent_key_into_slot( slot ); + + return( status ); +} + +psa_status_t psa_internal_release_key_slot( psa_key_handle_t handle ) +{ + psa_key_slot_t key; + key_slot_t *slot; + psa_status_t status; + /* Don't call psa_get_key_slot() so as not to trigger its automatic + * loading of persistent key data. */ + if( ( handle & PSA_KEY_HANDLE_ALLOCATED_FLAG ) == 0 ) + return( PSA_ERROR_INVALID_HANDLE ); + key = handle & ~PSA_KEY_HANDLE_ALLOCATED_FLAG; + if( key == 0 || key > ARRAY_LENGTH( global_data.key_slots ) ) + return( PSA_ERROR_INVALID_HANDLE ); + slot = &global_data.key_slots[key - 1]; + if( ! slot->allocated ) + return( PSA_ERROR_INVALID_HANDLE ); + status = psa_remove_key_data_from_memory( slot ); + memset( slot, 0, sizeof( *slot ) ); + return( status ); +} + psa_status_t psa_import_key( psa_key_slot_t key, psa_key_type_t type, const uint8_t *data, diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c new file mode 100644 index 000000000..ae5e146b9 --- /dev/null +++ b/library/psa_crypto_slot_management.c @@ -0,0 +1,116 @@ +/* + * PSA crypto layer on top of Mbed TLS crypto + */ +/* Copyright (C) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include "psa/crypto.h" + +#include "psa_crypto_slot_management.h" +#include "psa_crypto_storage.h" + +#include +#include +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) ) + +psa_status_t psa_allocate_key( psa_key_type_t type, + size_t max_bits, + psa_key_handle_t *handle ) +{ + /* This implementation doesn't reserve memory for the keys. */ + (void) type; + (void) max_bits; + *handle = 0; + return( psa_internal_allocate_key_slot( handle ) ); +} + +static psa_status_t persistent_key_setup( psa_key_lifetime_t lifetime, + psa_key_id_t id, + psa_key_handle_t *handle, + psa_status_t wanted_load_status ) +{ + psa_status_t status; + + *handle = 0; + + if( lifetime != PSA_KEY_LIFETIME_PERSISTENT ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_internal_allocate_key_slot( handle ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_internal_make_key_persistent( *handle, id ); + if( status != wanted_load_status ) + { + psa_internal_release_key_slot( *handle ); + *handle = 0; + } + return( status ); +} + +psa_status_t psa_open_key( psa_key_lifetime_t lifetime, + psa_key_id_t id, + psa_key_handle_t *handle ) +{ + return( persistent_key_setup( lifetime, id, handle, PSA_SUCCESS ) ); +} + +psa_status_t psa_create_key( psa_key_lifetime_t lifetime, + psa_key_id_t id, + psa_key_type_t type, + size_t max_bits, + psa_key_handle_t *handle ) +{ + psa_status_t status; + + /* This implementation doesn't reserve memory for the keys. */ + (void) type; + (void) max_bits; + + status = persistent_key_setup( lifetime, id, handle, + PSA_ERROR_EMPTY_SLOT ); + switch( status ) + { + case PSA_SUCCESS: return( PSA_ERROR_OCCUPIED_SLOT ); + case PSA_ERROR_EMPTY_SLOT: return( PSA_SUCCESS ); + default: return( status ); + } +} + +psa_status_t psa_close_key( psa_key_handle_t handle ) +{ + return( psa_internal_release_key_slot( handle ) ); +} + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h new file mode 100644 index 000000000..36917bbaa --- /dev/null +++ b/library/psa_crypto_slot_management.h @@ -0,0 +1,80 @@ +/* + * PSA crypto layer on top of Mbed TLS crypto + */ +/* Copyright (C) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_SLOT_MANAGEMENT_H +#define PSA_CRYPTO_SLOT_MANAGEMENT_H + +/* Number of key slots (plus one because 0 is not used). + * The value is a compile-time constant for now, for simplicity. */ +#define PSA_KEY_SLOT_COUNT 32 + +/* All dynamically allocated handles have this bit set. */ +#define PSA_KEY_HANDLE_ALLOCATED_FLAG ( (psa_key_handle_t) 0x8000 ) + +/** \defgroup core_slot_management Internal functions exposed by the core + * @{ + */ + +/** Find a free key slot and mark it as in use. + * + * \param[out] handle On success, a slot number that is not in use. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle ); + +/** Wipe an a key slot and mark it as available. + * + * This does not affect persistent storage. + * + * \param handle The key slot number to release. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_TAMPERING_DETECTED + */ +psa_status_t psa_internal_release_key_slot( psa_key_handle_t handle ); + +/** Declare a slot as persistent and load it from storage. + * + * This function may only be called immediately after a successful call + * to psa_internal_allocate_key_slot(). + * + * \param handle A handle to a key slot freshly allocated with + * psa_internal_allocate_key_slot(). + * + * \retval #PSA_SUCCESS + * The slot content was loaded successfully. + * \retval #PSA_ERROR_EMPTY_SLOT + * There is no content for this slot in persistent storage. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p id is not acceptable. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_STORAGE_FAILURE + */ +psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle, + psa_key_id_t id ); + +/**@}*/ + +#endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */ diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 91739f55e..33ca54f6d 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -39,7 +39,10 @@ PSA export out of range key slot - lower bound export_invalid_slot:0:PSA_ERROR_INVALID_ARGUMENT PSA export out of range key slot - upper bound -export_invalid_slot:(psa_key_slot_t)(-1):PSA_ERROR_INVALID_ARGUMENT +# Hard-code the upper bound of slots that are directly accessible because the +# API does not expose this value. This is temporary: directly-accessible +# slots are about to be removed. +export_invalid_slot:32767:PSA_ERROR_INVALID_ARGUMENT PSA export a slot where there was some activity but no key material creation export_with_no_key_activity diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj index d305c4515..341e058a8 100644 --- a/visualc/VS2010/mbedTLS.vcxproj +++ b/visualc/VS2010/mbedTLS.vcxproj @@ -232,6 +232,7 @@ + @@ -291,6 +292,7 @@ + From d7c75707b88d3e3aca2f2fdcdcad9f76cfafff83 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 3 Dec 2018 10:36:46 +0100 Subject: [PATCH 09/35] mbedtls_psa_crypto_free: free allocated slots as well Access the slot directly rather than going through psa_get_key_slot. Unlike other places where key slots are accessed through psa_get_key_slot, here, we know where all the slots are and there are no policy or permission considerations. This resolves a memory leak: allocated slots were not getting freed because psa_get_key_slot rejected the attempt of accessing them directly rather than via a handle. --- library/psa_crypto.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 0d809cbaa..50c8a8962 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -4559,17 +4559,13 @@ psa_status_t mbedtls_psa_crypto_configure_entropy_sources( void mbedtls_psa_crypto_free( void ) { - psa_key_slot_t key; - key_slot_t *slot; - psa_status_t status; if( global_data.key_slots_initialized ) { + psa_key_slot_t key; for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ ) { - status = psa_get_key_slot( key, &slot ); - if( status != PSA_SUCCESS ) - continue; - psa_remove_key_data_from_memory( slot ); + key_slot_t *slot = &global_data.key_slots[key - 1]; + (void) psa_remove_key_data_from_memory( slot ); /* Zeroize the slot to wipe metadata such as policies. */ mbedtls_zeroize( slot, sizeof( *slot ) ); } From a426168cbff890e96807a489e0d3a3a164d2e105 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 3 Dec 2018 11:34:01 +0100 Subject: [PATCH 10/35] Test that failure of import_key preserves metadata --- tests/suites/test_suite_psa_crypto.data | 4 +++ tests/suites/test_suite_psa_crypto.function | 39 +++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 33ca54f6d..d23c364bf 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -323,6 +323,10 @@ PSA import EC keypair: valid key but RSA depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP512R1_ENABLED:MBEDTLS_RSA_C import:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P512R1):PSA_ERROR_INVALID_ARGUMENT +PSA import failure preserves policy +depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15 +import_twice:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_VERIFY:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_SUCCESS + PSA import RSA key pair: maximum size exceeded depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C import_rsa_made_up:PSA_VENDOR_RSA_MAX_KEY_BITS+8:1:PSA_ERROR_NOT_SUPPORTED diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 2fa060b25..3978ba7a0 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -948,6 +948,45 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void import_twice( int alg_arg, int usage_arg, + int type1_arg, data_t *data1, + int expected_import1_status_arg, + int type2_arg, data_t *data2, + int expected_import2_status_arg ) +{ + int slot = 1; + psa_algorithm_t alg = alg_arg; + psa_key_usage_t usage = usage_arg; + psa_key_type_t type1 = type1_arg; + psa_status_t expected_import1_status = expected_import1_status_arg; + psa_key_type_t type2 = type2_arg; + psa_status_t expected_import2_status = expected_import2_status_arg; + psa_key_policy_t policy; + psa_status_t status; + + TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + + psa_key_policy_init( &policy ); + psa_key_policy_set_usage( &policy, usage, alg ); + TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + + status = psa_import_key( slot, type1, data1->x, data1->len ); + TEST_ASSERT( status == expected_import1_status ); + status = psa_import_key( slot, type2, data2->x, data2->len ); + TEST_ASSERT( status == expected_import2_status ); + + if( expected_import1_status == PSA_SUCCESS || + expected_import2_status == PSA_SUCCESS ) + { + TEST_ASSERT( exercise_key( slot, usage, alg ) ); + } + +exit: + mbedtls_psa_crypto_free( ); +} +/* END_CASE */ + /* BEGIN_CASE */ void import_rsa_made_up( int bits_arg, int keypair, int expected_status_arg ) { From f77ed1f20b636c81a980c1e7431130db249bf1eb Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 3 Dec 2018 11:58:46 +0100 Subject: [PATCH 11/35] Factor the common idiom psa_wipe_key_slot into a function Many places in the code called psa_remove_key_data_from_memory (which preserves metadata for the sake of failues in psa_import_key) followed by clearing the slot data. Use an auxiliary function for this. --- library/psa_crypto.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 50c8a8962..1a038a12a 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -637,6 +637,9 @@ exit: } #endif /* defined(MBEDTLS_ECP_C) */ +/** Import key data into a slot. `slot->type` must have been set + * previously. This function assumes that the slot does not contain + * any key material yet. On failure, the slot content is unchanged. */ static psa_status_t psa_import_key_into_slot( key_slot_t *slot, const uint8_t *data, size_t data_length ) @@ -840,6 +843,7 @@ static psa_status_t psa_get_key_from_slot( psa_key_slot_t key, return( PSA_SUCCESS ); } +/** Wipe key data from a slot. Preserve metadata such as the policy. */ static psa_status_t psa_remove_key_data_from_memory( key_slot_t *slot ) { if( slot->type == PSA_KEY_TYPE_NONE ) @@ -876,6 +880,18 @@ static psa_status_t psa_remove_key_data_from_memory( key_slot_t *slot ) return( PSA_SUCCESS ); } +/** Completely wipe a slot in memory, including its policy. + * Persistent storage is not affected. */ +static psa_status_t psa_wipe_key_slot( key_slot_t *slot ) +{ + psa_status_t status = psa_remove_key_data_from_memory( slot ); + /* 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. */ + memset( slot, 0, sizeof( *slot ) ); + return( status ); +} + /* A slot is available if nothing has been set in it: default lifetime * and policy, no key type. */ static int psa_internal_is_slot_available( key_slot_t *slot ) @@ -942,7 +958,6 @@ psa_status_t psa_internal_release_key_slot( psa_key_handle_t handle ) { psa_key_slot_t key; key_slot_t *slot; - psa_status_t status; /* Don't call psa_get_key_slot() so as not to trigger its automatic * loading of persistent key data. */ if( ( handle & PSA_KEY_HANDLE_ALLOCATED_FLAG ) == 0 ) @@ -953,9 +968,7 @@ psa_status_t psa_internal_release_key_slot( psa_key_handle_t handle ) slot = &global_data.key_slots[key - 1]; if( ! slot->allocated ) return( PSA_ERROR_INVALID_HANDLE ); - status = psa_remove_key_data_from_memory( slot ); - memset( slot, 0, sizeof( *slot ) ); - return( status ); + return( psa_wipe_key_slot( slot ) ); } psa_status_t psa_import_key( psa_key_slot_t key, @@ -1013,9 +1026,7 @@ psa_status_t psa_destroy_key( psa_key_slot_t key ) psa_destroy_persistent_key( slot->persistent_storage_id ); } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ - status = psa_remove_key_data_from_memory( slot ); - /* Zeroize the slot to wipe metadata such as policies. */ - mbedtls_zeroize( slot, sizeof( *slot ) ); + status = psa_wipe_key_slot( slot ); if( status != PSA_SUCCESS ) return( status ); return( storage_status ); @@ -4565,9 +4576,7 @@ void mbedtls_psa_crypto_free( void ) for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ ) { key_slot_t *slot = &global_data.key_slots[key - 1]; - (void) psa_remove_key_data_from_memory( slot ); - /* Zeroize the slot to wipe metadata such as policies. */ - mbedtls_zeroize( slot, sizeof( *slot ) ); + (void) psa_wipe_key_slot( slot ); } } if( global_data.rng_state != RNG_NOT_INITIALIZED ) From dc911fd59455bcee34227ea9d9ea358d3fec0cd0 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 3 Dec 2018 12:21:51 +0100 Subject: [PATCH 12/35] Remove redundant slot-based test fill_slots is superseded by many_transient_handles. --- tests/suites/test_suite_psa_crypto.data | 3 -- tests/suites/test_suite_psa_crypto.function | 56 --------------------- 2 files changed, 59 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index d23c364bf..a468abfef 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -1,9 +1,6 @@ PSA compile-time sanity checks static_checks: -PSA fill 250 slots -fill_slots:250 - 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 3978ba7a0..aebf9a6f2 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -871,62 +871,6 @@ void static_checks( ) } /* END_CASE */ -/* BEGIN_CASE */ -void fill_slots( int max_arg ) -{ - /* Fill all the slots until we run out of memory or out of slots, - * or until some limit specified in the test data for the sake of - * implementations with an essentially unlimited number of slots. - * This test assumes that available slots are numbered from 1. */ - - psa_key_slot_t slot; - psa_key_slot_t max = 0; - psa_key_policy_t policy; - uint8_t exported[sizeof( max )]; - size_t exported_size; - psa_status_t status; - - TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); - - psa_key_policy_init( &policy ); - psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, 0 ); - - for( max = 1; max <= (size_t) max_arg; max++ ) - { - status = psa_set_key_policy( max, &policy ); - /* Stop filling slots if we run out of memory or out of - * available slots. */ - TEST_ASSERT( status == PSA_SUCCESS || - status == PSA_ERROR_INSUFFICIENT_MEMORY || - status == PSA_ERROR_INVALID_ARGUMENT ); - if( status != PSA_SUCCESS ) - break; - status = psa_import_key( max, PSA_KEY_TYPE_RAW_DATA, - (uint8_t*) &max, sizeof( max ) ); - /* Since psa_set_key_policy succeeded, we know that the slot - * number is valid. But we may legitimately run out of memory. */ - TEST_ASSERT( status == PSA_SUCCESS || - status == PSA_ERROR_INSUFFICIENT_MEMORY ); - if( status != PSA_SUCCESS ) - break; - } - /* `max` is now the first slot number that wasn't filled. */ - max -= 1; - - for( slot = 1; slot <= max; slot++ ) - { - TEST_ASSERT( psa_export_key( slot, - exported, sizeof( exported ), - &exported_size ) == PSA_SUCCESS ); - ASSERT_COMPARE( &slot, sizeof( slot ), exported, exported_size ); - } - -exit: - /* Do not destroy the keys. mbedtls_psa_crypto_free() should do it. */ - mbedtls_psa_crypto_free( ); -} -/* END_CASE */ - /* BEGIN_CASE */ void import( data_t *data, int type, int expected_status_arg ) { From a8860b2990be9a1380a6bf1ca4072850e247c870 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 3 Dec 2018 14:56:51 +0100 Subject: [PATCH 13/35] Remove lifetime test functions With the handle-based slot management interface, psa_set_key_lifetime will no longer exist, so remove the corresponding unit tests. --- tests/suites/test_suite_psa_crypto.data | 12 ----- tests/suites/test_suite_psa_crypto.function | 55 --------------------- 2 files changed, 67 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index a468abfef..4d7793556 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -471,18 +471,6 @@ PSA key policy: agreement, wrong algorithm depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_FFDH(PSA_ALG_SELECT_RAW) -PSA key lifetime: set and get volatile -key_lifetime:PSA_KEY_LIFETIME_VOLATILE - -PSA key lifetime set: invalid key slot -key_lifetime_set_fail:0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_INVALID_ARGUMENT - -PSA key lifetime set: cannot change write_once lifetime -key_lifetime_set_fail:1:PSA_KEY_LIFETIME_WRITE_ONCE:PSA_ERROR_NOT_SUPPORTED - -PSA key lifetime set: invalid key lifetime value -key_lifetime_set_fail:1:PSA_KEY_LIFETIME_PERSISTENT+1:PSA_ERROR_INVALID_ARGUMENT - PSA hash setup: good, SHA-1 depends_on:MBEDTLS_SHA1_C hash_setup:PSA_ALG_SHA_1:PSA_SUCCESS diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index aebf9a6f2..8b3c79428 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -1733,61 +1733,6 @@ exit: } /* END_CASE */ -/* BEGIN_CASE */ -void key_lifetime( int lifetime_arg ) -{ - int key_slot = 1; - psa_key_type_t key_type = PSA_KEY_TYPE_RAW_DATA; - unsigned char key[32] = {0}; - psa_key_lifetime_t lifetime_set = lifetime_arg; - psa_key_lifetime_t lifetime_get; - - memset( key, 0x2a, sizeof( key ) ); - - TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); - - TEST_ASSERT( psa_set_key_lifetime( key_slot, - lifetime_set ) == PSA_SUCCESS ); - - TEST_ASSERT( psa_import_key( key_slot, key_type, - key, sizeof( key ) ) == PSA_SUCCESS ); - - TEST_ASSERT( psa_get_key_lifetime( key_slot, - &lifetime_get ) == PSA_SUCCESS ); - - TEST_ASSERT( lifetime_get == lifetime_set ); - -exit: - psa_destroy_key( key_slot ); - mbedtls_psa_crypto_free( ); -} -/* END_CASE */ - -/* BEGIN_CASE */ -void key_lifetime_set_fail( int key_slot_arg, - int lifetime_arg, - int expected_status_arg ) -{ - psa_key_slot_t key_slot = key_slot_arg; - psa_key_lifetime_t lifetime_set = lifetime_arg; - psa_status_t actual_status; - psa_status_t expected_status = expected_status_arg; - - TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); - - actual_status = psa_set_key_lifetime( key_slot, lifetime_set ); - - if( actual_status == PSA_SUCCESS ) - actual_status = psa_set_key_lifetime( key_slot, lifetime_set ); - - TEST_ASSERT( expected_status == actual_status ); - -exit: - psa_destroy_key( key_slot ); - mbedtls_psa_crypto_free( ); -} -/* END_CASE */ - /* BEGIN_CASE */ void hash_setup( int alg_arg, int expected_status_arg ) From bdf309ccdb51255a39abd1d29bbf19539263813b Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 3 Dec 2018 15:36:32 +0100 Subject: [PATCH 14/35] Convert the PSA crypto cryptography tests to the new handle API Switch from the direct use of slot numbers to handles allocated by psa_allocate_key. This commit does not affect persistent key tests except for the one test function in test_suite_psa_crypto that uses persistent keys (persistent_key_load_key_from_storage). The general principle for each function is: * Change `psa_key_slot_t slot` to `psa_key_handle_t handle`. * Call psa_allocate_key() before setting the policy of the slot, or before creating key material in functions that don't set a policy. * Some PSA_ERROR_EMPTY_SLOT errors become PSA_ERROR_INVALID_HANDLE because there is now a distinction between not having a valid handle, and having a valid handle to a slot that doesn't contain key material. * In tests that use symmetric keys, calculate the max_bits parameters of psa_allocate_key() from the key data size. In tests where the key may be asymmetric, call an auxiliary macro KEY_BITS_FROM_DATA which returns an overapproximation. There's no good way to find a good value for max_bits with the API, I think the API should be tweaked. --- tests/suites/test_suite_psa_crypto.data | 16 +- tests/suites/test_suite_psa_crypto.function | 855 ++++++++++++-------- 2 files changed, 511 insertions(+), 360 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 4d7793556..9801a8db7 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -29,17 +29,15 @@ PSA import to non empty key slot depends_on:MBEDTLS_AES_C import_key_nonempty_slot -PSA export empty key slot -export_invalid_slot:1:PSA_ERROR_EMPTY_SLOT +PSA export invalid handle (0) +export_invalid_handle:0:PSA_ERROR_INVALID_ARGUMENT -PSA export out of range key slot - lower bound -export_invalid_slot:0:PSA_ERROR_INVALID_ARGUMENT +PSA export invalid handle (smallest plausible handle) +# EMPTY_SLOT is temporary, because this valie is treated as a numbered slot, not as a handle +export_invalid_handle:1:PSA_ERROR_EMPTY_SLOT -PSA export out of range key slot - upper bound -# Hard-code the upper bound of slots that are directly accessible because the -# API does not expose this value. This is temporary: directly-accessible -# slots are about to be removed. -export_invalid_slot:32767:PSA_ERROR_INVALID_ARGUMENT +PSA export invalid handle (largest plausible handle) +export_invalid_handle:-1:PSA_ERROR_INVALID_HANDLE PSA export a slot where there was some activity but no key material creation export_with_no_key_activity diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 8b3c79428..c40ac5f7d 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -130,7 +130,7 @@ static int construct_fake_rsa_key( unsigned char *buffer, return( len ); } -static int exercise_mac_key( psa_key_slot_t key, +static int exercise_mac_key( psa_key_handle_t handle, psa_key_usage_t usage, psa_algorithm_t alg ) { @@ -142,7 +142,7 @@ static int exercise_mac_key( psa_key_slot_t key, if( usage & PSA_KEY_USAGE_SIGN ) { TEST_ASSERT( psa_mac_sign_setup( &operation, - key, alg ) == PSA_SUCCESS ); + handle, alg ) == PSA_SUCCESS ); TEST_ASSERT( psa_mac_update( &operation, input, sizeof( input ) ) == PSA_SUCCESS ); TEST_ASSERT( psa_mac_sign_finish( &operation, @@ -157,7 +157,7 @@ static int exercise_mac_key( psa_key_slot_t key, PSA_SUCCESS : PSA_ERROR_INVALID_SIGNATURE ); TEST_ASSERT( psa_mac_verify_setup( &operation, - key, alg ) == PSA_SUCCESS ); + handle, alg ) == PSA_SUCCESS ); TEST_ASSERT( psa_mac_update( &operation, input, sizeof( input ) ) == PSA_SUCCESS ); TEST_ASSERT( psa_mac_verify_finish( &operation, @@ -172,7 +172,7 @@ exit: return( 0 ); } -static int exercise_cipher_key( psa_key_slot_t key, +static int exercise_cipher_key( psa_key_handle_t handle, psa_key_usage_t usage, psa_algorithm_t alg ) { @@ -188,7 +188,7 @@ static int exercise_cipher_key( psa_key_slot_t key, if( usage & PSA_KEY_USAGE_ENCRYPT ) { TEST_ASSERT( psa_cipher_encrypt_setup( &operation, - key, alg ) == PSA_SUCCESS ); + handle, alg ) == PSA_SUCCESS ); TEST_ASSERT( psa_cipher_generate_iv( &operation, iv, sizeof( iv ), &iv_length ) == PSA_SUCCESS ); @@ -210,11 +210,11 @@ static int exercise_cipher_key( psa_key_slot_t key, if( ! ( usage & PSA_KEY_USAGE_ENCRYPT ) ) { size_t bits; - TEST_ASSERT( psa_get_key_information( key, &type, &bits ) ); + TEST_ASSERT( psa_get_key_information( handle, &type, &bits ) ); iv_length = PSA_BLOCK_CIPHER_BLOCK_SIZE( type ); } TEST_ASSERT( psa_cipher_decrypt_setup( &operation, - key, alg ) == PSA_SUCCESS ); + handle, alg ) == PSA_SUCCESS ); TEST_ASSERT( psa_cipher_set_iv( &operation, iv, iv_length ) == PSA_SUCCESS ); TEST_ASSERT( psa_cipher_update( &operation, @@ -243,7 +243,7 @@ exit: return( 0 ); } -static int exercise_aead_key( psa_key_slot_t key, +static int exercise_aead_key( psa_key_handle_t handle, psa_key_usage_t usage, psa_algorithm_t alg ) { @@ -256,7 +256,7 @@ static int exercise_aead_key( psa_key_slot_t key, if( usage & PSA_KEY_USAGE_ENCRYPT ) { - TEST_ASSERT( psa_aead_encrypt( key, alg, + TEST_ASSERT( psa_aead_encrypt( handle, alg, nonce, nonce_length, NULL, 0, plaintext, sizeof( plaintext ), @@ -270,7 +270,7 @@ static int exercise_aead_key( psa_key_slot_t key, ( usage & PSA_KEY_USAGE_ENCRYPT ? PSA_SUCCESS : PSA_ERROR_INVALID_SIGNATURE ); - TEST_ASSERT( psa_aead_decrypt( key, alg, + TEST_ASSERT( psa_aead_decrypt( handle, alg, nonce, nonce_length, NULL, 0, ciphertext, ciphertext_length, @@ -284,7 +284,7 @@ exit: return( 0 ); } -static int exercise_signature_key( psa_key_slot_t key, +static int exercise_signature_key( psa_key_handle_t handle, psa_key_usage_t usage, psa_algorithm_t alg ) { @@ -301,7 +301,7 @@ static int exercise_signature_key( psa_key_slot_t key, psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg ); if( hash_alg != 0 ) payload_length = PSA_HASH_SIZE( hash_alg ); - TEST_ASSERT( psa_asymmetric_sign( key, alg, + TEST_ASSERT( psa_asymmetric_sign( handle, alg, payload, payload_length, signature, sizeof( signature ), &signature_length ) == PSA_SUCCESS ); @@ -313,7 +313,7 @@ static int exercise_signature_key( psa_key_slot_t key, ( usage & PSA_KEY_USAGE_SIGN ? PSA_SUCCESS : PSA_ERROR_INVALID_SIGNATURE ); - TEST_ASSERT( psa_asymmetric_verify( key, alg, + TEST_ASSERT( psa_asymmetric_verify( handle, alg, payload, payload_length, signature, signature_length ) == verify_status ); @@ -325,7 +325,7 @@ exit: return( 0 ); } -static int exercise_asymmetric_encryption_key( psa_key_slot_t key, +static int exercise_asymmetric_encryption_key( psa_key_handle_t handle, psa_key_usage_t usage, psa_algorithm_t alg ) { @@ -337,7 +337,7 @@ static int exercise_asymmetric_encryption_key( psa_key_slot_t key, if( usage & PSA_KEY_USAGE_ENCRYPT ) { TEST_ASSERT( - psa_asymmetric_encrypt( key, alg, + psa_asymmetric_encrypt( handle, alg, plaintext, plaintext_length, NULL, 0, ciphertext, sizeof( ciphertext ), @@ -347,7 +347,7 @@ static int exercise_asymmetric_encryption_key( psa_key_slot_t key, if( usage & PSA_KEY_USAGE_DECRYPT ) { psa_status_t status = - psa_asymmetric_decrypt( key, alg, + psa_asymmetric_decrypt( handle, alg, ciphertext, ciphertext_length, NULL, 0, plaintext, sizeof( plaintext ), @@ -364,7 +364,7 @@ exit: return( 0 ); } -static int exercise_key_derivation_key( psa_key_slot_t key, +static int exercise_key_derivation_key( psa_key_handle_t handle, psa_key_usage_t usage, psa_algorithm_t alg ) { @@ -378,7 +378,7 @@ static int exercise_key_derivation_key( psa_key_slot_t key, if( usage & PSA_KEY_USAGE_DERIVE ) { TEST_ASSERT( psa_key_derivation( &generator, - key, alg, + handle, alg, label, label_length, seed, seed_length, sizeof( output ) ) == PSA_SUCCESS ); @@ -397,7 +397,7 @@ exit: /* We need two keys to exercise key agreement. Exercise the * private key against its own public key. */ static psa_status_t key_agreement_with_self( psa_crypto_generator_t *generator, - psa_key_type_t key_slot, + psa_key_handle_t handle, psa_algorithm_t alg ) { psa_key_type_t private_key_type; @@ -410,18 +410,18 @@ static psa_status_t key_agreement_with_self( psa_crypto_generator_t *generator, * good enough: callers will report it as a failed test anyway. */ psa_status_t status = PSA_ERROR_UNKNOWN_ERROR; - TEST_ASSERT( psa_get_key_information( key_slot, + TEST_ASSERT( psa_get_key_information( handle, &private_key_type, &key_bits ) == PSA_SUCCESS ); public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR( private_key_type ); public_key_length = PSA_KEY_EXPORT_MAX_SIZE( public_key_type, key_bits ); ASSERT_ALLOC( public_key, public_key_length ); TEST_ASSERT( public_key != NULL ); - TEST_ASSERT( psa_export_public_key( key_slot, + TEST_ASSERT( psa_export_public_key( handle, public_key, public_key_length, &public_key_length ) == PSA_SUCCESS ); - status = psa_key_agreement( generator, key_slot, + status = psa_key_agreement( generator, handle, public_key, public_key_length, alg ); exit: @@ -429,7 +429,7 @@ exit: return( status ); } -static int exercise_key_agreement_key( psa_key_slot_t key, +static int exercise_key_agreement_key( psa_key_handle_t handle, psa_key_usage_t usage, psa_algorithm_t alg ) { @@ -441,7 +441,7 @@ static int exercise_key_agreement_key( psa_key_slot_t key, { /* We need two keys to exercise key agreement. Exercise the * private key against its own public key. */ - TEST_ASSERT( key_agreement_with_self( &generator, key, alg ) == + TEST_ASSERT( key_agreement_with_self( &generator, handle, alg ) == PSA_SUCCESS ); TEST_ASSERT( psa_generator_read( &generator, output, @@ -713,7 +713,7 @@ exit: return( 0 ); } -static int exercise_export_key( psa_key_slot_t slot, +static int exercise_export_key( psa_key_handle_t handle, psa_key_usage_t usage ) { psa_key_type_t type; @@ -723,12 +723,12 @@ static int exercise_export_key( psa_key_slot_t slot, size_t exported_length = 0; int ok = 0; - TEST_ASSERT( psa_get_key_information( slot, &type, &bits ) == PSA_SUCCESS ); + TEST_ASSERT( psa_get_key_information( handle, &type, &bits ) == PSA_SUCCESS ); if( ( usage & PSA_KEY_USAGE_EXPORT ) == 0 && ! PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ) { - TEST_ASSERT( psa_export_key( slot, NULL, 0, &exported_length ) == + TEST_ASSERT( psa_export_key( handle, NULL, 0, &exported_length ) == PSA_ERROR_NOT_PERMITTED ); return( 1 ); } @@ -736,7 +736,7 @@ static int exercise_export_key( psa_key_slot_t slot, exported_size = PSA_KEY_EXPORT_MAX_SIZE( type, bits ); ASSERT_ALLOC( exported, exported_size ); - TEST_ASSERT( psa_export_key( slot, + TEST_ASSERT( psa_export_key( handle, exported, exported_size, &exported_length ) == PSA_SUCCESS ); ok = exported_key_sanity_check( type, bits, exported, exported_length ); @@ -746,7 +746,7 @@ exit: return( ok ); } -static int exercise_export_public_key( psa_key_slot_t slot ) +static int exercise_export_public_key( psa_key_handle_t handle ) { psa_key_type_t type; psa_key_type_t public_type; @@ -756,10 +756,10 @@ static int exercise_export_public_key( psa_key_slot_t slot ) size_t exported_length = 0; int ok = 0; - TEST_ASSERT( psa_get_key_information( slot, &type, &bits ) == PSA_SUCCESS ); + TEST_ASSERT( psa_get_key_information( handle, &type, &bits ) == PSA_SUCCESS ); if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( type ) ) { - TEST_ASSERT( psa_export_public_key( slot, + TEST_ASSERT( psa_export_public_key( handle, NULL, 0, &exported_length ) == PSA_ERROR_INVALID_ARGUMENT ); return( 1 ); @@ -769,7 +769,7 @@ static int exercise_export_public_key( psa_key_slot_t slot ) exported_size = PSA_KEY_EXPORT_MAX_SIZE( public_type, bits ); ASSERT_ALLOC( exported, exported_size ); - TEST_ASSERT( psa_export_public_key( slot, + TEST_ASSERT( psa_export_public_key( handle, exported, exported_size, &exported_length ) == PSA_SUCCESS ); ok = exported_key_sanity_check( public_type, bits, @@ -780,7 +780,7 @@ exit: return( ok ); } -static int exercise_key( psa_key_slot_t slot, +static int exercise_key( psa_key_handle_t handle, psa_key_usage_t usage, psa_algorithm_t alg ) { @@ -788,19 +788,19 @@ static int exercise_key( psa_key_slot_t slot, if( alg == 0 ) ok = 1; /* If no algorihm, do nothing (used for raw data "keys"). */ else if( PSA_ALG_IS_MAC( alg ) ) - ok = exercise_mac_key( slot, usage, alg ); + ok = exercise_mac_key( handle, usage, alg ); else if( PSA_ALG_IS_CIPHER( alg ) ) - ok = exercise_cipher_key( slot, usage, alg ); + ok = exercise_cipher_key( handle, usage, alg ); else if( PSA_ALG_IS_AEAD( alg ) ) - ok = exercise_aead_key( slot, usage, alg ); + ok = exercise_aead_key( handle, usage, alg ); else if( PSA_ALG_IS_SIGN( alg ) ) - ok = exercise_signature_key( slot, usage, alg ); + ok = exercise_signature_key( handle, usage, alg ); else if( PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ) - ok = exercise_asymmetric_encryption_key( slot, usage, alg ); + ok = exercise_asymmetric_encryption_key( handle, usage, alg ); else if( PSA_ALG_IS_KEY_DERIVATION( alg ) ) - ok = exercise_key_derivation_key( slot, usage, alg ); + ok = exercise_key_derivation_key( handle, usage, alg ); else if( PSA_ALG_IS_KEY_AGREEMENT( alg ) ) - ok = exercise_key_agreement_key( slot, usage, alg ); + ok = exercise_key_agreement_key( handle, usage, alg ); else { char message[40]; @@ -811,8 +811,8 @@ static int exercise_key( psa_key_slot_t slot, ok = 0; } - ok = ok && exercise_export_key( slot, usage ); - ok = ok && exercise_export_public_key( slot ); + ok = ok && exercise_export_key( handle, usage ); + ok = ok && exercise_export_public_key( handle ); return( ok ); } @@ -845,6 +845,13 @@ static psa_key_usage_t usage_to_exercise( psa_key_type_t type, } +/* An overapproximation of the amount of storage needed for a key of the + * given type and with the given content. The API doesn't make it easy + * to find a good value for the size. The current implementation doesn't + * care about the value anyway. */ +#define KEY_BITS_FROM_DATA( type, data ) \ + ( data )->len + typedef enum { IMPORT_KEY = 0, GENERATE_KEY = 1, @@ -874,7 +881,7 @@ void static_checks( ) /* BEGIN_CASE */ void import( data_t *data, int type, int expected_status_arg ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_status_t expected_status = expected_status_arg; psa_status_t status; @@ -882,10 +889,12 @@ void import( data_t *data, int type, int expected_status_arg ) TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( data->len ) ); TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); - status = psa_import_key( slot, type, data->x, data->len ); + TEST_ASSERT( psa_allocate_key( type, KEY_BITS_FROM_DATA( type, data ), + &handle ) == PSA_SUCCESS ); + status = psa_import_key( handle, type, data->x, data->len ); TEST_ASSERT( status == expected_status ); if( status == PSA_SUCCESS ) - TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS ); + TEST_ASSERT( psa_destroy_key( handle ) == PSA_SUCCESS ); exit: mbedtls_psa_crypto_free( ); @@ -899,7 +908,7 @@ void import_twice( int alg_arg, int usage_arg, int type2_arg, data_t *data2, int expected_import2_status_arg ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_algorithm_t alg = alg_arg; psa_key_usage_t usage = usage_arg; psa_key_type_t type1 = type1_arg; @@ -911,19 +920,23 @@ void import_twice( int alg_arg, int usage_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( type1, + MAX( KEY_BITS_FROM_DATA( type1, data1 ), + KEY_BITS_FROM_DATA( type2, data2 ) ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, usage, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - status = psa_import_key( slot, type1, data1->x, data1->len ); + status = psa_import_key( handle, type1, data1->x, data1->len ); TEST_ASSERT( status == expected_import1_status ); - status = psa_import_key( slot, type2, data2->x, data2->len ); + status = psa_import_key( handle, type2, data2->x, data2->len ); TEST_ASSERT( status == expected_import2_status ); if( expected_import1_status == PSA_SUCCESS || expected_import2_status == PSA_SUCCESS ) { - TEST_ASSERT( exercise_key( slot, usage, alg ) ); + TEST_ASSERT( exercise_key( handle, usage, alg ) ); } exit: @@ -934,7 +947,7 @@ exit: /* BEGIN_CASE */ void import_rsa_made_up( int bits_arg, int keypair, int expected_status_arg ) { - int slot = 1; + psa_key_handle_t handle = 0; size_t bits = bits_arg; psa_status_t expected_status = expected_status_arg; psa_status_t status; @@ -955,10 +968,11 @@ void import_rsa_made_up( int bits_arg, int keypair, int expected_status_arg ) length = ret; /* Try importing the key */ - status = psa_import_key( slot, type, p, length ); + TEST_ASSERT( psa_allocate_key( type, bits, &handle ) == PSA_SUCCESS ); + status = psa_import_key( handle, type, p, length ); TEST_ASSERT( status == expected_status ); if( status == PSA_SUCCESS ) - TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS ); + TEST_ASSERT( psa_destroy_key( handle ) == PSA_SUCCESS ); exit: mbedtls_free( buffer ); @@ -976,8 +990,7 @@ void import_export( data_t *data, int expected_export_status_arg, int canonical_input ) { - int slot = 1; - int slot2 = slot + 1; + psa_key_handle_t handle = 0; psa_key_type_t type = type_arg; psa_algorithm_t alg = alg_arg; psa_status_t expected_export_status = expected_export_status_arg; @@ -999,23 +1012,28 @@ void import_export( data_t *data, ASSERT_ALLOC( reexported, export_size ); TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( type, expected_bits, &handle ) == + PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, usage_arg, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); + + TEST_ASSERT( psa_get_key_information( + handle, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT ); /* Import the key */ - TEST_ASSERT( psa_import_key( slot, type, + TEST_ASSERT( psa_import_key( handle, type, data->x, data->len ) == PSA_SUCCESS ); /* Test the key information */ - TEST_ASSERT( psa_get_key_information( slot, + TEST_ASSERT( psa_get_key_information( handle, &got_type, &got_bits ) == PSA_SUCCESS ); TEST_ASSERT( got_type == type ); TEST_ASSERT( got_bits == (size_t) expected_bits ); /* Export the key */ - status = psa_export_key( slot, + status = psa_export_key( handle, exported, export_size, &exported_length ); TEST_ASSERT( status == expected_export_status ); @@ -1034,32 +1052,36 @@ void import_export( data_t *data, goto destroy; } - if( ! exercise_export_key( slot, usage_arg ) ) + if( ! exercise_export_key( handle, usage_arg ) ) goto exit; if( canonical_input ) ASSERT_COMPARE( data->x, data->len, exported, exported_length ); else { - TEST_ASSERT( psa_set_key_policy( slot2, &policy ) == PSA_SUCCESS ); + psa_key_handle_t handle2; + TEST_ASSERT( psa_allocate_key( type, expected_bits, &handle2 ) == + PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle2, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( slot2, type, + TEST_ASSERT( psa_import_key( handle2, type, exported, exported_length ) == PSA_SUCCESS ); - TEST_ASSERT( psa_export_key( slot2, + TEST_ASSERT( psa_export_key( handle2, reexported, export_size, &reexported_length ) == PSA_SUCCESS ); ASSERT_COMPARE( exported, exported_length, reexported, reexported_length ); + TEST_ASSERT( psa_close_key( handle2 ) == PSA_SUCCESS ); } TEST_ASSERT( exported_length <= PSA_KEY_EXPORT_MAX_SIZE( type, got_bits ) ); destroy: /* Destroy the key */ - TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS ); + TEST_ASSERT( psa_destroy_key( handle ) == PSA_SUCCESS ); TEST_ASSERT( psa_get_key_information( - slot, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT ); + handle, NULL, NULL ) == PSA_ERROR_INVALID_HANDLE ); exit: mbedtls_free( exported ); @@ -1071,18 +1093,21 @@ exit: /* BEGIN_CASE */ void import_key_nonempty_slot( ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t type = PSA_KEY_TYPE_RAW_DATA; psa_status_t status; const uint8_t data[] = { 0x1, 0x2, 0x3, 0x4, 0x5 }; TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( type, PSA_BYTES_TO_BITS( sizeof( data ) ), + &handle ) == PSA_SUCCESS ); + /* Import the key */ - TEST_ASSERT( psa_import_key( slot, type, + TEST_ASSERT( psa_import_key( handle, type, data, sizeof( data ) ) == PSA_SUCCESS ); /* Import the key again */ - status = psa_import_key( slot, type, data, sizeof( data ) ); + status = psa_import_key( handle, type, data, sizeof( data ) ); TEST_ASSERT( status == PSA_ERROR_OCCUPIED_SLOT ); exit: @@ -1091,7 +1116,7 @@ exit: /* END_CASE */ /* BEGIN_CASE */ -void export_invalid_slot( int slot, int expected_export_status_arg ) +void export_invalid_handle( int handle, int expected_export_status_arg ) { psa_status_t status; unsigned char *exported = NULL; @@ -1102,7 +1127,7 @@ void export_invalid_slot( int slot, int expected_export_status_arg ) TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); /* Export the key */ - status = psa_export_key( slot, + status = psa_export_key( (psa_key_handle_t) handle, exported, export_size, &exported_length ); TEST_ASSERT( status == expected_export_status ); @@ -1115,7 +1140,7 @@ exit: /* BEGIN_CASE */ void export_with_no_key_activity( ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_algorithm_t alg = PSA_ALG_CTR; psa_status_t status; psa_key_policy_t policy; @@ -1125,12 +1150,14 @@ void export_with_no_key_activity( ) TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_RAW_DATA, 0, + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); /* Export the key */ - status = psa_export_key( slot, + status = psa_export_key( handle, exported, export_size, &exported_length ); TEST_ASSERT( status == PSA_ERROR_EMPTY_SLOT ); @@ -1143,7 +1170,7 @@ exit: /* BEGIN_CASE */ void cipher_with_no_key_activity( ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_status_t status; psa_key_policy_t policy; psa_cipher_operation_t operation; @@ -1151,11 +1178,13 @@ void cipher_with_no_key_activity( ) TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_RAW_DATA, 0, + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, exercise_alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - status = psa_cipher_encrypt_setup( &operation, slot, exercise_alg ); + status = psa_cipher_encrypt_setup( &operation, handle, exercise_alg ); TEST_ASSERT( status == PSA_ERROR_EMPTY_SLOT ); exit: @@ -1168,7 +1197,7 @@ exit: void export_after_import_failure( data_t *data, int type_arg, int expected_import_status_arg ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t type = type_arg; psa_status_t status; unsigned char *exported = NULL; @@ -1178,13 +1207,16 @@ void export_after_import_failure( data_t *data, int type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( type, KEY_BITS_FROM_DATA( type, data ), + &handle ) == PSA_SUCCESS ); + /* Import the key - expect failure */ - status = psa_import_key( slot, type, + status = psa_import_key( handle, type, data->x, data->len ); TEST_ASSERT( status == expected_import_status ); /* Export the key */ - status = psa_export_key( slot, + status = psa_export_key( handle, exported, export_size, &exported_length ); TEST_ASSERT( status == PSA_ERROR_EMPTY_SLOT ); @@ -1198,7 +1230,7 @@ exit: void cipher_after_import_failure( data_t *data, int type_arg, int expected_import_status_arg ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_cipher_operation_t operation; psa_key_type_t type = type_arg; psa_status_t status; @@ -1207,12 +1239,15 @@ void cipher_after_import_failure( data_t *data, int type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( type, KEY_BITS_FROM_DATA( type, data ), + &handle ) == PSA_SUCCESS ); + /* Import the key - expect failure */ - status = psa_import_key( slot, type, + status = psa_import_key( handle, type, data->x, data->len ); TEST_ASSERT( status == expected_import_status ); - status = psa_cipher_encrypt_setup( &operation, slot, exercise_alg ); + status = psa_cipher_encrypt_setup( &operation, handle, exercise_alg ); TEST_ASSERT( status == PSA_ERROR_EMPTY_SLOT ); exit: @@ -1224,7 +1259,7 @@ exit: /* BEGIN_CASE */ void export_after_destroy_key( data_t *data, int type_arg ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t type = type_arg; psa_status_t status; psa_key_policy_t policy; @@ -1235,26 +1270,28 @@ void export_after_destroy_key( data_t *data, int type_arg ) TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( type, KEY_BITS_FROM_DATA( type, data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); export_size = (ptrdiff_t) data->len; ASSERT_ALLOC( exported, export_size ); /* Import the key */ - TEST_ASSERT( psa_import_key( slot, type, + TEST_ASSERT( psa_import_key( handle, type, data->x, data->len ) == PSA_SUCCESS ); - TEST_ASSERT( psa_export_key( slot, exported, export_size, + TEST_ASSERT( psa_export_key( handle, exported, export_size, &exported_length ) == PSA_SUCCESS ); /* Destroy the key */ - TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS ); + TEST_ASSERT( psa_destroy_key( handle ) == PSA_SUCCESS ); /* Export the key */ - status = psa_export_key( slot, exported, export_size, + status = psa_export_key( handle, exported, export_size, &exported_length ); - TEST_ASSERT( status == PSA_ERROR_EMPTY_SLOT ); + TEST_ASSERT( status == PSA_ERROR_INVALID_HANDLE ); exit: mbedtls_free( exported ); @@ -1270,7 +1307,7 @@ void import_export_public_key( data_t *data, int expected_export_status_arg, data_t *expected_public_key ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t type = type_arg; psa_algorithm_t alg = alg_arg; psa_status_t expected_export_status = expected_export_status_arg; @@ -1282,17 +1319,19 @@ void import_export_public_key( data_t *data, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( type, KEY_BITS_FROM_DATA( type, data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); /* Import the key */ - TEST_ASSERT( psa_import_key( slot, type, + TEST_ASSERT( psa_import_key( handle, type, data->x, data->len ) == PSA_SUCCESS ); /* Export the public key */ ASSERT_ALLOC( exported, export_size ); - status = psa_export_public_key( slot, + status = psa_export_public_key( handle, exported, export_size, &exported_length ); TEST_ASSERT( status == expected_export_status ); @@ -1300,7 +1339,7 @@ void import_export_public_key( data_t *data, { psa_key_type_t public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR( type ); size_t bits; - TEST_ASSERT( psa_get_key_information( slot, NULL, &bits ) == + TEST_ASSERT( psa_get_key_information( handle, NULL, &bits ) == PSA_SUCCESS ); TEST_ASSERT( expected_public_key->len <= PSA_KEY_EXPORT_MAX_SIZE( public_type, bits ) ); @@ -1310,7 +1349,7 @@ void import_export_public_key( data_t *data, exit: mbedtls_free( exported ); - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -1321,7 +1360,7 @@ void import_and_exercise_key( data_t *data, int bits_arg, int alg_arg ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t type = type_arg; size_t bits = bits_arg; psa_algorithm_t alg = alg_arg; @@ -1333,27 +1372,29 @@ void import_and_exercise_key( data_t *data, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( type, KEY_BITS_FROM_DATA( type, data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, usage, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); /* Import the key */ - status = psa_import_key( slot, type, data->x, data->len ); + status = psa_import_key( handle, type, data->x, data->len ); TEST_ASSERT( status == PSA_SUCCESS ); /* Test the key information */ - TEST_ASSERT( psa_get_key_information( slot, + TEST_ASSERT( psa_get_key_information( handle, &got_type, &got_bits ) == PSA_SUCCESS ); TEST_ASSERT( got_type == type ); TEST_ASSERT( got_bits == bits ); /* Do something with the key according to its type and permitted usage. */ - if( ! exercise_key( slot, usage, alg ) ) + if( ! exercise_key( handle, usage, alg ) ) goto exit; exit: - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -1361,7 +1402,7 @@ exit: /* BEGIN_CASE */ void key_policy( int usage_arg, int alg_arg ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_algorithm_t alg = alg_arg; psa_key_usage_t usage = usage_arg; psa_key_type_t key_type = PSA_KEY_TYPE_AES; @@ -1373,25 +1414,26 @@ void key_policy( int usage_arg, int alg_arg ) TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( sizeof( key ) ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy_set ); psa_key_policy_init( &policy_get ); - psa_key_policy_set_usage( &policy_set, usage, alg ); TEST_ASSERT( psa_key_policy_get_usage( &policy_set ) == usage ); TEST_ASSERT( psa_key_policy_get_algorithm( &policy_set ) == alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy_set ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy_set ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key, sizeof( key ) ) == PSA_SUCCESS ); - TEST_ASSERT( psa_get_key_policy( key_slot, &policy_get ) == PSA_SUCCESS ); + TEST_ASSERT( psa_get_key_policy( handle, &policy_get ) == PSA_SUCCESS ); TEST_ASSERT( policy_get.usage == policy_set.usage ); TEST_ASSERT( policy_get.alg == policy_set.alg ); exit: - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -1403,7 +1445,7 @@ void mac_key_policy( int policy_usage, data_t *key_data, int exercise_alg ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_key_policy_t policy; psa_mac_operation_t operation; psa_status_t status; @@ -1411,14 +1453,17 @@ void mac_key_policy( int policy_usage, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, + KEY_BITS_FROM_DATA( key_type, key_data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, policy_usage, policy_alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - status = psa_mac_sign_setup( &operation, key_slot, exercise_alg ); + status = psa_mac_sign_setup( &operation, handle, exercise_alg ); if( policy_alg == exercise_alg && ( policy_usage & PSA_KEY_USAGE_SIGN ) != 0 ) TEST_ASSERT( status == PSA_SUCCESS ); @@ -1427,7 +1472,7 @@ void mac_key_policy( int policy_usage, psa_mac_abort( &operation ); memset( mac, 0, sizeof( mac ) ); - status = psa_mac_verify_setup( &operation, key_slot, exercise_alg ); + status = psa_mac_verify_setup( &operation, handle, exercise_alg ); if( policy_alg == exercise_alg && ( policy_usage & PSA_KEY_USAGE_VERIFY ) != 0 ) TEST_ASSERT( status == PSA_SUCCESS ); @@ -1436,7 +1481,7 @@ void mac_key_policy( int policy_usage, exit: psa_mac_abort( &operation ); - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -1448,21 +1493,24 @@ void cipher_key_policy( int policy_usage, data_t *key_data, int exercise_alg ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_key_policy_t policy; psa_cipher_operation_t operation; psa_status_t status; TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, + KEY_BITS_FROM_DATA( key_type, key_data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, policy_usage, policy_alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - status = psa_cipher_encrypt_setup( &operation, key_slot, exercise_alg ); + status = psa_cipher_encrypt_setup( &operation, handle, exercise_alg ); if( policy_alg == exercise_alg && ( policy_usage & PSA_KEY_USAGE_ENCRYPT ) != 0 ) TEST_ASSERT( status == PSA_SUCCESS ); @@ -1470,7 +1518,7 @@ void cipher_key_policy( int policy_usage, TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED ); psa_cipher_abort( &operation ); - status = psa_cipher_decrypt_setup( &operation, key_slot, exercise_alg ); + status = psa_cipher_decrypt_setup( &operation, handle, exercise_alg ); if( policy_alg == exercise_alg && ( policy_usage & PSA_KEY_USAGE_DECRYPT ) != 0 ) TEST_ASSERT( status == PSA_SUCCESS ); @@ -1479,7 +1527,7 @@ void cipher_key_policy( int policy_usage, exit: psa_cipher_abort( &operation ); - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -1493,7 +1541,7 @@ void aead_key_policy( int policy_usage, int tag_length_arg, int exercise_alg ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_key_policy_t policy; psa_status_t status; unsigned char nonce[16] = {0}; @@ -1507,14 +1555,17 @@ void aead_key_policy( int policy_usage, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, + KEY_BITS_FROM_DATA( key_type, key_data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, policy_usage, policy_alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - status = psa_aead_encrypt( key_slot, exercise_alg, + status = psa_aead_encrypt( handle, exercise_alg, nonce, nonce_length, NULL, 0, NULL, 0, @@ -1527,7 +1578,7 @@ void aead_key_policy( int policy_usage, TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED ); memset( tag, 0, sizeof( tag ) ); - status = psa_aead_decrypt( key_slot, exercise_alg, + status = psa_aead_decrypt( handle, exercise_alg, nonce, nonce_length, NULL, 0, tag, tag_length, @@ -1540,7 +1591,7 @@ void aead_key_policy( int policy_usage, TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED ); exit: - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -1552,7 +1603,7 @@ void asymmetric_encryption_key_policy( int policy_usage, data_t *key_data, int exercise_alg ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_key_policy_t policy; psa_status_t status; size_t key_bits; @@ -1562,21 +1613,24 @@ void asymmetric_encryption_key_policy( int policy_usage, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, + KEY_BITS_FROM_DATA( key_type, key_data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, policy_usage, policy_alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - TEST_ASSERT( psa_get_key_information( key_slot, + TEST_ASSERT( psa_get_key_information( handle, NULL, &key_bits ) == PSA_SUCCESS ); buffer_length = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE( key_type, key_bits, exercise_alg ); ASSERT_ALLOC( buffer, buffer_length ); - status = psa_asymmetric_encrypt( key_slot, exercise_alg, + status = psa_asymmetric_encrypt( handle, exercise_alg, NULL, 0, NULL, 0, buffer, buffer_length, @@ -1589,7 +1643,7 @@ void asymmetric_encryption_key_policy( int policy_usage, if( buffer_length != 0 ) memset( buffer, 0, buffer_length ); - status = psa_asymmetric_decrypt( key_slot, exercise_alg, + status = psa_asymmetric_decrypt( handle, exercise_alg, buffer, buffer_length, NULL, 0, buffer, buffer_length, @@ -1601,7 +1655,7 @@ void asymmetric_encryption_key_policy( int policy_usage, TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED ); exit: - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); mbedtls_free( buffer ); } @@ -1614,7 +1668,7 @@ void asymmetric_signature_key_policy( int policy_usage, data_t *key_data, int exercise_alg ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_key_policy_t policy; psa_status_t status; unsigned char payload[16] = {1}; @@ -1624,14 +1678,17 @@ void asymmetric_signature_key_policy( int policy_usage, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, + KEY_BITS_FROM_DATA( key_type, key_data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, policy_usage, policy_alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - status = psa_asymmetric_sign( key_slot, exercise_alg, + status = psa_asymmetric_sign( handle, exercise_alg, payload, payload_length, signature, sizeof( signature ), &signature_length ); @@ -1642,7 +1699,7 @@ void asymmetric_signature_key_policy( int policy_usage, TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED ); memset( signature, 0, sizeof( signature ) ); - status = psa_asymmetric_verify( key_slot, exercise_alg, + status = psa_asymmetric_verify( handle, exercise_alg, payload, payload_length, signature, sizeof( signature ) ); if( policy_alg == exercise_alg && @@ -1652,7 +1709,7 @@ void asymmetric_signature_key_policy( int policy_usage, TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED ); exit: - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -1664,21 +1721,24 @@ void derive_key_policy( int policy_usage, data_t *key_data, int exercise_alg ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_key_policy_t policy; psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; psa_status_t status; TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, + KEY_BITS_FROM_DATA( key_type, key_data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, policy_usage, policy_alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - status = psa_key_derivation( &generator, key_slot, + status = psa_key_derivation( &generator, handle, exercise_alg, NULL, 0, NULL, 0, @@ -1691,7 +1751,7 @@ void derive_key_policy( int policy_usage, exit: psa_generator_abort( &generator ); - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -1703,7 +1763,7 @@ void agreement_key_policy( int policy_usage, data_t *key_data, int exercise_alg ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_key_policy_t policy; psa_key_type_t key_type = key_type_arg; psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; @@ -1711,14 +1771,17 @@ void agreement_key_policy( int policy_usage, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, + KEY_BITS_FROM_DATA( key_type, key_data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, policy_usage, policy_alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - status = key_agreement_with_self( &generator, key_slot, exercise_alg ); + status = key_agreement_with_self( &generator, handle, exercise_alg ); if( policy_alg == exercise_alg && ( policy_usage & PSA_KEY_USAGE_DERIVE ) != 0 ) @@ -1728,7 +1791,7 @@ void agreement_key_policy( int policy_usage, exit: psa_generator_abort( &generator ); - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -1856,7 +1919,7 @@ void mac_setup( int key_type_arg, int alg_arg, int expected_status_arg ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; psa_status_t expected_status = expected_status_arg; @@ -1866,21 +1929,23 @@ void mac_setup( int key_type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY, alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key->x, key->len ) == PSA_SUCCESS ); - status = psa_mac_sign_setup( &operation, key_slot, alg ); + status = psa_mac_sign_setup( &operation, handle, alg ); psa_mac_abort( &operation ); TEST_ASSERT( status == expected_status ); exit: - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -1892,7 +1957,7 @@ void mac_sign( int key_type_arg, data_t *input, data_t *expected_mac ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; psa_mac_operation_t operation; @@ -1911,16 +1976,18 @@ void mac_sign( int key_type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_SIGN, alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key->x, key->len ) == PSA_SUCCESS ); /* Calculate the MAC. */ TEST_ASSERT( psa_mac_sign_setup( &operation, - key_slot, alg ) == PSA_SUCCESS ); + handle, alg ) == PSA_SUCCESS ); TEST_ASSERT( psa_mac_update( &operation, input->x, input->len ) == PSA_SUCCESS ); TEST_ASSERT( psa_mac_sign_finish( &operation, @@ -1936,7 +2003,7 @@ void mac_sign( int key_type_arg, sizeof( actual_mac ) - mac_length ) ); exit: - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -1948,7 +2015,7 @@ void mac_verify( int key_type_arg, data_t *input, data_t *expected_mac ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; psa_mac_operation_t operation; @@ -1965,16 +2032,18 @@ void mac_verify( int key_type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_VERIFY, alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key->x, key->len ) == PSA_SUCCESS ); TEST_ASSERT( psa_mac_verify_setup( &operation, - key_slot, alg ) == PSA_SUCCESS ); - TEST_ASSERT( psa_destroy_key( key_slot ) == PSA_SUCCESS ); + handle, alg ) == PSA_SUCCESS ); + TEST_ASSERT( psa_destroy_key( handle ) == PSA_SUCCESS ); TEST_ASSERT( psa_mac_update( &operation, input->x, input->len ) == PSA_SUCCESS ); TEST_ASSERT( psa_mac_verify_finish( &operation, @@ -1982,7 +2051,7 @@ void mac_verify( int key_type_arg, expected_mac->len ) == PSA_SUCCESS ); exit: - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -1993,7 +2062,7 @@ void cipher_setup( int key_type_arg, int alg_arg, int expected_status_arg ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; psa_status_t expected_status = expected_status_arg; @@ -2003,19 +2072,21 @@ void cipher_setup( int key_type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key->x, key->len ) == PSA_SUCCESS ); - status = psa_cipher_encrypt_setup( &operation, key_slot, alg ); + status = psa_cipher_encrypt_setup( &operation, handle, alg ); psa_cipher_abort( &operation ); TEST_ASSERT( status == expected_status ); exit: - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -2026,7 +2097,7 @@ void cipher_encrypt( int alg_arg, int key_type_arg, data_t *input, data_t *expected_output, int expected_status_arg ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_status_t status; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; @@ -2052,15 +2123,17 @@ void cipher_encrypt( int alg_arg, int key_type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key->x, key->len ) == PSA_SUCCESS ); TEST_ASSERT( psa_cipher_encrypt_setup( &operation, - key_slot, alg ) == PSA_SUCCESS ); + handle, alg ) == PSA_SUCCESS ); TEST_ASSERT( psa_cipher_set_iv( &operation, iv, iv_size ) == PSA_SUCCESS ); @@ -2089,7 +2162,7 @@ void cipher_encrypt( int alg_arg, int key_type_arg, exit: mbedtls_free( output ); - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -2101,7 +2174,7 @@ void cipher_encrypt_multipart( int alg_arg, int key_type_arg, int first_part_size, data_t *expected_output ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; unsigned char iv[16] = {0}; @@ -2125,15 +2198,17 @@ void cipher_encrypt_multipart( int alg_arg, int key_type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key->x, key->len ) == PSA_SUCCESS ); TEST_ASSERT( psa_cipher_encrypt_setup( &operation, - key_slot, alg ) == PSA_SUCCESS ); + handle, alg ) == PSA_SUCCESS ); TEST_ASSERT( psa_cipher_set_iv( &operation, iv, sizeof( iv ) ) == PSA_SUCCESS ); @@ -2164,7 +2239,7 @@ void cipher_encrypt_multipart( int alg_arg, int key_type_arg, exit: mbedtls_free( output ); - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -2176,7 +2251,7 @@ void cipher_decrypt_multipart( int alg_arg, int key_type_arg, int first_part_size, data_t *expected_output ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; @@ -2201,15 +2276,17 @@ void cipher_decrypt_multipart( int alg_arg, int key_type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT, alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key->x, key->len ) == PSA_SUCCESS ); TEST_ASSERT( psa_cipher_decrypt_setup( &operation, - key_slot, alg ) == PSA_SUCCESS ); + handle, alg ) == PSA_SUCCESS ); TEST_ASSERT( psa_cipher_set_iv( &operation, iv, sizeof( iv ) ) == PSA_SUCCESS ); @@ -2242,7 +2319,7 @@ void cipher_decrypt_multipart( int alg_arg, int key_type_arg, exit: mbedtls_free( output ); - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -2253,7 +2330,7 @@ void cipher_decrypt( int alg_arg, int key_type_arg, data_t *input, data_t *expected_output, int expected_status_arg ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_status_t status; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; @@ -2279,15 +2356,17 @@ void cipher_decrypt( int alg_arg, int key_type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT, alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key->x, key->len ) == PSA_SUCCESS ); TEST_ASSERT( psa_cipher_decrypt_setup( &operation, - key_slot, alg ) == PSA_SUCCESS ); + handle, alg ) == PSA_SUCCESS ); TEST_ASSERT( psa_cipher_set_iv( &operation, iv, iv_size ) == PSA_SUCCESS ); @@ -2317,7 +2396,7 @@ void cipher_decrypt( int alg_arg, int key_type_arg, exit: mbedtls_free( output ); - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -2327,7 +2406,7 @@ void cipher_verify_output( int alg_arg, int key_type_arg, data_t *key, data_t *input ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; unsigned char iv[16] = {0}; @@ -2351,17 +2430,19 @@ void cipher_verify_output( int alg_arg, int key_type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT, alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key->x, key->len ) == PSA_SUCCESS ); TEST_ASSERT( psa_cipher_encrypt_setup( &operation1, - key_slot, alg ) == PSA_SUCCESS ); + handle, alg ) == PSA_SUCCESS ); TEST_ASSERT( psa_cipher_decrypt_setup( &operation2, - key_slot, alg ) == PSA_SUCCESS ); + handle, alg ) == PSA_SUCCESS ); TEST_ASSERT( psa_cipher_generate_iv( &operation1, iv, iv_size, @@ -2404,7 +2485,7 @@ void cipher_verify_output( int alg_arg, int key_type_arg, exit: mbedtls_free( output1 ); mbedtls_free( output2 ); - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -2416,7 +2497,7 @@ void cipher_verify_output_multipart( int alg_arg, data_t *input, int first_part_size ) { - int key_slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; unsigned char iv[16] = {0}; @@ -2440,17 +2521,19 @@ void cipher_verify_output_multipart( int alg_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT, alg ); - TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( key_slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key->x, key->len ) == PSA_SUCCESS ); TEST_ASSERT( psa_cipher_encrypt_setup( &operation1, - key_slot, alg ) == PSA_SUCCESS ); + handle, alg ) == PSA_SUCCESS ); TEST_ASSERT( psa_cipher_decrypt_setup( &operation2, - key_slot, alg ) == PSA_SUCCESS ); + handle, alg ) == PSA_SUCCESS ); TEST_ASSERT( psa_cipher_generate_iv( &operation1, iv, iv_size, @@ -2512,7 +2595,7 @@ void cipher_verify_output_multipart( int alg_arg, exit: mbedtls_free( output1 ); mbedtls_free( output2 ); - psa_destroy_key( key_slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -2525,7 +2608,7 @@ void aead_encrypt_decrypt( int key_type_arg, data_t *key_data, data_t *input_data, int expected_result_arg ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; unsigned char *output_data = NULL; @@ -2551,16 +2634,18 @@ void aead_encrypt_decrypt( int key_type_arg, data_t *key_data, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key_data->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - TEST_ASSERT( psa_aead_encrypt( slot, alg, + TEST_ASSERT( psa_aead_encrypt( handle, alg, nonce->x, nonce->len, additional_data->x, additional_data->len, @@ -2572,7 +2657,7 @@ void aead_encrypt_decrypt( int key_type_arg, data_t *key_data, { ASSERT_ALLOC( output_data2, output_length ); - TEST_ASSERT( psa_aead_decrypt( slot, alg, + TEST_ASSERT( psa_aead_decrypt( handle, alg, nonce->x, nonce->len, additional_data->x, additional_data->len, @@ -2585,7 +2670,7 @@ void aead_encrypt_decrypt( int key_type_arg, data_t *key_data, } exit: - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_free( output_data ); mbedtls_free( output_data2 ); mbedtls_psa_crypto_free( ); @@ -2600,7 +2685,7 @@ void aead_encrypt( int key_type_arg, data_t *key_data, data_t *input_data, data_t *expected_result ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; unsigned char *output_data = NULL; @@ -2625,15 +2710,17 @@ void aead_encrypt( int key_type_arg, data_t *key_data, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key_data->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT , alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - TEST_ASSERT( psa_aead_encrypt( slot, alg, + TEST_ASSERT( psa_aead_encrypt( handle, alg, nonce->x, nonce->len, additional_data->x, additional_data->len, input_data->x, input_data->len, @@ -2644,7 +2731,7 @@ void aead_encrypt( int key_type_arg, data_t *key_data, output_data, output_length ); exit: - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_free( output_data ); mbedtls_psa_crypto_free( ); } @@ -2659,7 +2746,7 @@ void aead_decrypt( int key_type_arg, data_t *key_data, data_t *expected_data, int expected_result_arg ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; unsigned char *output_data = NULL; @@ -2685,15 +2772,17 @@ void aead_decrypt( int key_type_arg, data_t *key_data, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key_data->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT , alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - TEST_ASSERT( psa_aead_decrypt( slot, alg, + TEST_ASSERT( psa_aead_decrypt( handle, alg, nonce->x, nonce->len, additional_data->x, additional_data->len, @@ -2706,7 +2795,7 @@ void aead_decrypt( int key_type_arg, data_t *key_data, output_data, output_length ); exit: - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_free( output_data ); mbedtls_psa_crypto_free( ); } @@ -2732,7 +2821,7 @@ void sign_deterministic( int key_type_arg, data_t *key_data, int alg_arg, data_t *input_data, data_t *output_data ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; size_t key_bits; @@ -2750,14 +2839,17 @@ void sign_deterministic( int key_type_arg, data_t *key_data, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, + KEY_BITS_FROM_DATA( key_type, key_data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_SIGN, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - TEST_ASSERT( psa_get_key_information( slot, + TEST_ASSERT( psa_get_key_information( handle, NULL, &key_bits ) == PSA_SUCCESS ); @@ -2770,7 +2862,7 @@ void sign_deterministic( int key_type_arg, data_t *key_data, ASSERT_ALLOC( signature, signature_size ); /* Perform the signature. */ - TEST_ASSERT( psa_asymmetric_sign( slot, alg, + TEST_ASSERT( psa_asymmetric_sign( handle, alg, input_data->x, input_data->len, signature, signature_size, &signature_length ) == PSA_SUCCESS ); @@ -2779,7 +2871,7 @@ void sign_deterministic( int key_type_arg, data_t *key_data, signature, signature_length ); exit: - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_free( signature ); mbedtls_psa_crypto_free( ); } @@ -2790,7 +2882,7 @@ void sign_fail( int key_type_arg, data_t *key_data, int alg_arg, data_t *input_data, int signature_size_arg, int expected_status_arg ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; size_t signature_size = signature_size_arg; @@ -2809,15 +2901,18 @@ void sign_fail( int key_type_arg, data_t *key_data, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, + KEY_BITS_FROM_DATA( key_type, key_data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_SIGN, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - actual_status = psa_asymmetric_sign( slot, alg, + actual_status = psa_asymmetric_sign( handle, alg, input_data->x, input_data->len, signature, signature_size, &signature_length ); @@ -2829,7 +2924,7 @@ void sign_fail( int key_type_arg, data_t *key_data, TEST_ASSERT( signature_length <= signature_size ); exit: - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_free( signature ); mbedtls_psa_crypto_free( ); } @@ -2839,7 +2934,7 @@ exit: void sign_verify( int key_type_arg, data_t *key_data, int alg_arg, data_t *input_data ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; size_t key_bits; @@ -2850,16 +2945,19 @@ void sign_verify( int key_type_arg, data_t *key_data, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, + KEY_BITS_FROM_DATA( key_type, key_data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - TEST_ASSERT( psa_get_key_information( slot, + TEST_ASSERT( psa_get_key_information( handle, NULL, &key_bits ) == PSA_SUCCESS ); @@ -2872,7 +2970,7 @@ void sign_verify( int key_type_arg, data_t *key_data, ASSERT_ALLOC( signature, signature_size ); /* Perform the signature. */ - TEST_ASSERT( psa_asymmetric_sign( slot, alg, + TEST_ASSERT( psa_asymmetric_sign( handle, alg, input_data->x, input_data->len, signature, signature_size, &signature_length ) == PSA_SUCCESS ); @@ -2882,7 +2980,7 @@ void sign_verify( int key_type_arg, data_t *key_data, /* Use the library to verify that the signature is correct. */ TEST_ASSERT( psa_asymmetric_verify( - slot, alg, + handle, alg, input_data->x, input_data->len, signature, signature_length ) == PSA_SUCCESS ); @@ -2893,14 +2991,14 @@ void sign_verify( int key_type_arg, data_t *key_data, * because ECDSA may ignore the last few bits of the input. */ input_data->x[0] ^= 1; TEST_ASSERT( psa_asymmetric_verify( - slot, alg, + handle, alg, input_data->x, input_data->len, signature, signature_length ) == PSA_ERROR_INVALID_SIGNATURE ); } exit: - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_free( signature ); mbedtls_psa_crypto_free( ); } @@ -2911,7 +3009,7 @@ void asymmetric_verify( int key_type_arg, data_t *key_data, int alg_arg, data_t *hash_data, data_t *signature_data ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; psa_key_policy_t policy; @@ -2927,20 +3025,23 @@ void asymmetric_verify( int key_type_arg, data_t *key_data, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, + KEY_BITS_FROM_DATA( key_type, key_data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_VERIFY, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - TEST_ASSERT( psa_asymmetric_verify( slot, alg, + TEST_ASSERT( psa_asymmetric_verify( handle, alg, hash_data->x, hash_data->len, signature_data->x, signature_data->len ) == PSA_SUCCESS ); exit: - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -2951,7 +3052,7 @@ void asymmetric_verify_fail( int key_type_arg, data_t *key_data, data_t *signature_data, int expected_status_arg ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; psa_status_t actual_status; @@ -2967,15 +3068,18 @@ void asymmetric_verify_fail( int key_type_arg, data_t *key_data, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, + KEY_BITS_FROM_DATA( key_type, key_data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_VERIFY, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - actual_status = psa_asymmetric_verify( slot, alg, + actual_status = psa_asymmetric_verify( handle, alg, hash_data->x, hash_data->len, signature_data->x, signature_data->len ); @@ -2983,7 +3087,7 @@ void asymmetric_verify_fail( int key_type_arg, data_t *key_data, TEST_ASSERT( actual_status == expected_status ); exit: - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -2997,7 +3101,7 @@ void asymmetric_encrypt( int key_type_arg, int expected_output_length_arg, int expected_status_arg ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; size_t expected_output_length = expected_output_length_arg; @@ -3011,23 +3115,27 @@ void asymmetric_encrypt( int key_type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + /* Import the key */ + TEST_ASSERT( psa_allocate_key( key_type, + KEY_BITS_FROM_DATA( key_type, key_data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( slot, key_type, + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); /* Determine the maximum output length */ - TEST_ASSERT( psa_get_key_information( slot, + TEST_ASSERT( psa_get_key_information( handle, NULL, &key_bits ) == PSA_SUCCESS ); output_size = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE( key_type, key_bits, alg ); ASSERT_ALLOC( output, output_size ); /* Encrypt the input */ - actual_status = psa_asymmetric_encrypt( slot, alg, + actual_status = psa_asymmetric_encrypt( handle, alg, input_data->x, input_data->len, label->x, label->len, output, output_size, @@ -3042,7 +3150,7 @@ void asymmetric_encrypt( int key_type_arg, output_length = ~0; if( output_size != 0 ) memset( output, 0, output_size ); - actual_status = psa_asymmetric_encrypt( slot, alg, + actual_status = psa_asymmetric_encrypt( handle, alg, input_data->x, input_data->len, NULL, label->len, output, output_size, @@ -3052,7 +3160,7 @@ void asymmetric_encrypt( int key_type_arg, } exit: - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_free( output ); mbedtls_psa_crypto_free( ); } @@ -3065,7 +3173,7 @@ void asymmetric_encrypt_decrypt( int key_type_arg, data_t *input_data, data_t *label ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; size_t key_bits; @@ -3084,19 +3192,22 @@ void asymmetric_encrypt_decrypt( int key_type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, + KEY_BITS_FROM_DATA( key_type, key_data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); /* Determine the maximum ciphertext length */ - TEST_ASSERT( psa_get_key_information( slot, + TEST_ASSERT( psa_get_key_information( handle, NULL, &key_bits ) == PSA_SUCCESS ); output_size = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE( key_type, key_bits, alg ); @@ -3107,7 +3218,7 @@ void asymmetric_encrypt_decrypt( int key_type_arg, /* We test encryption by checking that encrypt-then-decrypt gives back * the original plaintext because of the non-optional random * part of encryption process which prevents using fixed vectors. */ - TEST_ASSERT( psa_asymmetric_encrypt( slot, alg, + TEST_ASSERT( psa_asymmetric_encrypt( handle, alg, input_data->x, input_data->len, label->x, label->len, output, output_size, @@ -3116,7 +3227,7 @@ void asymmetric_encrypt_decrypt( int key_type_arg, * it looks sensible. */ TEST_ASSERT( output_length <= output_size ); - TEST_ASSERT( psa_asymmetric_decrypt( slot, alg, + TEST_ASSERT( psa_asymmetric_decrypt( handle, alg, output, output_length, label->x, label->len, output2, output2_size, @@ -3125,7 +3236,7 @@ void asymmetric_encrypt_decrypt( int key_type_arg, output2, output2_length ); exit: - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_free( output ); mbedtls_free( output2 ); mbedtls_psa_crypto_free( ); @@ -3140,7 +3251,7 @@ void asymmetric_decrypt( int key_type_arg, data_t *label, data_t *expected_data ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; unsigned char *output = NULL; @@ -3160,15 +3271,18 @@ void asymmetric_decrypt( int key_type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, + KEY_BITS_FROM_DATA( key_type, key_data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - TEST_ASSERT( psa_asymmetric_decrypt( slot, alg, + TEST_ASSERT( psa_asymmetric_decrypt( handle, alg, input_data->x, input_data->len, label->x, label->len, output, @@ -3184,7 +3298,7 @@ void asymmetric_decrypt( int key_type_arg, output_length = ~0; if( output_size != 0 ) memset( output, 0, output_size ); - TEST_ASSERT( psa_asymmetric_decrypt( slot, alg, + TEST_ASSERT( psa_asymmetric_decrypt( handle, alg, input_data->x, input_data->len, NULL, label->len, output, @@ -3195,7 +3309,7 @@ void asymmetric_decrypt( int key_type_arg, } exit: - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_free( output ); mbedtls_psa_crypto_free( ); } @@ -3209,7 +3323,7 @@ void asymmetric_decrypt_fail( int key_type_arg, data_t *label, int expected_status_arg ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; unsigned char *output = NULL; @@ -3229,15 +3343,18 @@ void asymmetric_decrypt_fail( int key_type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, + KEY_BITS_FROM_DATA( key_type, key_data ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - actual_status = psa_asymmetric_decrypt( slot, alg, + actual_status = psa_asymmetric_decrypt( handle, alg, input_data->x, input_data->len, label->x, label->len, output, output_size, @@ -3252,7 +3369,7 @@ void asymmetric_decrypt_fail( int key_type_arg, output_length = ~0; if( output_size != 0 ) memset( output, 0, output_size ); - actual_status = psa_asymmetric_decrypt( slot, alg, + actual_status = psa_asymmetric_decrypt( handle, alg, input_data->x, input_data->len, NULL, label->len, output, output_size, @@ -3262,7 +3379,7 @@ void asymmetric_decrypt_fail( int key_type_arg, } exit: - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_free( output ); mbedtls_psa_crypto_free( ); } @@ -3277,7 +3394,7 @@ void derive_setup( int key_type_arg, int requested_capacity_arg, int expected_status_arg ) { - psa_key_slot_t slot = 1; + psa_key_handle_t handle = 0; size_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; size_t requested_capacity = requested_capacity_arg; @@ -3287,22 +3404,24 @@ void derive_setup( int key_type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key_data->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( slot, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - TEST_ASSERT( psa_key_derivation( &generator, slot, alg, + TEST_ASSERT( psa_key_derivation( &generator, handle, alg, salt->x, salt->len, label->x, label->len, requested_capacity ) == expected_status ); exit: psa_generator_abort( &generator ); - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -3310,7 +3429,7 @@ exit: /* BEGIN_CASE */ void test_derive_invalid_generator_state( ) { - psa_key_slot_t base_key = 1; + psa_key_handle_t handle = 0; size_t key_type = PSA_KEY_TYPE_DERIVE; psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; psa_algorithm_t alg = PSA_ALG_HKDF( PSA_ALG_SHA_256 ); @@ -3323,22 +3442,25 @@ void test_derive_invalid_generator_state( ) TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( key_type, + PSA_BYTES_TO_BITS( sizeof( key_data ) ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg ); - TEST_ASSERT( psa_set_key_policy( base_key, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( base_key, key_type, + TEST_ASSERT( psa_import_key( handle, key_type, key_data, sizeof( key_data ) ) == PSA_SUCCESS ); /* valid key derivation */ - TEST_ASSERT( psa_key_derivation( &generator, base_key, alg, + TEST_ASSERT( psa_key_derivation( &generator, handle, alg, NULL, 0, NULL, 0, capacity ) == PSA_SUCCESS ); /* state of generator shouldn't allow additional generation */ - TEST_ASSERT( psa_key_derivation( &generator, base_key, alg, + TEST_ASSERT( psa_key_derivation( &generator, handle, alg, NULL, 0, NULL, 0, capacity ) == PSA_ERROR_BAD_STATE ); @@ -3352,7 +3474,7 @@ void test_derive_invalid_generator_state( ) exit: psa_generator_abort( &generator ); - psa_destroy_key( base_key ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -3394,7 +3516,7 @@ void derive_output( int alg_arg, data_t *expected_output1, data_t *expected_output2 ) { - psa_key_slot_t slot = 1; + psa_key_handle_t handle = 0; psa_algorithm_t alg = alg_arg; size_t requested_capacity = requested_capacity_arg; psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; @@ -3420,16 +3542,19 @@ void derive_output( int alg_arg, ASSERT_ALLOC( output_buffer, output_buffer_size ); TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_DERIVE, + PSA_BYTES_TO_BITS( key_data->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( slot, PSA_KEY_TYPE_DERIVE, + TEST_ASSERT( psa_import_key( handle, PSA_KEY_TYPE_DERIVE, key_data->x, key_data->len ) == PSA_SUCCESS ); /* Extraction phase. */ - TEST_ASSERT( psa_key_derivation( &generator, slot, alg, + TEST_ASSERT( psa_key_derivation( &generator, handle, alg, salt->x, salt->len, label->x, label->len, requested_capacity ) == PSA_SUCCESS ); @@ -3477,7 +3602,7 @@ void derive_output( int alg_arg, exit: mbedtls_free( output_buffer ); psa_generator_abort( &generator ); - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -3489,7 +3614,7 @@ void derive_full( int alg_arg, data_t *label, int requested_capacity_arg ) { - psa_key_slot_t slot = 1; + psa_key_handle_t handle = 0; psa_algorithm_t alg = alg_arg; size_t requested_capacity = requested_capacity_arg; psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; @@ -3500,16 +3625,19 @@ void derive_full( int alg_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_DERIVE, + PSA_BYTES_TO_BITS( key_data->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( slot, PSA_KEY_TYPE_DERIVE, + TEST_ASSERT( psa_import_key( handle, PSA_KEY_TYPE_DERIVE, key_data->x, key_data->len ) == PSA_SUCCESS ); /* Extraction phase. */ - TEST_ASSERT( psa_key_derivation( &generator, slot, alg, + TEST_ASSERT( psa_key_derivation( &generator, handle, alg, salt->x, salt->len, label->x, label->len, requested_capacity ) == PSA_SUCCESS ); @@ -3543,7 +3671,7 @@ void derive_full( int alg_arg, exit: psa_generator_abort( &generator ); - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -3558,8 +3686,8 @@ void derive_key_exercise( int alg_arg, int derived_usage_arg, int derived_alg_arg ) { - psa_key_slot_t base_key = 1; - psa_key_slot_t derived_key = 2; + psa_key_handle_t base_handle = 0; + psa_key_handle_t derived_handle = 0; psa_algorithm_t alg = alg_arg; psa_key_type_t derived_type = derived_type_arg; size_t derived_bits = derived_bits_arg; @@ -3573,40 +3701,45 @@ void derive_key_exercise( int alg_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_DERIVE, + PSA_BYTES_TO_BITS( key_data->len ), + &base_handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg ); - TEST_ASSERT( psa_set_key_policy( base_key, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( base_key, PSA_KEY_TYPE_DERIVE, + TEST_ASSERT( psa_set_key_policy( base_handle, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_import_key( base_handle, PSA_KEY_TYPE_DERIVE, key_data->x, key_data->len ) == PSA_SUCCESS ); /* Derive a key. */ - TEST_ASSERT( psa_key_derivation( &generator, base_key, alg, + TEST_ASSERT( psa_key_derivation( &generator, base_handle, alg, salt->x, salt->len, label->x, label->len, capacity ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( derived_type, derived_bits, + &derived_handle ) == PSA_SUCCESS ); psa_key_policy_set_usage( &policy, derived_usage, derived_alg ); - TEST_ASSERT( psa_set_key_policy( derived_key, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_generator_import_key( derived_key, + TEST_ASSERT( psa_set_key_policy( derived_handle, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_generator_import_key( derived_handle, derived_type, derived_bits, &generator ) == PSA_SUCCESS ); /* Test the key information */ - TEST_ASSERT( psa_get_key_information( derived_key, + TEST_ASSERT( psa_get_key_information( derived_handle, &got_type, &got_bits ) == PSA_SUCCESS ); TEST_ASSERT( got_type == derived_type ); TEST_ASSERT( got_bits == derived_bits ); /* Exercise the derived key. */ - if( ! exercise_key( derived_key, derived_usage, derived_alg ) ) + if( ! exercise_key( derived_handle, derived_usage, derived_alg ) ) goto exit; exit: psa_generator_abort( &generator ); - psa_destroy_key( base_key ); - psa_destroy_key( derived_key ); + psa_destroy_key( base_handle ); + psa_destroy_key( derived_handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -3619,10 +3752,11 @@ void derive_key_export( int alg_arg, int bytes1_arg, int bytes2_arg ) { - psa_key_slot_t base_key = 1; - psa_key_slot_t derived_key = 2; + psa_key_handle_t base_handle = 0; + psa_key_handle_t derived_handle = 0; psa_algorithm_t alg = alg_arg; size_t bytes1 = bytes1_arg; + size_t derived_bits = PSA_BYTES_TO_BITS( bytes1 ); size_t bytes2 = bytes2_arg; size_t capacity = bytes1 + bytes2; psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; @@ -3635,15 +3769,18 @@ void derive_key_export( int alg_arg, ASSERT_ALLOC( export_buffer, capacity ); TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_DERIVE, + PSA_BYTES_TO_BITS( key_data->len ), + &base_handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg ); - TEST_ASSERT( psa_set_key_policy( base_key, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( base_key, PSA_KEY_TYPE_DERIVE, + TEST_ASSERT( psa_set_key_policy( base_handle, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_import_key( base_handle, PSA_KEY_TYPE_DERIVE, key_data->x, key_data->len ) == PSA_SUCCESS ); /* Derive some material and output it. */ - TEST_ASSERT( psa_key_derivation( &generator, base_key, alg, + TEST_ASSERT( psa_key_derivation( &generator, base_handle, alg, salt->x, salt->len, label->x, label->len, capacity ) == PSA_SUCCESS ); @@ -3653,27 +3790,32 @@ void derive_key_export( int alg_arg, TEST_ASSERT( psa_generator_abort( &generator ) == PSA_SUCCESS ); /* Derive the same output again, but this time store it in key objects. */ - TEST_ASSERT( psa_key_derivation( &generator, base_key, alg, + TEST_ASSERT( psa_key_derivation( &generator, base_handle, alg, salt->x, salt->len, label->x, label->len, capacity ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_RAW_DATA, derived_bits, + &derived_handle ) == PSA_SUCCESS ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, 0 ); - TEST_ASSERT( psa_set_key_policy( derived_key, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_generator_import_key( derived_key, + TEST_ASSERT( psa_set_key_policy( derived_handle, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_generator_import_key( derived_handle, PSA_KEY_TYPE_RAW_DATA, - PSA_BYTES_TO_BITS( bytes1 ), + derived_bits, &generator ) == PSA_SUCCESS ); - TEST_ASSERT( psa_export_key( derived_key, + TEST_ASSERT( psa_export_key( derived_handle, export_buffer, bytes1, &length ) == PSA_SUCCESS ); TEST_ASSERT( length == bytes1 ); - TEST_ASSERT( psa_destroy_key( derived_key ) == PSA_SUCCESS ); - TEST_ASSERT( psa_set_key_policy( derived_key, &policy ) == PSA_SUCCESS ); - TEST_ASSERT( psa_generator_import_key( derived_key, + TEST_ASSERT( psa_destroy_key( derived_handle ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_RAW_DATA, + PSA_BYTES_TO_BITS( bytes2 ), + &derived_handle ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( derived_handle, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_generator_import_key( derived_handle, PSA_KEY_TYPE_RAW_DATA, PSA_BYTES_TO_BITS( bytes2 ), &generator ) == PSA_SUCCESS ); - TEST_ASSERT( psa_export_key( derived_key, + TEST_ASSERT( psa_export_key( derived_handle, export_buffer + bytes1, bytes2, &length ) == PSA_SUCCESS ); TEST_ASSERT( length == bytes2 ); @@ -3685,8 +3827,8 @@ exit: mbedtls_free( output_buffer ); mbedtls_free( export_buffer ); psa_generator_abort( &generator ); - psa_destroy_key( base_key ); - psa_destroy_key( derived_key ); + psa_destroy_key( base_handle ); + psa_destroy_key( derived_handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -3697,7 +3839,7 @@ void key_agreement_setup( int alg_arg, data_t *peer_key_data, int expected_status_arg ) { - psa_key_slot_t our_key = 1; + psa_key_handle_t our_key = 0; psa_algorithm_t alg = alg_arg; psa_key_type_t our_key_type = our_key_type_arg; psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; @@ -3705,6 +3847,10 @@ void key_agreement_setup( int alg_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( our_key_type, + KEY_BITS_FROM_DATA( our_key_type, + our_key_data ), + &our_key ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg ); TEST_ASSERT( psa_set_key_policy( our_key, &policy ) == PSA_SUCCESS ); @@ -3730,7 +3876,7 @@ void key_agreement_capacity( int alg_arg, data_t *peer_key_data, int expected_capacity_arg ) { - psa_key_slot_t our_key = 1; + psa_key_handle_t our_key = 0; psa_algorithm_t alg = alg_arg; psa_key_type_t our_key_type = our_key_type_arg; psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; @@ -3740,6 +3886,10 @@ void key_agreement_capacity( int alg_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( our_key_type, + KEY_BITS_FROM_DATA( our_key_type, + our_key_data ), + &our_key ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg ); TEST_ASSERT( psa_set_key_policy( our_key, &policy ) == PSA_SUCCESS ); @@ -3784,7 +3934,7 @@ void key_agreement_output( int alg_arg, data_t *peer_key_data, data_t *expected_output1, data_t *expected_output2 ) { - psa_key_slot_t our_key = 1; + psa_key_handle_t our_key = 0; psa_algorithm_t alg = alg_arg; psa_key_type_t our_key_type = our_key_type_arg; psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; @@ -3796,6 +3946,10 @@ void key_agreement_output( int alg_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( our_key_type, + KEY_BITS_FROM_DATA( our_key_type, + our_key_data ), + &our_key ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg ); TEST_ASSERT( psa_set_key_policy( our_key, &policy ) == PSA_SUCCESS ); @@ -3889,7 +4043,7 @@ void generate_key( int type_arg, int alg_arg, int expected_status_arg ) { - int slot = 1; + psa_key_handle_t handle = 0; psa_key_type_t type = type_arg; psa_key_usage_t usage = usage_arg; size_t bits = bits_arg; @@ -3903,16 +4057,17 @@ void generate_key( int type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); + TEST_ASSERT( psa_allocate_key( type, bits, &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, usage, alg ); - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); /* Generate a key */ - TEST_ASSERT( psa_generate_key( slot, type, bits, + TEST_ASSERT( psa_generate_key( handle, type, bits, NULL, 0 ) == expected_status ); /* Test the key information */ - TEST_ASSERT( psa_get_key_information( slot, + TEST_ASSERT( psa_get_key_information( handle, &got_type, &got_bits ) == expected_info_status ); if( expected_info_status != PSA_SUCCESS ) @@ -3921,11 +4076,11 @@ void generate_key( int type_arg, TEST_ASSERT( got_bits == bits ); /* Do something with the key according to its type and permitted usage. */ - if( ! exercise_key( slot, usage, alg ) ) + if( ! exercise_key( handle, usage, alg ) ) goto exit; exit: - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -3936,8 +4091,8 @@ void persistent_key_load_key_from_storage( data_t *data, int type_arg, int alg_arg, int generation_method, int export_status ) { - psa_key_slot_t slot = 1; - psa_key_slot_t base_key = 2; + psa_key_handle_t handle = 0; + psa_key_handle_t base_key; psa_key_type_t type = (psa_key_type_t) type_arg; psa_key_type_t type_get; size_t bits_get; @@ -3959,33 +4114,34 @@ void persistent_key_load_key_from_storage( data_t *data, int type_arg, TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS ); - TEST_ASSERT( psa_set_key_lifetime( - slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS ); - + TEST_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, 1, + type, bits, + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy_set ); - psa_key_policy_set_usage( &policy_set, policy_usage, policy_alg ); + TEST_ASSERT( psa_set_key_policy( handle, &policy_set ) == PSA_SUCCESS ); - TEST_ASSERT( psa_set_key_policy( slot, &policy_set ) == PSA_SUCCESS ); switch( generation_method ) { case IMPORT_KEY: /* Import the key */ - TEST_ASSERT( psa_import_key( slot, type, + TEST_ASSERT( psa_import_key( handle, type, data->x, data->len ) == PSA_SUCCESS ); break; case GENERATE_KEY: /* Generate a key */ - TEST_ASSERT( psa_generate_key( slot, type, bits, + TEST_ASSERT( psa_generate_key( handle, type, bits, NULL, 0 ) == PSA_SUCCESS ); break; case DERIVE_KEY: /* Create base key */ + TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_DERIVE, + PSA_BYTES_TO_BITS( data->len ), + &base_key ) == PSA_SUCCESS ); psa_key_policy_init( &base_policy_set ); - psa_key_policy_set_usage( &base_policy_set, PSA_KEY_USAGE_DERIVE, base_policy_alg ); TEST_ASSERT( psa_set_key_policy( @@ -3998,38 +4154,35 @@ void persistent_key_load_key_from_storage( data_t *data, int type_arg, NULL, 0, NULL, 0, export_size ) == PSA_SUCCESS ); TEST_ASSERT( psa_generator_import_key( - slot, PSA_KEY_TYPE_RAW_DATA, + handle, PSA_KEY_TYPE_RAW_DATA, bits, &generator ) == PSA_SUCCESS ); break; } /* Export the key */ - TEST_ASSERT( psa_export_key( slot, first_export, export_size, + TEST_ASSERT( psa_export_key( handle, first_export, export_size, &first_exported_length ) == export_status ); /* Shutdown and restart */ mbedtls_psa_crypto_free(); - TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS ); - /* Mark slot as persistent again */ - TEST_ASSERT( psa_set_key_lifetime( - slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS ); - /* Check key slot still contains key data */ + TEST_ASSERT( psa_open_key( PSA_KEY_LIFETIME_PERSISTENT, 1, + &handle ) == PSA_SUCCESS ); TEST_ASSERT( psa_get_key_information( - slot, &type_get, &bits_get ) == PSA_SUCCESS ); + handle, &type_get, &bits_get ) == PSA_SUCCESS ); TEST_ASSERT( type_get == type ); TEST_ASSERT( bits_get == (size_t) bits ); - TEST_ASSERT( psa_get_key_policy( slot, &policy_get ) == PSA_SUCCESS ); + TEST_ASSERT( psa_get_key_policy( handle, &policy_get ) == PSA_SUCCESS ); TEST_ASSERT( psa_key_policy_get_usage( &policy_get ) == policy_usage ); TEST_ASSERT( psa_key_policy_get_algorithm( &policy_get ) == policy_alg ); /* Export the key again */ - TEST_ASSERT( psa_export_key( slot, second_export, export_size, + TEST_ASSERT( psa_export_key( handle, second_export, export_size, &second_exported_length ) == export_status ); if( export_status == PSA_SUCCESS ) @@ -4049,13 +4202,13 @@ void persistent_key_load_key_from_storage( data_t *data, int type_arg, } /* Do something with the key according to its type and permitted usage. */ - if( ! exercise_key( slot, policy_usage, policy_alg ) ) + if( ! exercise_key( handle, policy_usage, policy_alg ) ) goto exit; exit: mbedtls_free( first_export ); mbedtls_free( second_export ); - psa_destroy_key( slot ); + psa_destroy_key( handle ); mbedtls_psa_crypto_free(); } /* END_CASE */ From b0edfb513b2f256507650a48b35b69891f940f76 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 3 Dec 2018 16:24:51 +0100 Subject: [PATCH 15/35] Convert the PSA example programs to the new handle API Switch from the direct use of slot numbers to handles allocated by psa_allocate_key. --- programs/psa/crypto_examples.c | 56 ++++++++------ programs/psa/key_ladder_demo.c | 136 +++++++++++++++++++++------------ 2 files changed, 121 insertions(+), 71 deletions(-) diff --git a/programs/psa/crypto_examples.c b/programs/psa/crypto_examples.c index 72c41fa79..53b6b2ae7 100644 --- a/programs/psa/crypto_examples.c +++ b/programs/psa/crypto_examples.c @@ -44,10 +44,7 @@ int main( void ) } #else -/* Use key slot 1 for our cipher key. Key slot 0 is reserved as unused. */ -static const psa_key_slot_t key_slot_cipher = 1; - -static psa_status_t set_key_policy( psa_key_slot_t key_slot, +static psa_status_t set_key_policy( psa_key_handle_t key_handle, psa_key_usage_t key_usage, psa_algorithm_t alg ) { @@ -56,7 +53,7 @@ static psa_status_t set_key_policy( psa_key_slot_t key_slot, psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, key_usage, alg ); - status = psa_set_key_policy( key_slot, &policy ); + status = psa_set_key_policy( key_handle, &policy ); ASSERT_STATUS( status, PSA_SUCCESS ); exit: return( status ); @@ -98,7 +95,7 @@ exit: return( status ); } -static psa_status_t cipher_encrypt( psa_key_slot_t key_slot, +static psa_status_t cipher_encrypt( psa_key_handle_t key_handle, psa_algorithm_t alg, uint8_t * iv, size_t iv_size, @@ -114,7 +111,7 @@ static psa_status_t cipher_encrypt( psa_key_slot_t key_slot, size_t iv_len = 0; memset( &operation, 0, sizeof( operation ) ); - status = psa_cipher_encrypt_setup( &operation, key_slot, alg ); + status = psa_cipher_encrypt_setup( &operation, key_handle, alg ); ASSERT_STATUS( status, PSA_SUCCESS ); status = psa_cipher_generate_iv( &operation, iv, iv_size, &iv_len ); @@ -129,7 +126,7 @@ exit: return( status ); } -static psa_status_t cipher_decrypt( psa_key_slot_t key_slot, +static psa_status_t cipher_decrypt( psa_key_handle_t key_handle, psa_algorithm_t alg, const uint8_t * iv, size_t iv_size, @@ -144,7 +141,7 @@ static psa_status_t cipher_decrypt( psa_key_slot_t key_slot, psa_cipher_operation_t operation; memset( &operation, 0, sizeof( operation ) ); - status = psa_cipher_decrypt_setup( &operation, key_slot, alg ); + status = psa_cipher_decrypt_setup( &operation, key_handle, alg ); ASSERT_STATUS( status, PSA_SUCCESS ); status = psa_cipher_set_iv( &operation, iv, iv_size ); @@ -170,6 +167,7 @@ cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block( void ) const psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING; psa_status_t status; + psa_key_handle_t key_handle = 0; size_t output_len = 0; uint8_t iv[block_size]; uint8_t input[block_size]; @@ -179,21 +177,24 @@ cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block( void ) status = psa_generate_random( input, sizeof( input ) ); ASSERT_STATUS( status, PSA_SUCCESS ); - status = set_key_policy( key_slot_cipher, + status = psa_allocate_key( PSA_KEY_TYPE_AES, key_bits, &key_handle ); + ASSERT_STATUS( status, PSA_SUCCESS ); + + status = set_key_policy( key_handle, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT, alg ); ASSERT_STATUS( status, PSA_SUCCESS ); - status = psa_generate_key( key_slot_cipher, PSA_KEY_TYPE_AES, key_bits, + status = psa_generate_key( key_handle, PSA_KEY_TYPE_AES, key_bits, NULL, 0 ); ASSERT_STATUS( status, PSA_SUCCESS ); - status = cipher_encrypt( key_slot_cipher, alg, iv, sizeof( iv ), + status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ), input, sizeof( input ), part_size, encrypt, sizeof( encrypt ), &output_len ); ASSERT_STATUS( status, PSA_SUCCESS ); - status = cipher_decrypt( key_slot_cipher, alg, iv, sizeof( iv ), + status = cipher_decrypt( key_handle, alg, iv, sizeof( iv ), encrypt, output_len, part_size, decrypt, sizeof( decrypt ), &output_len ); ASSERT_STATUS( status, PSA_SUCCESS ); @@ -202,7 +203,7 @@ cipher_example_encrypt_decrypt_aes_cbc_nopad_1_block( void ) ASSERT_STATUS( status, PSA_SUCCESS ); exit: - psa_destroy_key( key_slot_cipher ); + psa_destroy_key( key_handle ); return( status ); } @@ -218,6 +219,7 @@ static psa_status_t cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi( void ) const psa_algorithm_t alg = PSA_ALG_CBC_PKCS7; psa_status_t status; + psa_key_handle_t key_handle = 0; size_t output_len = 0; uint8_t iv[block_size], input[input_size], encrypt[input_size + block_size], decrypt[input_size + block_size]; @@ -225,21 +227,24 @@ static psa_status_t cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi( void ) status = psa_generate_random( input, sizeof( input ) ); ASSERT_STATUS( status, PSA_SUCCESS ); - status = set_key_policy( key_slot_cipher, + status = psa_allocate_key( PSA_KEY_TYPE_AES, key_bits, &key_handle ); + ASSERT_STATUS( status, PSA_SUCCESS ); + + status = set_key_policy( key_handle, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT, alg ); ASSERT_STATUS( status, PSA_SUCCESS ); - status = psa_generate_key( key_slot_cipher, PSA_KEY_TYPE_AES, key_bits, + status = psa_generate_key( key_handle, PSA_KEY_TYPE_AES, key_bits, NULL, 0 ); ASSERT_STATUS( status, PSA_SUCCESS ); - status = cipher_encrypt( key_slot_cipher, alg, iv, sizeof( iv ), + status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ), input, sizeof( input ), part_size, encrypt, sizeof( encrypt ), &output_len ); ASSERT_STATUS( status, PSA_SUCCESS ); - status = cipher_decrypt( key_slot_cipher, alg, iv, sizeof( iv ), + status = cipher_decrypt( key_handle, alg, iv, sizeof( iv ), encrypt, output_len, part_size, decrypt, sizeof( decrypt ), &output_len ); ASSERT_STATUS( status, PSA_SUCCESS ); @@ -248,7 +253,7 @@ static psa_status_t cipher_example_encrypt_decrypt_aes_cbc_pkcs7_multi( void ) ASSERT_STATUS( status, PSA_SUCCESS ); exit: - psa_destroy_key( key_slot_cipher ); + psa_destroy_key( key_handle ); return( status ); } @@ -263,6 +268,7 @@ static psa_status_t cipher_example_encrypt_decrypt_aes_ctr_multi( void ) const psa_algorithm_t alg = PSA_ALG_CTR; psa_status_t status; + psa_key_handle_t key_handle = 0; size_t output_len = 0; uint8_t iv[block_size], input[input_size], encrypt[input_size], decrypt[input_size]; @@ -270,21 +276,23 @@ static psa_status_t cipher_example_encrypt_decrypt_aes_ctr_multi( void ) status = psa_generate_random( input, sizeof( input ) ); ASSERT_STATUS( status, PSA_SUCCESS ); - status = set_key_policy( key_slot_cipher, + status = psa_allocate_key( PSA_KEY_TYPE_AES, key_bits, &key_handle ); + ASSERT_STATUS( status, PSA_SUCCESS ); + status = set_key_policy( key_handle, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT, alg ); ASSERT_STATUS( status, PSA_SUCCESS ); - status = psa_generate_key( key_slot_cipher, PSA_KEY_TYPE_AES, key_bits, + status = psa_generate_key( key_handle, PSA_KEY_TYPE_AES, key_bits, NULL, 0 ); ASSERT_STATUS( status, PSA_SUCCESS ); - status = cipher_encrypt( key_slot_cipher, alg, iv, sizeof( iv ), + status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ), input, sizeof( input ), part_size, encrypt, sizeof( encrypt ), &output_len ); ASSERT_STATUS( status, PSA_SUCCESS ); - status = cipher_decrypt( key_slot_cipher, alg, iv, sizeof( iv ), + status = cipher_decrypt( key_handle, alg, iv, sizeof( iv ), encrypt, output_len, part_size, decrypt, sizeof( decrypt ), &output_len ); ASSERT_STATUS( status, PSA_SUCCESS ); @@ -293,7 +301,7 @@ static psa_status_t cipher_example_encrypt_decrypt_aes_ctr_multi( void ) ASSERT_STATUS( status, PSA_SUCCESS ); exit: - psa_destroy_key( key_slot_cipher ); + psa_destroy_key( key_handle ); return( status ); } diff --git a/programs/psa/key_ladder_demo.c b/programs/psa/key_ladder_demo.c index 2c75ca462..470b1fce4 100644 --- a/programs/psa/key_ladder_demo.c +++ b/programs/psa/key_ladder_demo.c @@ -167,15 +167,6 @@ typedef struct uint8_t iv[WRAPPING_IV_SIZE]; } wrapped_data_header_t; -/* This program uses three key slots: one for the master key, one to - * derive intermediate keys, and one for the wrapping key. We use a - * single slot for all the intermediate keys because they are only - * needed successively, so each time we derive an intermediate key, - * we destroy the previous one. */ -static const psa_key_slot_t master_key_slot = 1; -static const psa_key_slot_t derived_key_slot = 2; -static const psa_key_slot_t wrapping_key_slot = 3; - /* The modes that this program can operate in (see usage). */ enum program_mode { @@ -187,7 +178,7 @@ enum program_mode /* Save a key to a file. In the real world, you may want to export a derived * key sometimes, to share it with another party. */ -static psa_status_t save_key( psa_key_slot_t key_slot, +static psa_status_t save_key( psa_key_handle_t key_handle, const char *output_file_name ) { psa_status_t status = PSA_SUCCESS; @@ -195,7 +186,7 @@ static psa_status_t save_key( psa_key_slot_t key_slot, size_t key_size; FILE *key_file = NULL; - PSA_CHECK( psa_export_key( key_slot, + PSA_CHECK( psa_export_key( key_handle, key_data, sizeof( key_data ), &key_size ) ); SYS_CHECK( ( key_file = fopen( output_file_name, "wb" ) ) != NULL ); @@ -217,22 +208,27 @@ exit: static psa_status_t generate( const char *key_file_name ) { psa_status_t status = PSA_SUCCESS; + psa_key_handle_t key_handle = 0; psa_key_policy_t policy; + PSA_CHECK( psa_allocate_key( PSA_KEY_TYPE_DERIVE, + PSA_BYTES_TO_BITS( KEY_SIZE_BYTES ), + &key_handle ) ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT, KDF_ALG ); - PSA_CHECK( psa_set_key_policy( master_key_slot, &policy ) ); + PSA_CHECK( psa_set_key_policy( key_handle, &policy ) ); - PSA_CHECK( psa_generate_key( master_key_slot, + PSA_CHECK( psa_generate_key( key_handle, PSA_KEY_TYPE_DERIVE, PSA_BYTES_TO_BITS( KEY_SIZE_BYTES ), NULL, 0 ) ); - PSA_CHECK( save_key( master_key_slot, key_file_name ) ); + PSA_CHECK( save_key( key_handle, key_file_name ) ); exit: + (void) psa_destroy_key( key_handle ); return( status ); } @@ -241,10 +237,10 @@ exit: * In the real world, this master key would be stored in an internal memory * and the storage would be managed by the keystore capability of the PSA * crypto library. */ -static psa_status_t import_key_from_file( psa_key_slot_t key_slot, - psa_key_usage_t usage, +static psa_status_t import_key_from_file( psa_key_usage_t usage, psa_algorithm_t alg, - const char *key_file_name ) + const char *key_file_name, + psa_key_handle_t *master_key_handle ) { psa_status_t status = PSA_SUCCESS; psa_key_policy_t policy; @@ -253,6 +249,8 @@ static psa_status_t import_key_from_file( psa_key_slot_t key_slot, FILE *key_file = NULL; unsigned char extra_byte; + *master_key_handle = 0; + SYS_CHECK( ( key_file = fopen( key_file_name, "rb" ) ) != NULL ); SYS_CHECK( ( key_size = fread( key_data, 1, sizeof( key_data ), key_file ) ) != 0 ); @@ -266,30 +264,41 @@ static psa_status_t import_key_from_file( psa_key_slot_t key_slot, SYS_CHECK( fclose( key_file ) == 0 ); key_file = NULL; + PSA_CHECK( psa_allocate_key( PSA_KEY_TYPE_DERIVE, + PSA_BYTES_TO_BITS( key_size ), + master_key_handle ) ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, usage, alg ); - PSA_CHECK( psa_set_key_policy( key_slot, &policy ) ); - PSA_CHECK( psa_import_key( key_slot, + PSA_CHECK( psa_set_key_policy( *master_key_handle, &policy ) ); + PSA_CHECK( psa_import_key( *master_key_handle, PSA_KEY_TYPE_DERIVE, key_data, key_size ) ); exit: if( key_file != NULL ) fclose( key_file ); mbedtls_platform_zeroize( key_data, sizeof( key_data ) ); + if( status != PSA_SUCCESS ) + { + /* If psa_allocate_key hasn't been called yet or has failed, + * *master_key_handle is 0. psa_destroy_key(0) is guaranteed to do + * nothing and return PSA_ERROR_INVALID_HANDLE. */ + (void) psa_destroy_key( *master_key_handle ); + *master_key_handle = 0; + } return( status ); } /* Derive the intermediate keys, using the list of labels provided on - * the command line. */ + * the command line. On input, *key_handle is a handle to the master key. + * This function closes the master key. On successful output, *key_handle + * is a handle to the final derived key. */ static psa_status_t derive_key_ladder( const char *ladder[], - size_t ladder_depth ) + size_t ladder_depth, + psa_key_handle_t *key_handle ) { psa_status_t status = PSA_SUCCESS; psa_key_policy_t policy; psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; - /* We'll derive the first intermediate key from the master key, then - * each subsequent intemediate key from the previous intemediate key. */ - psa_key_slot_t parent_key_slot = master_key_slot; size_t i; psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, @@ -303,63 +312,81 @@ static psa_status_t derive_key_ladder( const char *ladder[], * the current intermediate key (if i>0). */ PSA_CHECK( psa_key_derivation( &generator, - parent_key_slot, + *key_handle, KDF_ALG, DERIVE_KEY_SALT, DERIVE_KEY_SALT_LENGTH, (uint8_t*) ladder[i], strlen( ladder[i] ), KEY_SIZE_BYTES ) ); /* When the parent key is not the master key, destroy it, * since it is no longer needed. */ - if( i != 0 ) - PSA_CHECK( psa_destroy_key( derived_key_slot ) ); - PSA_CHECK( psa_set_key_policy( derived_key_slot, &policy ) ); + PSA_CHECK( psa_close_key( *key_handle ) ); + *key_handle = 0; + PSA_CHECK( psa_allocate_key( PSA_KEY_TYPE_DERIVE, + PSA_BYTES_TO_BITS( KEY_SIZE_BYTES ), + key_handle ) ); + PSA_CHECK( psa_set_key_policy( *key_handle, &policy ) ); /* Use the generator obtained from the parent key to create * the next intermediate key. */ PSA_CHECK( psa_generator_import_key( - derived_key_slot, + *key_handle, PSA_KEY_TYPE_DERIVE, PSA_BYTES_TO_BITS( KEY_SIZE_BYTES ), &generator ) ); PSA_CHECK( psa_generator_abort( &generator ) ); - parent_key_slot = derived_key_slot; } exit: psa_generator_abort( &generator ); + if( status != PSA_SUCCESS ) + { + psa_close_key( *key_handle ); + *key_handle = 0; + } return( status ); } /* Derive a wrapping key from the last intermediate key. */ -static psa_status_t derive_wrapping_key( psa_key_usage_t usage ) +static psa_status_t derive_wrapping_key( psa_key_usage_t usage, + psa_key_handle_t derived_key_handle, + psa_key_handle_t *wrapping_key_handle ) { psa_status_t status = PSA_SUCCESS; psa_key_policy_t policy; psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; + *wrapping_key_handle = 0; + PSA_CHECK( psa_allocate_key( PSA_KEY_TYPE_AES, WRAPPING_KEY_BITS, + wrapping_key_handle ) ); psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, usage, WRAPPING_ALG ); - PSA_CHECK( psa_set_key_policy( wrapping_key_slot, &policy ) ); + PSA_CHECK( psa_set_key_policy( *wrapping_key_handle, &policy ) ); PSA_CHECK( psa_key_derivation( &generator, - derived_key_slot, + derived_key_handle, KDF_ALG, WRAPPING_KEY_SALT, WRAPPING_KEY_SALT_LENGTH, NULL, 0, PSA_BITS_TO_BYTES( WRAPPING_KEY_BITS ) ) ); PSA_CHECK( psa_generator_import_key( - wrapping_key_slot, + *wrapping_key_handle, PSA_KEY_TYPE_AES, WRAPPING_KEY_BITS, &generator ) ); exit: psa_generator_abort( &generator ); + if( status != PSA_SUCCESS ) + { + psa_close_key( *wrapping_key_handle ); + *wrapping_key_handle = 0; + } return( status ); } static psa_status_t wrap_data( const char *input_file_name, - const char *output_file_name ) + const char *output_file_name, + psa_key_handle_t wrapping_key_handle ) { psa_status_t status; FILE *input_file = NULL; @@ -407,7 +434,7 @@ static psa_status_t wrap_data( const char *input_file_name, /* Wrap the data. */ PSA_CHECK( psa_generate_random( header.iv, WRAPPING_IV_SIZE ) ); - PSA_CHECK( psa_aead_encrypt( wrapping_key_slot, WRAPPING_ALG, + PSA_CHECK( psa_aead_encrypt( wrapping_key_handle, WRAPPING_ALG, header.iv, WRAPPING_IV_SIZE, (uint8_t *) &header, sizeof( header ), buffer, input_size, @@ -435,7 +462,8 @@ exit: } static psa_status_t unwrap_data( const char *input_file_name, - const char *output_file_name ) + const char *output_file_name, + psa_key_handle_t wrapping_key_handle ) { psa_status_t status; FILE *input_file = NULL; @@ -487,7 +515,7 @@ static psa_status_t unwrap_data( const char *input_file_name, input_file = NULL; /* Unwrap the data. */ - PSA_CHECK( psa_aead_decrypt( wrapping_key_slot, WRAPPING_ALG, + PSA_CHECK( psa_aead_decrypt( wrapping_key_handle, WRAPPING_ALG, header.iv, WRAPPING_IV_SIZE, (uint8_t *) &header, sizeof( header ), buffer, ciphertext_size, @@ -525,6 +553,8 @@ static psa_status_t run( enum program_mode mode, const char *output_file_name ) { psa_status_t status = PSA_SUCCESS; + psa_key_handle_t derivation_key_handle = 0; + psa_key_handle_t wrapping_key_handle = 0; /* Initialize the PSA crypto library. */ PSA_CHECK( psa_crypto_init( ) ); @@ -534,26 +564,33 @@ static psa_status_t run( enum program_mode mode, return( generate( key_file_name ) ); /* Read the master key. */ - PSA_CHECK( import_key_from_file( master_key_slot, - PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT, + PSA_CHECK( import_key_from_file( PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT, KDF_ALG, - key_file_name ) ); + key_file_name, + &derivation_key_handle ) ); /* Calculate the derived key for this session. */ - PSA_CHECK( derive_key_ladder( ladder, ladder_depth ) ); + PSA_CHECK( derive_key_ladder( ladder, ladder_depth, + &derivation_key_handle ) ); switch( mode ) { case MODE_SAVE: - PSA_CHECK( save_key( derived_key_slot, output_file_name ) ); + PSA_CHECK( save_key( derivation_key_handle, output_file_name ) ); break; case MODE_UNWRAP: - PSA_CHECK( derive_wrapping_key( PSA_KEY_USAGE_DECRYPT ) ); - PSA_CHECK( unwrap_data( input_file_name, output_file_name ) ); + PSA_CHECK( derive_wrapping_key( PSA_KEY_USAGE_DECRYPT, + derivation_key_handle, + &wrapping_key_handle ) ); + PSA_CHECK( unwrap_data( input_file_name, output_file_name, + wrapping_key_handle ) ); break; case MODE_WRAP: - PSA_CHECK( derive_wrapping_key( PSA_KEY_USAGE_ENCRYPT ) ); - PSA_CHECK( wrap_data( input_file_name, output_file_name ) ); + PSA_CHECK( derive_wrapping_key( PSA_KEY_USAGE_ENCRYPT, + derivation_key_handle, + &wrapping_key_handle ) ); + PSA_CHECK( wrap_data( input_file_name, output_file_name, + wrapping_key_handle ) ); break; default: /* Unreachable but some compilers don't realize it. */ @@ -561,6 +598,11 @@ static psa_status_t run( enum program_mode mode, } exit: + /* Close any remaining key. Deinitializing the crypto library would do + * this anyway, but explicitly closing handles makes the code easier + * to reuse. */ + (void) psa_close_key( derivation_key_handle ); + (void) psa_close_key( wrapping_key_handle ); /* Deinitialize the PSA crypto library. */ mbedtls_psa_crypto_free( ); return( status ); From 8d4919bc6a46e93da2a62105a31bed55f147b745 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 3 Dec 2018 16:48:09 +0100 Subject: [PATCH 16/35] Persistent storage implementation: psa_key_slot_t -> psa_key_id_t Move the persistent storage implementation from psa_key_slot_t to psa_key_id_t. For the most part, this just means changing the types of function arguments. Update the documentation of some functions to reflect the fact that the slot identifier is purely a storage identifier and is not related to how the slot is designated in memory. --- library/psa_crypto_storage.c | 4 ++-- library/psa_crypto_storage.h | 27 +++++++++++++------------- library/psa_crypto_storage_backend.h | 29 +++++++++++++++------------- library/psa_crypto_storage_file.c | 26 ++++++++++++------------- library/psa_crypto_storage_its.c | 12 ++++++------ 5 files changed, 51 insertions(+), 47 deletions(-) diff --git a/library/psa_crypto_storage.c b/library/psa_crypto_storage.c index 0a5805b62..687269b07 100644 --- a/library/psa_crypto_storage.c +++ b/library/psa_crypto_storage.c @@ -147,7 +147,7 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, return( PSA_SUCCESS ); } -psa_status_t psa_save_persistent_key( const psa_key_slot_t key, +psa_status_t psa_save_persistent_key( const psa_key_id_t key, const psa_key_type_t type, const psa_key_policy_t *policy, const uint8_t *data, @@ -185,7 +185,7 @@ void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length ) mbedtls_free( key_data ); } -psa_status_t psa_load_persistent_key( psa_key_slot_t key, +psa_status_t psa_load_persistent_key( psa_key_id_t key, psa_key_type_t *type, psa_key_policy_t *policy, uint8_t **data, diff --git a/library/psa_crypto_storage.h b/library/psa_crypto_storage.h index 167b0db05..478daef8f 100644 --- a/library/psa_crypto_storage.h +++ b/library/psa_crypto_storage.h @@ -56,20 +56,20 @@ extern "C" { * already occupied non-persistent key, as well as validating the key data. * * - * \param key Slot number of the key to be stored. This must be a - * valid slot for a key of the chosen type. This should be - * an occupied key slot with an unoccupied corresponding - * storage location. + * \param key Persistent identifier of the key to be stored. This + * should be an unoccupied storage location. * \param type Key type (a \c PSA_KEY_TYPE_XXX value). * \param[in] policy The key policy to save. * \param[in] data Buffer containing the key data. * \param data_length The number of bytes that make up the key data. * * \retval PSA_SUCCESS + * \retval PSA_ERROR_INSUFFICIENT_MEMORY * \retval PSA_ERROR_INSUFFICIENT_STORAGE * \retval PSA_ERROR_STORAGE_FAILURE + * \retval PSA_ERROR_OCCUPIED_SLOT */ -psa_status_t psa_save_persistent_key( const psa_key_slot_t key, +psa_status_t psa_save_persistent_key( const psa_key_id_t key, const psa_key_type_t type, const psa_key_policy_t *policy, const uint8_t *data, @@ -87,10 +87,8 @@ psa_status_t psa_save_persistent_key( const psa_key_slot_t key, * this function to zeroize and free this buffer, regardless of whether this * function succeeds or fails. * - * \param key Slot number whose content is to be loaded. This - * must be an unoccupied key slot with an occupied - * corresponding storage location. The key slot - * lifetime must be set to persistent. + * \param key Persistent identifier of the key to be loaded. This + * should be an occupied storage location. * \param[out] type On success, the key type (a \c PSA_KEY_TYPE_XXX * value). * \param[out] policy On success, the key's policy. @@ -100,8 +98,9 @@ psa_status_t psa_save_persistent_key( const psa_key_slot_t key, * \retval PSA_SUCCESS * \retval PSA_ERROR_INSUFFICIENT_MEMORY * \retval PSA_ERROR_STORAGE_FAILURE + * \retval PSA_ERROR_EMPTY_SLOT */ -psa_status_t psa_load_persistent_key( psa_key_slot_t key, +psa_status_t psa_load_persistent_key( psa_key_id_t key, psa_key_type_t *type, psa_key_policy_t *policy, uint8_t **data, @@ -110,16 +109,18 @@ psa_status_t psa_load_persistent_key( psa_key_slot_t key, /** * \brief Remove persistent data for the given key slot number. * - * \param key Slot number whose content is to be removed + * \param key Persistent identifier of the key to remove * from persistent storage. * * \retval PSA_SUCCESS + * The key was successfully removed, + * or the key did not exist. * \retval PSA_ERROR_STORAGE_FAILURE */ -psa_status_t psa_destroy_persistent_key( const psa_key_slot_t key ); +psa_status_t psa_destroy_persistent_key( const psa_key_id_t key ); /** - * \brief Zeroizes and frees the given buffer. + * \brief Free the temporary buffer allocated by psa_load_persistent_key(). * * This function must be called at some point after psa_load_persistent_key() * to zeroize and free the memory allocated to the buffer in that function. diff --git a/library/psa_crypto_storage_backend.h b/library/psa_crypto_storage_backend.h index 3ca9a1d74..47896b872 100644 --- a/library/psa_crypto_storage_backend.h +++ b/library/psa_crypto_storage_backend.h @@ -47,15 +47,16 @@ extern "C" { * This function reads data from a storage backend and returns the data in a * buffer. * - * \param key Slot number whose content is to be loaded. This must - * be a key slot whose lifetime is set to persistent. - * \param[out] data Buffer where the data is to be written. - * \param data_size Size of the \c data buffer in bytes. + * \param key Persistent identifier of the key to be loaded. This + * should be an occupied storage location. + * \param[out] data Buffer where the data is to be written. + * \param data_size Size of the \c data buffer in bytes. * * \retval PSA_SUCCESS * \retval PSA_ERROR_STORAGE_FAILURE + * \retval PSA_ERROR_EMPTY_SLOT */ -psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data, +psa_status_t psa_crypto_storage_load( const psa_key_id_t key, uint8_t *data, size_t data_size ); /** @@ -63,7 +64,8 @@ psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data, * * This function stores the given data buffer to a persistent storage. * - * \param key Slot number whose content is to be stored. + * \param key Persistent identifier of the key to be stored. This + * should be an unoccupied storage location. * \param[in] data Buffer containing the data to be stored. * \param data_length The number of bytes * that make up the data. @@ -71,8 +73,9 @@ psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data, * \retval PSA_SUCCESS * \retval PSA_ERROR_INSUFFICIENT_STORAGE * \retval PSA_ERROR_STORAGE_FAILURE + * \retval PSA_ERROR_OCCUPIED_SLOT */ -psa_status_t psa_crypto_storage_store( const psa_key_slot_t key, +psa_status_t psa_crypto_storage_store( const psa_key_id_t key, const uint8_t *data, size_t data_length ); @@ -82,26 +85,26 @@ psa_status_t psa_crypto_storage_store( const psa_key_slot_t key, * This function checks if any key data or metadata exists for the key slot in * the persistent storage. * - * \param key Slot number whose content is to be checked. + * \param key Persistent identifier to check. * * \retval 0 * No persistent data present for slot number * \retval 1 * Persistent data present for slot number */ -int psa_is_key_present_in_storage( const psa_key_slot_t key ); +int psa_is_key_present_in_storage( const psa_key_id_t key ); /** * \brief Get data length for given key slot number. * - * \param key Slot number whose stored data length is to be obtained. - * \param[out] data_length The number of bytes - * that make up the data. + * \param key Persistent identifier whose stored data length + * is to be obtained. + * \param[out] data_length The number of bytes that make up the data. * * \retval PSA_SUCCESS * \retval PSA_ERROR_STORAGE_FAILURE */ -psa_status_t psa_crypto_storage_get_data_length( const psa_key_slot_t key, +psa_status_t psa_crypto_storage_get_data_length( const psa_key_id_t key, size_t *data_length ); diff --git a/library/psa_crypto_storage_file.c b/library/psa_crypto_storage_file.c index 03c711af3..95857fa40 100644 --- a/library/psa_crypto_storage_file.c +++ b/library/psa_crypto_storage_file.c @@ -48,15 +48,15 @@ enum { MAX_LOCATION_LEN = sizeof(CRYPTO_STORAGE_FILE_LOCATION) + 40 }; -static void key_slot_to_location( const psa_key_slot_t key, - char *location, - size_t location_size ) +static void key_id_to_location( const psa_key_id_t key, + char *location, + size_t location_size ) { mbedtls_snprintf( location, location_size, CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_%d", key ); } -psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data, +psa_status_t psa_crypto_storage_load( const psa_key_id_t key, uint8_t *data, size_t data_size ) { psa_status_t status = PSA_SUCCESS; @@ -64,7 +64,7 @@ psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data, size_t num_read; char slot_location[MAX_LOCATION_LEN]; - key_slot_to_location( key, slot_location, MAX_LOCATION_LEN ); + key_id_to_location( key, slot_location, MAX_LOCATION_LEN ); file = fopen( slot_location, "rb" ); if( file == NULL ) { @@ -81,12 +81,12 @@ exit: return( status ); } -int psa_is_key_present_in_storage( const psa_key_slot_t key ) +int psa_is_key_present_in_storage( const psa_key_id_t key ) { char slot_location[MAX_LOCATION_LEN]; FILE *file; - key_slot_to_location( key, slot_location, MAX_LOCATION_LEN ); + key_id_to_location( key, slot_location, MAX_LOCATION_LEN ); file = fopen( slot_location, "r" ); if( file == NULL ) @@ -99,7 +99,7 @@ int psa_is_key_present_in_storage( const psa_key_slot_t key ) return( 1 ); } -psa_status_t psa_crypto_storage_store( const psa_key_slot_t key, +psa_status_t psa_crypto_storage_store( const psa_key_id_t key, const uint8_t *data, size_t data_length ) { @@ -114,7 +114,7 @@ psa_status_t psa_crypto_storage_store( const psa_key_slot_t key, * affect actual keys. */ const char *temp_location = CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_0"; - key_slot_to_location( key, slot_location, MAX_LOCATION_LEN ); + key_id_to_location( key, slot_location, MAX_LOCATION_LEN ); if( psa_is_key_present_in_storage( key ) == 1 ) return( PSA_ERROR_OCCUPIED_SLOT ); @@ -154,12 +154,12 @@ exit: return( status ); } -psa_status_t psa_destroy_persistent_key( const psa_key_slot_t key ) +psa_status_t psa_destroy_persistent_key( const psa_key_id_t key ) { FILE *file; char slot_location[MAX_LOCATION_LEN]; - key_slot_to_location( key, slot_location, MAX_LOCATION_LEN ); + key_id_to_location( key, slot_location, MAX_LOCATION_LEN ); /* Only try remove the file if it exists */ file = fopen( slot_location, "rb" ); @@ -173,7 +173,7 @@ psa_status_t psa_destroy_persistent_key( const psa_key_slot_t key ) return( PSA_SUCCESS ); } -psa_status_t psa_crypto_storage_get_data_length( const psa_key_slot_t key, +psa_status_t psa_crypto_storage_get_data_length( const psa_key_id_t key, size_t *data_length ) { psa_status_t status = PSA_SUCCESS; @@ -181,7 +181,7 @@ psa_status_t psa_crypto_storage_get_data_length( const psa_key_slot_t key, long file_size; char slot_location[MAX_LOCATION_LEN]; - key_slot_to_location( key, slot_location, MAX_LOCATION_LEN ); + key_id_to_location( key, slot_location, MAX_LOCATION_LEN ); file = fopen( slot_location, "rb" ); if( file == NULL ) diff --git a/library/psa_crypto_storage_its.c b/library/psa_crypto_storage_its.c index 29394b5d8..86e0e89f3 100644 --- a/library/psa_crypto_storage_its.c +++ b/library/psa_crypto_storage_its.c @@ -68,12 +68,12 @@ static psa_status_t its_to_psa_error( psa_its_status_t ret ) } } -static uint32_t psa_its_identifier_of_slot( psa_key_slot_t key ) +static uint32_t psa_its_identifier_of_slot( psa_key_id_t key ) { return( key ); } -psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data, +psa_status_t psa_crypto_storage_load( const psa_key_id_t key, uint8_t *data, size_t data_size ) { psa_its_status_t ret; @@ -92,7 +92,7 @@ psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data, return( status ); } -int psa_is_key_present_in_storage( const psa_key_slot_t key ) +int psa_is_key_present_in_storage( const psa_key_id_t key ) { psa_its_status_t ret; uint32_t data_identifier = psa_its_identifier_of_slot( key ); @@ -105,7 +105,7 @@ int psa_is_key_present_in_storage( const psa_key_slot_t key ) return( 1 ); } -psa_status_t psa_crypto_storage_store( const psa_key_slot_t key, +psa_status_t psa_crypto_storage_store( const psa_key_id_t key, const uint8_t *data, size_t data_length ) { @@ -143,7 +143,7 @@ exit: return( status ); } -psa_status_t psa_destroy_persistent_key( const psa_key_slot_t key ) +psa_status_t psa_destroy_persistent_key( const psa_key_id_t key ) { psa_its_status_t ret; uint32_t data_identifier = psa_its_identifier_of_slot( key ); @@ -163,7 +163,7 @@ psa_status_t psa_destroy_persistent_key( const psa_key_slot_t key ) return( PSA_SUCCESS ); } -psa_status_t psa_crypto_storage_get_data_length( const psa_key_slot_t key, +psa_status_t psa_crypto_storage_get_data_length( const psa_key_id_t key, size_t *data_length ) { psa_its_status_t ret; From a23eafce3ae5ac76ffd708afc06ee2e20946d51f Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 3 Dec 2018 16:48:14 +0100 Subject: [PATCH 17/35] Fix snprintf call to assume less about integral type sizes The code only worked if psa_key_id_t (formerly psa_key_slot_t) promoted to int and every value fit in int. Now the code only assumes that psa_key_id_t is less wide than unsigned long, which is the case since psa_key_id_t is a 32-bit type in our implementation. --- library/psa_crypto_storage_file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/psa_crypto_storage_file.c b/library/psa_crypto_storage_file.c index 95857fa40..87420be98 100644 --- a/library/psa_crypto_storage_file.c +++ b/library/psa_crypto_storage_file.c @@ -53,7 +53,8 @@ static void key_id_to_location( const psa_key_id_t key, size_t location_size ) { mbedtls_snprintf( location, location_size, - CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_%d", key ); + CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_%lu", + (unsigned long) key ); } psa_status_t psa_crypto_storage_load( const psa_key_id_t key, uint8_t *data, From 7bc9f682324acdb2692bca373c877d7cc8263b31 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 3 Dec 2018 17:05:18 +0100 Subject: [PATCH 18/35] Convert the PSA crypto persistent storage tests to the new handle API Switch from the direct use of slot numbers to handles allocated by psa_allocate_key. The general principle for each function is: * Change `psa_key_slot_t slot` to `psa_key_handle_t handle` or `psa_key_id_t key_id` depending on whether it's used as a handle to an open slot or as a persistent name for a key. * Call psa_create_key() before using a slot, instead of calling psa_set_key_lifetime to make a slot persistent. Remove the unit test persistent_key_is_configurable which is no longer relevant. --- .../test_suite_psa_crypto_persistent_key.data | 8 - ...t_suite_psa_crypto_persistent_key.function | 186 ++++++------------ ...est_suite_psa_crypto_storage_file.function | 7 +- 3 files changed, 60 insertions(+), 141 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto_persistent_key.data b/tests/suites/test_suite_psa_crypto_persistent_key.data index 46e547c93..c9eb8e103 100644 --- a/tests/suites/test_suite_psa_crypto_persistent_key.data +++ b/tests/suites/test_suite_psa_crypto_persistent_key.data @@ -24,10 +24,6 @@ save_large_persistent_key:0:PSA_SUCCESS Save larger than maximum size persistent raw key, should fail save_large_persistent_key:1:PSA_ERROR_INSUFFICIENT_STORAGE -Persistent key is configurable -depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C -persistent_key_is_configurable:1:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24" - Persistent key destroy depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C persistent_key_destroy:1:1:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RAW_DATA:"deadbeef" @@ -36,10 +32,6 @@ Persistent key destroy missing key depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C persistent_key_destroy:1:0:PSA_KEY_TYPE_RSA_KEYPAIR:"":PSA_KEY_TYPE_RAW_DATA:"deadbeef" -Key lifetime defaults to volatile -depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C -default_volatile_lifetime:1:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24" - Persistent key import depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C persistent_key_import:1:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_SUCCESS diff --git a/tests/suites/test_suite_psa_crypto_persistent_key.function b/tests/suites/test_suite_psa_crypto_persistent_key.function index 0ede6e6c8..08c7ca017 100644 --- a/tests/suites/test_suite_psa_crypto_persistent_key.function +++ b/tests/suites/test_suite_psa_crypto_persistent_key.function @@ -85,7 +85,8 @@ exit: /* BEGIN_CASE */ void save_large_persistent_key( int data_too_large, int expected_status ) { - psa_key_slot_t slot = 1; + psa_key_id_t key_id = 42; + psa_key_handle_t handle = 0; uint8_t *data = NULL; size_t data_length = PSA_CRYPTO_MAX_STORAGE_SIZE; @@ -96,180 +97,107 @@ void save_large_persistent_key( int data_too_large, int expected_status ) TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS ); - TEST_ASSERT( psa_set_key_lifetime( - slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS ); + TEST_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, key_id, + PSA_KEY_TYPE_RAW_DATA, + PSA_BYTES_TO_BITS( data_length ), + &handle ) == PSA_SUCCESS ); - TEST_ASSERT( psa_import_key( slot, PSA_KEY_TYPE_RAW_DATA, + TEST_ASSERT( psa_import_key( handle, PSA_KEY_TYPE_RAW_DATA, data, data_length ) == expected_status ); exit: mbedtls_free( data ); - psa_destroy_persistent_key( slot ); - mbedtls_psa_crypto_free(); -} -/* END_CASE */ - - -/* BEGIN_CASE */ -void persistent_key_is_configurable( int slot_arg, int type_arg, - data_t *data ) -{ - psa_key_policy_t policy; - psa_key_lifetime_t lifetime; - psa_key_slot_t slot = (psa_key_slot_t) slot_arg; - psa_key_type_t type = (psa_key_type_t) type_arg; - - TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS ); - - TEST_ASSERT( psa_set_key_lifetime( - slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS ); - - psa_key_policy_init( &policy ); - - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); - - TEST_ASSERT( psa_import_key( slot, type, - data->x, data->len ) == PSA_SUCCESS ); - - TEST_ASSERT( psa_get_key_lifetime( slot, &lifetime ) == PSA_SUCCESS ); - - TEST_ASSERT( lifetime == PSA_KEY_LIFETIME_PERSISTENT ); - -exit: - psa_destroy_persistent_key( slot ); mbedtls_psa_crypto_free(); + psa_destroy_persistent_key( key_id ); } /* END_CASE */ /* BEGIN_CASE */ -void persistent_key_destroy( int slot_arg, int should_store, +void persistent_key_destroy( int key_id_arg, int should_store, int first_type_arg, data_t *first_data, int second_type_arg, data_t *second_data ) { psa_key_policy_t policy; - psa_key_slot_t slot = (psa_key_slot_t) slot_arg; + psa_key_id_t key_id = key_id_arg; + psa_key_handle_t handle = 0; psa_key_type_t first_type = (psa_key_type_t) first_type_arg; psa_key_type_t second_type = (psa_key_type_t) second_type_arg; TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS ); - TEST_ASSERT( psa_set_key_lifetime( - slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS ); - psa_key_policy_init( &policy ); + TEST_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, key_id, + first_type, + PSA_BYTES_TO_BITS( first_data->len ), + &handle ) == PSA_SUCCESS ); + if( should_store == 1 ) { TEST_ASSERT( psa_import_key( - slot, first_type, + handle, first_type, first_data->x, first_data->len ) == PSA_SUCCESS ); } /* Destroy the key */ - TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS ); - - TEST_ASSERT( psa_get_key_information( - slot, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT ); + TEST_ASSERT( psa_destroy_key( handle ) == PSA_SUCCESS ); /* Check key slot storage is removed */ - TEST_ASSERT( psa_is_key_present_in_storage( slot ) == 0 ); - - /* Check destroying the key again doesn't report failure */ - TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS ); - TEST_ASSERT( psa_get_key_information( - slot, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT ); + TEST_ASSERT( psa_is_key_present_in_storage( key_id ) == 0 ); + TEST_ASSERT( psa_open_key( PSA_KEY_LIFETIME_PERSISTENT, key_id, + &handle ) == PSA_ERROR_EMPTY_SLOT ); + TEST_ASSERT( handle == 0 ); /* Shutdown and restart */ mbedtls_psa_crypto_free(); - TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS ); - /* Mark slot as persistent again */ - TEST_ASSERT( psa_set_key_lifetime( - slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS ); - - /* Check key slot is empty */ - TEST_ASSERT( psa_get_key_information( - slot, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT ); - - /* Import different key data to ensure slot really was empty */ - psa_key_policy_init( &policy ); - - psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, - PSA_ALG_VENDOR_FLAG ); - - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); - + /* Create another key in the same slot */ + TEST_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, key_id, + second_type, + PSA_BYTES_TO_BITS( second_data->len ), + &handle ) == PSA_SUCCESS ); TEST_ASSERT( psa_import_key( - slot, second_type, + handle, second_type, second_data->x, second_data->len ) == PSA_SUCCESS ); exit: - psa_destroy_persistent_key( slot ); mbedtls_psa_crypto_free(); + psa_destroy_persistent_key( key_id ); } /* END_CASE */ /* BEGIN_CASE */ -void default_volatile_lifetime( int slot_arg, int type_arg, data_t *data ) -{ - psa_key_policy_t policy; - psa_key_slot_t slot = (psa_key_slot_t) slot_arg; - psa_key_type_t type = (psa_key_type_t) type_arg; - - TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS ); - - psa_key_policy_init( &policy ); - - TEST_ASSERT( psa_import_key( slot, type, - data->x, data->len ) == PSA_SUCCESS ); - - /* Shutdown and restart */ - mbedtls_psa_crypto_free(); - - TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS ); - - /* Check key slot is empty */ - TEST_ASSERT( psa_get_key_information( - slot, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT ); - -exit: - psa_destroy_persistent_key( slot ); - mbedtls_psa_crypto_free(); -} -/* END_CASE */ - -/* BEGIN_CASE */ -void persistent_key_import( int slot_arg, int type_arg, data_t *data, +void persistent_key_import( int key_id_arg, int type_arg, data_t *data, int expected_status ) { psa_key_policy_t policy; psa_key_lifetime_t lifetime; - psa_key_slot_t slot = (psa_key_slot_t) slot_arg; + psa_key_id_t key_id = (psa_key_id_t) key_id_arg; psa_key_type_t type = (psa_key_type_t) type_arg; + psa_key_handle_t handle = 0; TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS ); - TEST_ASSERT( psa_set_key_lifetime( - slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS ); - + TEST_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, key_id, + type, + PSA_BYTES_TO_BITS( data->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); - - TEST_ASSERT( psa_import_key( slot, type, + TEST_ASSERT( psa_import_key( handle, type, data->x, data->len ) == expected_status ); if( expected_status != PSA_SUCCESS ) { - TEST_ASSERT( psa_is_key_present_in_storage( slot ) == 0 ); + TEST_ASSERT( psa_is_key_present_in_storage( key_id ) == 0 ); goto exit; } - TEST_ASSERT( psa_get_key_lifetime( slot, &lifetime ) == PSA_SUCCESS ); - + TEST_ASSERT( psa_get_key_lifetime( handle, &lifetime ) == PSA_SUCCESS ); TEST_ASSERT( lifetime == PSA_KEY_LIFETIME_PERSISTENT ); exit: - psa_destroy_persistent_key( slot ); + psa_destroy_persistent_key( key_id ); mbedtls_psa_crypto_free(); } /* END_CASE */ @@ -278,8 +206,9 @@ exit: void import_export_persistent_key( data_t *data, int type_arg, int expected_bits, int key_not_exist ) { - psa_key_slot_t slot = 1; + psa_key_id_t key_id = 42; psa_key_type_t type = (psa_key_type_t) type_arg; + psa_key_handle_t handle = 0; unsigned char *exported = NULL; size_t export_size = data->len; size_t exported_length; @@ -292,51 +221,48 @@ void import_export_persistent_key( data_t *data, int type_arg, TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); - TEST_ASSERT( psa_set_key_lifetime( - slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS ); + TEST_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, key_id, + type, + PSA_BYTES_TO_BITS( data->len ), + &handle ) == PSA_SUCCESS ); psa_key_policy_init( &policy ); - psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, PSA_ALG_VENDOR_FLAG ); - - TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS ); + TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS ); /* Import the key */ - TEST_ASSERT( psa_import_key( slot, type, + TEST_ASSERT( psa_import_key( handle, type, data->x, data->len ) == PSA_SUCCESS ); - TEST_ASSERT( psa_get_key_lifetime( - slot, &lifetime_get ) == PSA_SUCCESS ); + TEST_ASSERT( psa_get_key_lifetime( handle, &lifetime_get ) == PSA_SUCCESS ); TEST_ASSERT( lifetime_get == PSA_KEY_LIFETIME_PERSISTENT ); /* Test the key information */ TEST_ASSERT( psa_get_key_information( - slot, &got_type, &got_bits ) == PSA_SUCCESS ); + handle, &got_type, &got_bits ) == PSA_SUCCESS ); TEST_ASSERT( got_type == type ); TEST_ASSERT( got_bits == (size_t) expected_bits ); - TEST_ASSERT( psa_is_key_present_in_storage( slot ) == 1 ); + TEST_ASSERT( psa_is_key_present_in_storage( key_id ) == 1 ); if( key_not_exist ) { - psa_destroy_persistent_key( slot ); + psa_destroy_persistent_key( key_id ); } /* Export the key */ - TEST_ASSERT( psa_export_key( slot, exported, export_size, + TEST_ASSERT( psa_export_key( handle, exported, export_size, &exported_length ) == PSA_SUCCESS ); ASSERT_COMPARE( data->x, data->len, exported, exported_length ); /* Destroy the key */ - TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS ); - TEST_ASSERT( psa_get_key_information( - slot, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT ); - TEST_ASSERT( psa_is_key_present_in_storage( slot ) == 0 ); + TEST_ASSERT( psa_destroy_key( handle ) == PSA_SUCCESS ); + TEST_ASSERT( psa_is_key_present_in_storage( key_id ) == 0 ); exit: mbedtls_free( exported ); - psa_destroy_persistent_key( slot ); mbedtls_psa_crypto_free( ); + psa_destroy_persistent_key( key_id ); } /* END_CASE */ diff --git a/tests/suites/test_suite_psa_crypto_storage_file.function b/tests/suites/test_suite_psa_crypto_storage_file.function index b6dcad777..e753d7862 100644 --- a/tests/suites/test_suite_psa_crypto_storage_file.function +++ b/tests/suites/test_suite_psa_crypto_storage_file.function @@ -11,9 +11,11 @@ */ /* BEGIN_CASE */ -void load_data_from_file( int slot_to_load, data_t *data, int should_make_file, +void load_data_from_file( int id_to_load_arg, + data_t *data, int should_make_file, int capacity_arg, int expected_status ) { + psa_key_id_t id_to_load = id_to_load_arg; char slot_location[] = "psa_key_slot_1"; psa_status_t status; int ret; @@ -36,8 +38,7 @@ void load_data_from_file( int slot_to_load, data_t *data, int should_make_file, /* Read from the file with psa_crypto_storage_load. */ loaded_data = mbedtls_calloc( 1, capacity ); TEST_ASSERT( loaded_data != NULL ); - status = psa_crypto_storage_load( (psa_key_slot_t) slot_to_load, loaded_data, - file_size ); + status = psa_crypto_storage_load( id_to_load, loaded_data, file_size ); /* Check we get the expected status. */ TEST_ASSERT( status == expected_status ); From f6cc435a8a09f6dff383433a775583a0f691ba1c Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 3 Dec 2018 17:44:43 +0100 Subject: [PATCH 19/35] Remove psa_key_slot_t from public headers This commit marks the beginning of the removal of support for direct access to key slots. From this commit on, programs that use psa_key_slot_t will no longer compile. Subsequent commits will remove the now-unused legacy support in psa_crypto.c. --- include/psa/crypto_platform.h | 3 --- library/psa_crypto.c | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/psa/crypto_platform.h b/include/psa/crypto_platform.h index c20396619..50ca546fb 100644 --- a/include/psa/crypto_platform.h +++ b/include/psa/crypto_platform.h @@ -46,9 +46,6 @@ /* PSA requires several types which C99 provides in stdint.h. */ #include -/* Integral type representing a key slot number. */ -typedef uint16_t psa_key_slot_t; - /* Integral type representing a key handle. */ typedef uint16_t psa_key_handle_t; diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 1a038a12a..bff0ce709 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -43,6 +43,10 @@ #include "psa/crypto.h" +/* Transitional definition while moving away from directly-accessible key + * slots and to a handle-only interface. */ +typedef psa_key_handle_t psa_key_slot_t; + #include "psa_crypto_invasive.h" #include "psa_crypto_slot_management.h" /* Include internal declarations that are useful for implementing persistently From b77a6b25c02a8b5a94de7927d4d963dd5df11d97 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 3 Dec 2018 17:46:13 +0100 Subject: [PATCH 20/35] Remove psa_set_key_lifetime This function is no longer relevant. Use psa_create_key instead. --- include/psa/crypto.h | 45 -------------------------------------------- library/psa_crypto.c | 29 ---------------------------- 2 files changed, 74 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 6807c73f3..4aea9905d 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -1419,11 +1419,6 @@ typedef uint32_t psa_key_id_t; */ #define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001) -/** A write-once key slot may not be modified once a key has been set. - * It will retain its content as long as the device remains operational. - */ -#define PSA_KEY_LIFETIME_WRITE_ONCE ((psa_key_lifetime_t)0x7fffffff) - /** \brief Retrieve the lifetime of an open key. * * \param handle Handle to query. @@ -1443,46 +1438,6 @@ typedef uint32_t psa_key_id_t; psa_status_t psa_get_key_lifetime(psa_key_handle_t handle, psa_key_lifetime_t *lifetime); -/** \brief Change the lifetime of a key slot. - * - * Whether the lifetime of a key slot can be changed at all, and if so - * whether the lifetime of an occupied key slot can be changed, is - * implementation-dependent. - * - * When creating a persistent key, you must call this function before creating - * the key material with psa_import_key(), psa_generate_key() or - * psa_generator_import_key(). To open an existing persistent key, you must - * call this function with the correct lifetime value before using the slot - * for a cryptographic operation. Once a slot's lifetime has been set, - * the lifetime remains associated with the slot until a subsequent call to - * psa_set_key_lifetime(), until the key is wiped with psa_destroy_key or - * until the application terminates (or disconnects from the cryptography - * service, if the implementation offers such a possibility). - * - * \param key Slot whose lifetime is to be changed. - * \param lifetime The lifetime value to set for the given key slot. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key slot is invalid, - * or the lifetime value is invalid. - * \retval #PSA_ERROR_NOT_SUPPORTED - * The implementation does not support the specified lifetime value, - * at least for the specified key slot. - * \retval #PSA_ERROR_OCCUPIED_SLOT - * The slot contains a key, and the implementation does not support - * changing the lifetime of an occupied slot. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED - * \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. - */ -psa_status_t psa_set_key_lifetime(psa_key_handle_t key, - psa_key_lifetime_t lifetime); /** Allocate a key slot for a transient key, i.e. a key which is only stored * in volatile memory. diff --git a/library/psa_crypto.c b/library/psa_crypto.c index bff0ce709..15bab676f 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3206,35 +3206,6 @@ psa_status_t psa_get_key_lifetime( psa_key_slot_t key, return( PSA_SUCCESS ); } -psa_status_t psa_set_key_lifetime( psa_key_slot_t key, - psa_key_lifetime_t lifetime ) -{ - key_slot_t *slot; - psa_status_t status; - - if( lifetime != PSA_KEY_LIFETIME_VOLATILE && - lifetime != PSA_KEY_LIFETIME_PERSISTENT && - lifetime != PSA_KEY_LIFETIME_WRITE_ONCE ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - status = psa_get_empty_key_slot( key, &slot ); - if( status != PSA_SUCCESS ) - return( status ); - - if( lifetime == PSA_KEY_LIFETIME_WRITE_ONCE ) - return( PSA_ERROR_NOT_SUPPORTED ); - -#if !defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) - if( lifetime == PSA_KEY_LIFETIME_PERSISTENT ) - return( PSA_ERROR_NOT_SUPPORTED ); -#endif - - slot->lifetime = lifetime; - slot->persistent_storage_id = key; - - return( PSA_SUCCESS ); -} - /****************************************************************/ From c5487a889289ec977e860d1293fec61aae805260 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 3 Dec 2018 18:08:14 +0100 Subject: [PATCH 21/35] Drop support for psa_key_slot_t in psa_crypto.c This commit finishes the removal of support for direct access to key slots in psa_crypto.c. This marks the end of the necessary phase of the transition to key handles. The code should subsequently be refactored to move key slot management from psa_crypto.c to psa_crypto_slot_management.c. --- library/psa_crypto.c | 202 +++++++----------- library/psa_crypto_slot_management.h | 3 - tests/suites/test_suite_psa_crypto.data | 5 +- ..._suite_psa_crypto_slot_management.function | 5 +- 4 files changed, 79 insertions(+), 136 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 15bab676f..ce9e3e5f2 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -43,10 +43,6 @@ #include "psa/crypto.h" -/* Transitional definition while moving away from directly-accessible key - * slots and to a handle-only interface. */ -typedef psa_key_handle_t psa_key_slot_t; - #include "psa_crypto_invasive.h" #include "psa_crypto_slot_management.h" /* Include internal declarations that are useful for implementing persistently @@ -746,55 +742,34 @@ exit: } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ -/* Retrieve a key slot, occupied or not. */ -static psa_status_t psa_get_key_slot( psa_key_slot_t key_or_handle, +/* Access a key slot at the given handle. The handle of a key slot is + * the index of the slot in the global slot array, plus one so that handles + * start at 1 and not 0. */ +static psa_status_t psa_get_key_slot( psa_key_handle_t handle, key_slot_t **p_slot ) { - psa_key_slot_t key = key_or_handle & ~PSA_KEY_HANDLE_ALLOCATED_FLAG; - int is_handle = ( key_or_handle & PSA_KEY_HANDLE_ALLOCATED_FLAG ) != 0; - psa_status_t error_if_invalid = - ( is_handle ? - PSA_ERROR_INVALID_HANDLE : - PSA_ERROR_INVALID_ARGUMENT ); + key_slot_t *slot = NULL; GUARD_MODULE_INITIALIZED; - /* 0 is not a valid slot number under any circumstance. This + /* 0 is not a valid handle under any circumstance. This * implementation provides slots number 1 to N where N is the * number of available slots. */ - if( key == 0 || key > ARRAY_LENGTH( global_data.key_slots ) ) - return( error_if_invalid ); + if( handle == 0 || handle > ARRAY_LENGTH( global_data.key_slots ) ) + return( PSA_ERROR_INVALID_HANDLE ); + slot = &global_data.key_slots[handle - 1]; - *p_slot = &global_data.key_slots[key - 1]; - - /* Allocated slots must only be accessed via a handle. - * Unallocated slots must only be accessed directly. */ - if( ( *p_slot )->allocated != is_handle ) - return( error_if_invalid ); - -#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) - if( ! ( *p_slot )->allocated && - ( *p_slot )->lifetime == PSA_KEY_LIFETIME_PERSISTENT ) - { - /* There are two circumstances this can occur: the key material has - * not yet been created, or the key exists in storage but has not yet - * been loaded into memory. */ - if( ( *p_slot )->type == PSA_KEY_TYPE_NONE ) - { - psa_status_t status = PSA_SUCCESS; - status = psa_load_persistent_key_into_slot( *p_slot ); - if( status != PSA_ERROR_EMPTY_SLOT ) - return( status ); - } - } -#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + /* If the slot hasn't been allocated, the handle is invalid. */ + if( ! slot->allocated ) + return( PSA_ERROR_INVALID_HANDLE ); + *p_slot = slot; return( PSA_SUCCESS ); } /* Retrieve an empty key slot (slot with no key data, but possibly * with some metadata such as a policy). */ -static psa_status_t psa_get_empty_key_slot( psa_key_slot_t key, +static psa_status_t psa_get_empty_key_slot( psa_key_handle_t handle, key_slot_t **p_slot ) { psa_status_t status; @@ -802,7 +777,7 @@ static psa_status_t psa_get_empty_key_slot( psa_key_slot_t key, *p_slot = NULL; - status = psa_get_key_slot( key, &slot ); + status = psa_get_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); @@ -816,7 +791,7 @@ static psa_status_t psa_get_empty_key_slot( psa_key_slot_t key, /** Retrieve a slot which must contain a key. The key must have allow all the * usage flags set in \p usage. If \p alg is nonzero, the key must allow * operations with this algorithm. */ -static psa_status_t psa_get_key_from_slot( psa_key_slot_t key, +static psa_status_t psa_get_key_from_slot( psa_key_handle_t handle, key_slot_t **p_slot, psa_key_usage_t usage, psa_algorithm_t alg ) @@ -826,7 +801,7 @@ static psa_status_t psa_get_key_from_slot( psa_key_slot_t key, *p_slot = NULL; - status = psa_get_key_slot( key, &slot ); + status = psa_get_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); if( slot->type == PSA_KEY_TYPE_NONE ) @@ -896,31 +871,14 @@ static psa_status_t psa_wipe_key_slot( key_slot_t *slot ) return( status ); } -/* A slot is available if nothing has been set in it: default lifetime - * and policy, no key type. */ -static int psa_internal_is_slot_available( key_slot_t *slot ) -{ - if( slot->allocated ) - return( 0 ); - if( slot->type != PSA_KEY_TYPE_NONE ) - return( 0 ); - if( slot->lifetime != PSA_KEY_LIFETIME_VOLATILE ) - return( 0 ); - if( slot->policy.usage != 0 || slot->policy.alg != 0 ) - return( 0 ); - return( 1 ); -} - psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle ) { - psa_key_slot_t key; - for( key = PSA_KEY_SLOT_COUNT; key != 0; --( key ) ) + for( *handle = PSA_KEY_SLOT_COUNT; *handle != 0; --( *handle ) ) { - key_slot_t *slot = &global_data.key_slots[key - 1]; - if( psa_internal_is_slot_available( slot ) ) + key_slot_t *slot = &global_data.key_slots[*handle - 1]; + if( ! slot->allocated ) { slot->allocated = 1; - *handle = key | PSA_KEY_HANDLE_ALLOCATED_FLAG; return( PSA_SUCCESS ); } } @@ -941,11 +899,6 @@ psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle, * library's internal use. */ if( id >= 0xffff0000 ) return( PSA_ERROR_INVALID_ARGUMENT ); - /* Reject values that don't fit in the key slot number type. - * This is a temporary limitation due to the library's internal - * plumbing. */ - if( id > (psa_key_slot_t)( -1 ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); status = psa_get_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) @@ -960,22 +913,19 @@ psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle, psa_status_t psa_internal_release_key_slot( psa_key_handle_t handle ) { - psa_key_slot_t key; key_slot_t *slot; - /* Don't call psa_get_key_slot() so as not to trigger its automatic - * loading of persistent key data. */ - if( ( handle & PSA_KEY_HANDLE_ALLOCATED_FLAG ) == 0 ) - return( PSA_ERROR_INVALID_HANDLE ); - key = handle & ~PSA_KEY_HANDLE_ALLOCATED_FLAG; - if( key == 0 || key > ARRAY_LENGTH( global_data.key_slots ) ) - return( PSA_ERROR_INVALID_HANDLE ); - slot = &global_data.key_slots[key - 1]; + psa_status_t status; + + status = psa_get_key_slot( handle, &slot ); + if( status != PSA_SUCCESS ) + return( status ); if( ! slot->allocated ) return( PSA_ERROR_INVALID_HANDLE ); + return( psa_wipe_key_slot( slot ) ); } -psa_status_t psa_import_key( psa_key_slot_t key, +psa_status_t psa_import_key( psa_key_handle_t handle, psa_key_type_t type, const uint8_t *data, size_t data_length ) @@ -983,7 +933,7 @@ psa_status_t psa_import_key( psa_key_slot_t key, key_slot_t *slot; psa_status_t status; - status = psa_get_empty_key_slot( key, &slot ); + status = psa_get_empty_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); @@ -1014,13 +964,13 @@ psa_status_t psa_import_key( psa_key_slot_t key, return( status ); } -psa_status_t psa_destroy_key( psa_key_slot_t key ) +psa_status_t psa_destroy_key( psa_key_handle_t handle ) { key_slot_t *slot; psa_status_t status = PSA_SUCCESS; psa_status_t storage_status = PSA_SUCCESS; - status = psa_get_key_slot( key, &slot ); + status = psa_get_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) @@ -1053,7 +1003,7 @@ static size_t psa_get_key_bits( const key_slot_t *slot ) return( 0 ); } -psa_status_t psa_get_key_information( psa_key_slot_t key, +psa_status_t psa_get_key_information( psa_key_handle_t handle, psa_key_type_t *type, size_t *bits ) { @@ -1064,7 +1014,7 @@ psa_status_t psa_get_key_information( psa_key_slot_t key, *type = 0; if( bits != NULL ) *bits = 0; - status = psa_get_key_slot( key, &slot ); + status = psa_get_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); @@ -1185,7 +1135,7 @@ static psa_status_t psa_internal_export_key( key_slot_t *slot, } } -psa_status_t psa_export_key( psa_key_slot_t key, +psa_status_t psa_export_key( psa_key_handle_t handle, uint8_t *data, size_t data_size, size_t *data_length ) @@ -1202,14 +1152,14 @@ psa_status_t psa_export_key( psa_key_slot_t key, /* Export requires the EXPORT flag. There is an exception for public keys, * which don't require any flag, but psa_get_key_from_slot takes * care of this. */ - status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_EXPORT, 0 ); + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_EXPORT, 0 ); if( status != PSA_SUCCESS ) return( status ); return( psa_internal_export_key( slot, data, data_size, data_length, 0 ) ); } -psa_status_t psa_export_public_key( psa_key_slot_t key, +psa_status_t psa_export_public_key( psa_key_handle_t handle, uint8_t *data, size_t data_size, size_t *data_length ) @@ -1224,7 +1174,7 @@ psa_status_t psa_export_public_key( psa_key_slot_t key, *data_length = 0; /* Exporting a public key doesn't require a usage flag. */ - status = psa_get_key_from_slot( key, &slot, 0, 0 ); + status = psa_get_key_from_slot( handle, &slot, 0, 0 ); if( status != PSA_SUCCESS ) return( status ); return( psa_internal_export_key( slot, data, data_size, @@ -1916,7 +1866,7 @@ cleanup: #endif /* MBEDTLS_MD_C */ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg, int is_sign ) { @@ -1934,7 +1884,7 @@ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation, if( is_sign ) operation->is_sign = 1; - status = psa_get_key_from_slot( key, &slot, usage, alg ); + status = psa_get_key_from_slot( handle, &slot, usage, alg ); if( status != PSA_SUCCESS ) goto exit; key_bits = psa_get_key_bits( slot ); @@ -2027,17 +1977,17 @@ exit: } psa_status_t psa_mac_sign_setup( psa_mac_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg ) { - return( psa_mac_setup( operation, key, alg, 1 ) ); + return( psa_mac_setup( operation, handle, alg, 1 ) ); } psa_status_t psa_mac_verify_setup( psa_mac_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg ) { - return( psa_mac_setup( operation, key, alg, 0 ) ); + return( psa_mac_setup( operation, handle, alg, 0 ) ); } psa_status_t psa_mac_update( psa_mac_operation_t *operation, @@ -2494,7 +2444,7 @@ cleanup: } #endif /* MBEDTLS_ECDSA_C */ -psa_status_t psa_asymmetric_sign( psa_key_slot_t key, +psa_status_t psa_asymmetric_sign( psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, @@ -2507,7 +2457,7 @@ psa_status_t psa_asymmetric_sign( psa_key_slot_t key, *signature_length = signature_size; - status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_SIGN, alg ); + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_SIGN, alg ); if( status != PSA_SUCCESS ) goto exit; if( ! PSA_KEY_TYPE_IS_KEYPAIR( slot->type ) ) @@ -2570,7 +2520,7 @@ exit: return( status ); } -psa_status_t psa_asymmetric_verify( psa_key_slot_t key, +psa_status_t psa_asymmetric_verify( psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, @@ -2580,7 +2530,7 @@ psa_status_t psa_asymmetric_verify( psa_key_slot_t key, key_slot_t *slot; psa_status_t status; - status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_VERIFY, alg ); + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_VERIFY, alg ); if( status != PSA_SUCCESS ) return( status ); @@ -2626,7 +2576,7 @@ static void psa_rsa_oaep_set_padding_mode( psa_algorithm_t alg, } #endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) */ -psa_status_t psa_asymmetric_encrypt( psa_key_slot_t key, +psa_status_t psa_asymmetric_encrypt( psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *input, size_t input_length, @@ -2650,7 +2600,7 @@ psa_status_t psa_asymmetric_encrypt( psa_key_slot_t key, if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 ) return( PSA_ERROR_INVALID_ARGUMENT ); - status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_ENCRYPT, alg ); + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_ENCRYPT, alg ); if( status != PSA_SUCCESS ) return( status ); if( ! ( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->type ) || @@ -2706,7 +2656,7 @@ psa_status_t psa_asymmetric_encrypt( psa_key_slot_t key, } } -psa_status_t psa_asymmetric_decrypt( psa_key_slot_t key, +psa_status_t psa_asymmetric_decrypt( psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *input, size_t input_length, @@ -2730,7 +2680,7 @@ psa_status_t psa_asymmetric_decrypt( psa_key_slot_t key, if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 ) return( PSA_ERROR_INVALID_ARGUMENT ); - status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_DECRYPT, alg ); + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_DECRYPT, alg ); if( status != PSA_SUCCESS ) return( status ); if( ! PSA_KEY_TYPE_IS_KEYPAIR( slot->type ) ) @@ -2816,7 +2766,7 @@ static psa_status_t psa_cipher_init( psa_cipher_operation_t *operation, } static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg, mbedtls_operation_t cipher_operation ) { @@ -2833,7 +2783,7 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, if( status != PSA_SUCCESS ) return( status ); - status = psa_get_key_from_slot( key, &slot, usage, alg); + status = psa_get_key_from_slot( handle, &slot, usage, alg); if( status != PSA_SUCCESS ) return( status ); key_bits = psa_get_key_bits( slot ); @@ -2908,17 +2858,17 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, } psa_status_t psa_cipher_encrypt_setup( psa_cipher_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg ) { - return( psa_cipher_setup( operation, key, alg, MBEDTLS_ENCRYPT ) ); + return( psa_cipher_setup( operation, handle, alg, MBEDTLS_ENCRYPT ) ); } psa_status_t psa_cipher_decrypt_setup( psa_cipher_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg ) { - return( psa_cipher_setup( operation, key, alg, MBEDTLS_DECRYPT ) ); + return( psa_cipher_setup( operation, handle, alg, MBEDTLS_DECRYPT ) ); } psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation, @@ -3141,7 +3091,7 @@ psa_algorithm_t psa_key_policy_get_algorithm( const psa_key_policy_t *policy ) } #endif /* !defined(MBEDTLS_PSA_CRYPTO_SPM) */ -psa_status_t psa_set_key_policy( psa_key_slot_t key, +psa_status_t psa_set_key_policy( psa_key_handle_t handle, const psa_key_policy_t *policy ) { key_slot_t *slot; @@ -3150,7 +3100,7 @@ psa_status_t psa_set_key_policy( psa_key_slot_t key, if( policy == NULL ) return( PSA_ERROR_INVALID_ARGUMENT ); - status = psa_get_empty_key_slot( key, &slot ); + status = psa_get_empty_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); @@ -3167,7 +3117,7 @@ psa_status_t psa_set_key_policy( psa_key_slot_t key, return( PSA_SUCCESS ); } -psa_status_t psa_get_key_policy( psa_key_slot_t key, +psa_status_t psa_get_key_policy( psa_key_handle_t handle, psa_key_policy_t *policy ) { key_slot_t *slot; @@ -3176,7 +3126,7 @@ psa_status_t psa_get_key_policy( psa_key_slot_t key, if( policy == NULL ) return( PSA_ERROR_INVALID_ARGUMENT ); - status = psa_get_key_slot( key, &slot ); + status = psa_get_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); @@ -3191,13 +3141,13 @@ psa_status_t psa_get_key_policy( psa_key_slot_t key, /* Key Lifetime */ /****************************************************************/ -psa_status_t psa_get_key_lifetime( psa_key_slot_t key, +psa_status_t psa_get_key_lifetime( psa_key_handle_t handle, psa_key_lifetime_t *lifetime ) { key_slot_t *slot; psa_status_t status; - status = psa_get_key_slot( key, &slot ); + status = psa_get_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); @@ -3248,7 +3198,7 @@ static void psa_aead_abort( aead_operation_t *operation ) } static psa_status_t psa_aead_setup( aead_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_key_usage_t usage, psa_algorithm_t alg ) { @@ -3256,7 +3206,7 @@ static psa_status_t psa_aead_setup( aead_operation_t *operation, size_t key_bits; mbedtls_cipher_id_t cipher_id; - status = psa_get_key_from_slot( key, &operation->slot, usage, alg ); + status = psa_get_key_from_slot( handle, &operation->slot, usage, alg ); if( status != PSA_SUCCESS ) return( status ); @@ -3321,7 +3271,7 @@ cleanup: return( status ); } -psa_status_t psa_aead_encrypt( psa_key_slot_t key, +psa_status_t psa_aead_encrypt( psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, @@ -3339,7 +3289,7 @@ psa_status_t psa_aead_encrypt( psa_key_slot_t key, *ciphertext_length = 0; - status = psa_aead_setup( &operation, key, PSA_KEY_USAGE_ENCRYPT, alg ); + status = psa_aead_setup( &operation, handle, PSA_KEY_USAGE_ENCRYPT, alg ); if( status != PSA_SUCCESS ) return( status ); @@ -3415,7 +3365,7 @@ static psa_status_t psa_aead_unpadded_locate_tag( size_t tag_length, return( PSA_SUCCESS ); } -psa_status_t psa_aead_decrypt( psa_key_slot_t key, +psa_status_t psa_aead_decrypt( psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, @@ -3433,7 +3383,7 @@ psa_status_t psa_aead_decrypt( psa_key_slot_t key, *plaintext_length = 0; - status = psa_aead_setup( &operation, key, PSA_KEY_USAGE_DECRYPT, alg ); + status = psa_aead_setup( &operation, handle, PSA_KEY_USAGE_DECRYPT, alg ); if( status != PSA_SUCCESS ) return( status ); @@ -3862,7 +3812,7 @@ static void psa_des_set_key_parity( uint8_t *data, size_t data_size ) } #endif /* MBEDTLS_DES_C */ -psa_status_t psa_generator_import_key( psa_key_slot_t key, +psa_status_t psa_generator_import_key( psa_key_handle_t handle, psa_key_type_t type, size_t bits, psa_crypto_generator_t *generator ) @@ -3886,7 +3836,7 @@ psa_status_t psa_generator_import_key( psa_key_slot_t key, if( type == PSA_KEY_TYPE_DES ) psa_des_set_key_parity( data, bytes ); #endif /* MBEDTLS_DES_C */ - status = psa_import_key( key, type, data, bytes ); + status = psa_import_key( handle, type, data, bytes ); exit: mbedtls_free( data ); @@ -4143,7 +4093,7 @@ static psa_status_t psa_key_derivation_internal( } psa_status_t psa_key_derivation( psa_crypto_generator_t *generator, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *salt, size_t salt_length, @@ -4163,7 +4113,7 @@ psa_status_t psa_key_derivation( psa_crypto_generator_t *generator, if( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ) return( PSA_ERROR_INVALID_ARGUMENT ); - status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_DERIVE, alg ); + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_DERIVE, alg ); if( status != PSA_SUCCESS ) return( status ); @@ -4294,7 +4244,7 @@ exit: } psa_status_t psa_key_agreement( psa_crypto_generator_t *generator, - psa_key_slot_t private_key, + psa_key_handle_t private_key, const uint8_t *peer_key, size_t peer_key_length, psa_algorithm_t alg ) @@ -4399,7 +4349,7 @@ psa_status_t mbedtls_psa_inject_entropy( const unsigned char *seed, } #endif -psa_status_t psa_generate_key( psa_key_slot_t key, +psa_status_t psa_generate_key( psa_key_handle_t handle, psa_key_type_t type, size_t bits, const void *extra, @@ -4411,7 +4361,7 @@ psa_status_t psa_generate_key( psa_key_slot_t key, if( extra == NULL && extra_size != 0 ) return( PSA_ERROR_INVALID_ARGUMENT ); - status = psa_get_empty_key_slot( key, &slot ); + status = psa_get_empty_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); @@ -4547,7 +4497,7 @@ void mbedtls_psa_crypto_free( void ) { if( global_data.key_slots_initialized ) { - psa_key_slot_t key; + psa_key_handle_t key; for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ ) { key_slot_t *slot = &global_data.key_slots[key - 1]; diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h index 36917bbaa..cf244f266 100644 --- a/library/psa_crypto_slot_management.h +++ b/library/psa_crypto_slot_management.h @@ -26,9 +26,6 @@ * The value is a compile-time constant for now, for simplicity. */ #define PSA_KEY_SLOT_COUNT 32 -/* All dynamically allocated handles have this bit set. */ -#define PSA_KEY_HANDLE_ALLOCATED_FLAG ( (psa_key_handle_t) 0x8000 ) - /** \defgroup core_slot_management Internal functions exposed by the core * @{ */ diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 9801a8db7..848e8edfd 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -30,11 +30,10 @@ depends_on:MBEDTLS_AES_C import_key_nonempty_slot PSA export invalid handle (0) -export_invalid_handle:0:PSA_ERROR_INVALID_ARGUMENT +export_invalid_handle:0:PSA_ERROR_INVALID_HANDLE PSA export invalid handle (smallest plausible handle) -# EMPTY_SLOT is temporary, because this valie is treated as a numbered slot, not as a handle -export_invalid_handle:1:PSA_ERROR_EMPTY_SLOT +export_invalid_handle:1:PSA_ERROR_INVALID_HANDLE PSA export invalid handle (largest plausible handle) export_invalid_handle:-1:PSA_ERROR_INVALID_HANDLE diff --git a/tests/suites/test_suite_psa_crypto_slot_management.function b/tests/suites/test_suite_psa_crypto_slot_management.function index 1f1984e3f..753a70564 100644 --- a/tests/suites/test_suite_psa_crypto_slot_management.function +++ b/tests/suites/test_suite_psa_crypto_slot_management.function @@ -321,10 +321,7 @@ void invalid_handle( ) TEST_ASSERT( psa_close_key( 0 ) == PSA_ERROR_INVALID_HANDLE ); TEST_ASSERT( psa_close_key( handle1 - 1 ) == PSA_ERROR_INVALID_HANDLE ); TEST_ASSERT( psa_close_key( handle1 + 1 ) == PSA_ERROR_INVALID_HANDLE ); - /* At the moment the implementation returns INVALID_ARGUMENT for 0 - * because of the transitional support for non-allocated slot numbers. - * When this is removed, the error will switch to INVALID_HANDLE. */ - TEST_ASSERT( psa_destroy_key( 0 ) == PSA_ERROR_INVALID_ARGUMENT ); + TEST_ASSERT( psa_destroy_key( 0 ) == PSA_ERROR_INVALID_HANDLE ); TEST_ASSERT( psa_destroy_key( handle1 - 1 ) == PSA_ERROR_INVALID_HANDLE ); TEST_ASSERT( psa_destroy_key( handle1 + 1 ) == PSA_ERROR_INVALID_HANDLE ); From 4a044739a8443fcfbb9cf9d89f862389b3dd3066 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 3 Dec 2018 18:19:39 +0100 Subject: [PATCH 22/35] Fix the build without persistent storage Add missing guards on MBEDTLS_PSA_CRYPTO_STORAGE_C. Add test cases to test that psa_create_key and psa_open_key return NOT_SUPPORTED. --- library/psa_crypto.c | 7 +++++++ .../test_suite_psa_crypto_slot_management.data | 13 +++++++++++++ .../test_suite_psa_crypto_slot_management.function | 10 ++++++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index ce9e3e5f2..c67c8a798 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -888,6 +888,7 @@ psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle ) psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle, psa_key_id_t id ) { +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) key_slot_t *slot; psa_status_t status; @@ -909,6 +910,12 @@ psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle, status = psa_load_persistent_key_into_slot( slot ); return( status ); + +#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ + (void) handle; + (void) id; + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */ } psa_status_t psa_internal_release_key_slot( psa_key_handle_t handle ) diff --git a/tests/suites/test_suite_psa_crypto_slot_management.data b/tests/suites/test_suite_psa_crypto_slot_management.data index 133f4c873..39e05abf8 100644 --- a/tests/suites/test_suite_psa_crypto_slot_management.data +++ b/tests/suites/test_suite_psa_crypto_slot_management.data @@ -38,20 +38,33 @@ depends_on:MBEDTLS_AES_C create_existent:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_AES:KEEP_OPEN Open failure: non-existent identifier +depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C open_fail:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_ERROR_EMPTY_SLOT Open failure: volatile lifetime +depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C open_fail:PSA_KEY_LIFETIME_VOLATILE:1:PSA_ERROR_INVALID_ARGUMENT Open failure: invalid lifetime +depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C open_fail:0x7fffffff:0:PSA_ERROR_INVALID_ARGUMENT Create failure: volatile lifetime +depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C create_fail:PSA_KEY_LIFETIME_VOLATILE:1:PSA_KEY_TYPE_RAW_DATA:8:PSA_ERROR_INVALID_ARGUMENT Create failure: invalid lifetime +depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C create_fail:0x7fffffff:0:PSA_KEY_TYPE_RAW_DATA:8:PSA_ERROR_INVALID_ARGUMENT +Open not supported +depends_on:!MBEDTLS_PSA_CRYPTO_STORAGE_C +open_fail:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_ERROR_NOT_SUPPORTED + +Create not supported +depends_on:!MBEDTLS_PSA_CRYPTO_STORAGE_C +create_fail:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_RAW_DATA:8:PSA_ERROR_NOT_SUPPORTED + Close/destroy invalid handle invalid_handle: diff --git a/tests/suites/test_suite_psa_crypto_slot_management.function b/tests/suites/test_suite_psa_crypto_slot_management.function index 753a70564..754aae08d 100644 --- a/tests/suites/test_suite_psa_crypto_slot_management.function +++ b/tests/suites/test_suite_psa_crypto_slot_management.function @@ -29,6 +29,7 @@ typedef enum * identifier, and must call psa_purge_key_storage() in their cleanup * code. */ +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) /* There is no API to purge all keys. For this test suite, require that * all key IDs be less than a certain maximum. */ #define MAX_KEY_ID_FOR_TEST 32 @@ -43,6 +44,9 @@ void psa_purge_key_storage( void ) for( i = 0; i <= MAX_KEY_ID_FOR_TEST; i++ ) psa_destroy_persistent_key( i ); } +#else +#define TEST_MAX_KEY_ID( key_id ) ( (void) ( key_id ) ) +#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ static int psa_key_policy_equal( psa_key_policy_t *p1, psa_key_policy_t *p2 ) @@ -109,7 +113,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */ void persistent_slot_lifecycle( int lifetime_arg, int id_arg, int type_arg, int max_bits_arg, int alg_arg, int usage_arg, @@ -188,7 +192,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */ void create_existent( int lifetime_arg, int id_arg, int new_type_arg, int reopen_policy_arg ) @@ -293,7 +297,9 @@ void create_fail( int lifetime_arg, int id_arg, exit: mbedtls_psa_crypto_free( ); +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) psa_purge_key_storage( ); +#endif } /* END_CASE */ From 2f060a8ea54ead4912d5ad8ab5cebc16513dbdc4 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 4 Dec 2018 17:12:32 +0100 Subject: [PATCH 23/35] Rename key_slot_t to psa_key_slot_t in psa_crypto.c That way it'll be ok to add it to an internal header so as to use it in multiple source modules. --- library/psa_crypto.c | 78 ++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index c67c8a798..3e08657db 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -139,7 +139,7 @@ typedef struct mbedtls_ecp_keypair *ecp; #endif /* MBEDTLS_ECP_C */ } data; -} key_slot_t; +} psa_key_slot_t; static int key_type_is_raw_bytes( psa_key_type_t type ) { @@ -157,7 +157,7 @@ typedef struct void (* entropy_free )( mbedtls_entropy_context *ctx ); mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; - key_slot_t key_slots[PSA_KEY_SLOT_COUNT]; + psa_key_slot_t key_slots[PSA_KEY_SLOT_COUNT]; unsigned initialized : 1; unsigned rng_state : 2; unsigned key_slots_initialized : 1; @@ -640,7 +640,7 @@ exit: /** Import key data into a slot. `slot->type` must have been set * previously. This function assumes that the slot does not contain * any key material yet. On failure, the slot content is unchanged. */ -static psa_status_t psa_import_key_into_slot( key_slot_t *slot, +static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, const uint8_t *data, size_t data_length ) { @@ -722,7 +722,7 @@ static psa_status_t psa_import_key_into_slot( key_slot_t *slot, } #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) -static psa_status_t psa_load_persistent_key_into_slot( key_slot_t *p_slot ) +static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *p_slot ) { psa_status_t status = PSA_SUCCESS; uint8_t *key_data = NULL; @@ -746,9 +746,9 @@ exit: * the index of the slot in the global slot array, plus one so that handles * start at 1 and not 0. */ static psa_status_t psa_get_key_slot( psa_key_handle_t handle, - key_slot_t **p_slot ) + psa_key_slot_t **p_slot ) { - key_slot_t *slot = NULL; + psa_key_slot_t *slot = NULL; GUARD_MODULE_INITIALIZED; @@ -770,10 +770,10 @@ static psa_status_t psa_get_key_slot( psa_key_handle_t handle, /* Retrieve an empty key slot (slot with no key data, but possibly * with some metadata such as a policy). */ static psa_status_t psa_get_empty_key_slot( psa_key_handle_t handle, - key_slot_t **p_slot ) + psa_key_slot_t **p_slot ) { psa_status_t status; - key_slot_t *slot = NULL; + psa_key_slot_t *slot = NULL; *p_slot = NULL; @@ -792,12 +792,12 @@ static psa_status_t psa_get_empty_key_slot( psa_key_handle_t handle, * usage flags set in \p usage. If \p alg is nonzero, the key must allow * operations with this algorithm. */ static psa_status_t psa_get_key_from_slot( psa_key_handle_t handle, - key_slot_t **p_slot, + psa_key_slot_t **p_slot, psa_key_usage_t usage, psa_algorithm_t alg ) { psa_status_t status; - key_slot_t *slot = NULL; + psa_key_slot_t *slot = NULL; *p_slot = NULL; @@ -823,7 +823,7 @@ static psa_status_t psa_get_key_from_slot( psa_key_handle_t handle, } /** Wipe key data from a slot. Preserve metadata such as the policy. */ -static psa_status_t psa_remove_key_data_from_memory( key_slot_t *slot ) +static psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot ) { if( slot->type == PSA_KEY_TYPE_NONE ) { @@ -861,7 +861,7 @@ static psa_status_t psa_remove_key_data_from_memory( key_slot_t *slot ) /** Completely wipe a slot in memory, including its policy. * Persistent storage is not affected. */ -static psa_status_t psa_wipe_key_slot( key_slot_t *slot ) +static psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ) { psa_status_t status = psa_remove_key_data_from_memory( slot ); /* At this point, key material and other type-specific content has @@ -875,7 +875,7 @@ psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle ) { for( *handle = PSA_KEY_SLOT_COUNT; *handle != 0; --( *handle ) ) { - key_slot_t *slot = &global_data.key_slots[*handle - 1]; + psa_key_slot_t *slot = &global_data.key_slots[*handle - 1]; if( ! slot->allocated ) { slot->allocated = 1; @@ -889,7 +889,7 @@ psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle, psa_key_id_t id ) { #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; /* Reject id=0 because by general library conventions, 0 is an invalid @@ -920,7 +920,7 @@ psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle, psa_status_t psa_internal_release_key_slot( psa_key_handle_t handle ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; status = psa_get_key_slot( handle, &slot ); @@ -937,7 +937,7 @@ psa_status_t psa_import_key( psa_key_handle_t handle, const uint8_t *data, size_t data_length ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; status = psa_get_empty_key_slot( handle, &slot ); @@ -973,7 +973,7 @@ psa_status_t psa_import_key( psa_key_handle_t handle, psa_status_t psa_destroy_key( psa_key_handle_t handle ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status = PSA_SUCCESS; psa_status_t storage_status = PSA_SUCCESS; @@ -994,7 +994,7 @@ psa_status_t psa_destroy_key( psa_key_handle_t handle ) } /* Return the size of the key in the given slot, in bits. */ -static size_t psa_get_key_bits( const key_slot_t *slot ) +static size_t psa_get_key_bits( const psa_key_slot_t *slot ) { if( key_type_is_raw_bytes( slot->type ) ) return( slot->data.raw.bytes * 8 ); @@ -1014,7 +1014,7 @@ psa_status_t psa_get_key_information( psa_key_handle_t handle, psa_key_type_t *type, size_t *bits ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; if( type != NULL ) @@ -1034,7 +1034,7 @@ psa_status_t psa_get_key_information( psa_key_handle_t handle, return( PSA_SUCCESS ); } -static psa_status_t psa_internal_export_key( key_slot_t *slot, +static psa_status_t psa_internal_export_key( psa_key_slot_t *slot, uint8_t *data, size_t data_size, size_t *data_length, @@ -1147,7 +1147,7 @@ psa_status_t psa_export_key( psa_key_handle_t handle, size_t data_size, size_t *data_length ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; /* Set the key to empty now, so that even when there are errors, we always @@ -1171,7 +1171,7 @@ psa_status_t psa_export_public_key( psa_key_handle_t handle, size_t data_size, size_t *data_length ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; /* Set the key to empty now, so that even when there are errors, we always @@ -1189,7 +1189,7 @@ psa_status_t psa_export_public_key( psa_key_handle_t handle, } #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) -static psa_status_t psa_save_generated_persistent_key( key_slot_t *slot, +static psa_status_t psa_save_generated_persistent_key( psa_key_slot_t *slot, size_t bits ) { psa_status_t status; @@ -1784,7 +1784,7 @@ bad_state: #if defined(MBEDTLS_CMAC_C) static int psa_cmac_setup( psa_mac_operation_t *operation, size_t key_bits, - key_slot_t *slot, + psa_key_slot_t *slot, const mbedtls_cipher_info_t *cipher_info ) { int ret; @@ -1878,7 +1878,7 @@ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation, int is_sign ) { psa_status_t status; - key_slot_t *slot; + psa_key_slot_t *slot; size_t key_bits; psa_key_usage_t usage = is_sign ? PSA_KEY_USAGE_SIGN : PSA_KEY_USAGE_VERIFY; @@ -2459,7 +2459,7 @@ psa_status_t psa_asymmetric_sign( psa_key_handle_t handle, size_t signature_size, size_t *signature_length ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; *signature_length = signature_size; @@ -2534,7 +2534,7 @@ psa_status_t psa_asymmetric_verify( psa_key_handle_t handle, const uint8_t *signature, size_t signature_length ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_VERIFY, alg ); @@ -2593,7 +2593,7 @@ psa_status_t psa_asymmetric_encrypt( psa_key_handle_t handle, size_t output_size, size_t *output_length ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; (void) input; @@ -2673,7 +2673,7 @@ psa_status_t psa_asymmetric_decrypt( psa_key_handle_t handle, size_t output_size, size_t *output_length ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; (void) input; @@ -2779,7 +2779,7 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, { int ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; psa_status_t status; - key_slot_t *slot; + psa_key_slot_t *slot; size_t key_bits; const mbedtls_cipher_info_t *cipher_info = NULL; psa_key_usage_t usage = ( cipher_operation == MBEDTLS_ENCRYPT ? @@ -3101,7 +3101,7 @@ psa_algorithm_t psa_key_policy_get_algorithm( const psa_key_policy_t *policy ) psa_status_t psa_set_key_policy( psa_key_handle_t handle, const psa_key_policy_t *policy ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; if( policy == NULL ) @@ -3127,7 +3127,7 @@ psa_status_t psa_set_key_policy( psa_key_handle_t handle, psa_status_t psa_get_key_policy( psa_key_handle_t handle, psa_key_policy_t *policy ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; if( policy == NULL ) @@ -3151,7 +3151,7 @@ psa_status_t psa_get_key_policy( psa_key_handle_t handle, psa_status_t psa_get_key_lifetime( psa_key_handle_t handle, psa_key_lifetime_t *lifetime ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; status = psa_get_key_slot( handle, &slot ); @@ -3171,7 +3171,7 @@ psa_status_t psa_get_key_lifetime( psa_key_handle_t handle, typedef struct { - key_slot_t *slot; + psa_key_slot_t *slot; const mbedtls_cipher_info_t *cipher_info; union { @@ -4108,7 +4108,7 @@ psa_status_t psa_key_derivation( psa_crypto_generator_t *generator, size_t label_length, size_t capacity ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; if( generator->alg != 0 ) @@ -4205,7 +4205,7 @@ exit: * to potentially free embedded data structures and wipe confidential data. */ static psa_status_t psa_key_agreement_internal( psa_crypto_generator_t *generator, - key_slot_t *private_key, + psa_key_slot_t *private_key, const uint8_t *peer_key, size_t peer_key_length, psa_algorithm_t alg ) @@ -4256,7 +4256,7 @@ psa_status_t psa_key_agreement( psa_crypto_generator_t *generator, size_t peer_key_length, psa_algorithm_t alg ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; if( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ) return( PSA_ERROR_INVALID_ARGUMENT ); @@ -4362,7 +4362,7 @@ psa_status_t psa_generate_key( psa_key_handle_t handle, const void *extra, size_t extra_size ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; if( extra == NULL && extra_size != 0 ) @@ -4507,7 +4507,7 @@ void mbedtls_psa_crypto_free( void ) psa_key_handle_t key; for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ ) { - key_slot_t *slot = &global_data.key_slots[key - 1]; + psa_key_slot_t *slot = &global_data.key_slots[key - 1]; (void) psa_wipe_key_slot( slot ); } } From fe9756b1f59c3c5290bf40c90ab27074231828b8 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 7 Dec 2018 18:12:28 +0100 Subject: [PATCH 24/35] Remove a comment that is no longer applicable --- library/psa_crypto.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 3e08657db..1b44fc61e 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -4551,8 +4551,7 @@ psa_status_t psa_crypto_init( void ) global_data.rng_state = RNG_SEEDED; /* Initialize the key slots. Zero-initialization has made all key - * slots empty, so there is nothing to do. In a future version we will - * load data from storage. */ + * slots empty, so there is nothing to do. */ global_data.key_slots_initialized = 1; /* All done. */ From 3f10812ff998055c36a0697e1f5687119954d7c6 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 7 Dec 2018 18:14:53 +0100 Subject: [PATCH 25/35] Use the library-wide zeroize function Since Mbed TLS 2.10, there is a single copy of mbedtls_platform_zeroize for the whole library instead of one per module. Update the PSA crypto module accordingly. --- library/psa_crypto.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 1b44fc61e..afb4d325c 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -81,6 +81,7 @@ #include "mbedtls/md_internal.h" #include "mbedtls/pk.h" #include "mbedtls/pk_internal.h" +#include "mbedtls/platform_util.h" #include "mbedtls/ripemd160.h" #include "mbedtls/rsa.h" #include "mbedtls/sha1.h" @@ -94,12 +95,6 @@ #define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) ) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) -{ - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* constant-time buffer comparison */ static inline int safer_memcmp( const uint8_t *a, const uint8_t *b, size_t n ) { @@ -1215,7 +1210,7 @@ static psa_status_t psa_save_generated_persistent_key( psa_key_slot_t *slot, slot->type = PSA_KEY_TYPE_NONE; } exit: - mbedtls_zeroize( data, key_length ); + mbedtls_platform_zeroize( data, key_length ); mbedtls_free( data ); return( status ); } @@ -1722,7 +1717,7 @@ static psa_status_t psa_mac_init( psa_mac_operation_t *operation, #if defined(MBEDTLS_MD_C) static psa_status_t psa_hmac_abort_internal( psa_hmac_internal_data *hmac ) { - mbedtls_zeroize( hmac->opad, sizeof( hmac->opad ) ); + mbedtls_platform_zeroize( hmac->opad, sizeof( hmac->opad ) ); return( psa_hash_abort( &hmac->hash_ctx ) ); } @@ -1866,7 +1861,7 @@ static psa_status_t psa_hmac_setup_internal( psa_hmac_internal_data *hmac, status = psa_hash_update( &hmac->hash_ctx, ipad, block_size ); cleanup: - mbedtls_zeroize( ipad, key_length ); + mbedtls_platform_zeroize( ipad, key_length ); return( status ); } @@ -2072,7 +2067,7 @@ static psa_status_t psa_hmac_finish_internal( psa_hmac_internal_data *hmac, memcpy( mac, tmp, mac_size ); exit: - mbedtls_zeroize( tmp, hash_size ); + mbedtls_platform_zeroize( tmp, hash_size ); return( status ); } #endif /* MBEDTLS_MD_C */ @@ -2096,7 +2091,7 @@ static psa_status_t psa_mac_finish_internal( psa_mac_operation_t *operation, int ret = mbedtls_cipher_cmac_finish( &operation->ctx.cmac, tmp ); if( ret == 0 ) memcpy( mac, tmp, operation->mac_size ); - mbedtls_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); return( mbedtls_to_psa_error( ret ) ); } else @@ -2184,7 +2179,7 @@ cleanup: else psa_mac_abort( operation ); - mbedtls_zeroize( actual_mac, sizeof( actual_mac ) ); + mbedtls_platform_zeroize( actual_mac, sizeof( actual_mac ) ); return( status ); } @@ -3025,7 +3020,7 @@ psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, goto error; } - mbedtls_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); + mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); status = psa_cipher_abort( operation ); return( status ); @@ -3034,7 +3029,7 @@ error: *output_length = 0; - mbedtls_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); + mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); (void) psa_cipher_abort( operation ); return( status ); @@ -3468,7 +3463,7 @@ psa_status_t psa_generator_abort( psa_crypto_generator_t *generator ) { if( generator->ctx.buffer.data != NULL ) { - mbedtls_zeroize( generator->ctx.buffer.data, + mbedtls_platform_zeroize( generator->ctx.buffer.data, generator->ctx.buffer.size ); mbedtls_free( generator->ctx.buffer.data ); } @@ -3486,14 +3481,14 @@ psa_status_t psa_generator_abort( psa_crypto_generator_t *generator ) { if( generator->ctx.tls12_prf.key != NULL ) { - mbedtls_zeroize( generator->ctx.tls12_prf.key, + mbedtls_platform_zeroize( generator->ctx.tls12_prf.key, generator->ctx.tls12_prf.key_len ); mbedtls_free( generator->ctx.tls12_prf.key ); } if( generator->ctx.tls12_prf.Ai_with_seed != NULL ) { - mbedtls_zeroize( generator->ctx.tls12_prf.Ai_with_seed, + mbedtls_platform_zeroize( generator->ctx.tls12_prf.Ai_with_seed, generator->ctx.tls12_prf.Ai_with_seed_len ); mbedtls_free( generator->ctx.tls12_prf.Ai_with_seed ); } @@ -3995,7 +3990,7 @@ static psa_status_t psa_generator_tls12_psk_to_ms_setup( salt, salt_length, label, label_length ); - mbedtls_zeroize( pms, sizeof( pms ) ); + mbedtls_platform_zeroize( pms, sizeof( pms ) ); return( status ); } #endif /* MBEDTLS_MD_C */ @@ -4246,7 +4241,7 @@ static psa_status_t psa_key_agreement_internal( psa_crypto_generator_t *generato NULL, 0, NULL, 0, PSA_GENERATOR_UNBRIDLED_CAPACITY ); exit: - mbedtls_zeroize( shared_secret, shared_secret_length ); + mbedtls_platform_zeroize( shared_secret, shared_secret_length ); return( status ); } @@ -4519,7 +4514,7 @@ void mbedtls_psa_crypto_free( void ) /* Wipe all remaining data, including configuration. * In particular, this sets all state indicator to the value * indicating "uninitialized". */ - mbedtls_zeroize( &global_data, sizeof( global_data ) ); + mbedtls_platform_zeroize( &global_data, sizeof( global_data ) ); } psa_status_t psa_crypto_init( void ) From 039b90cf5b30855ebd10d0cbcdb395f6793e9a23 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 7 Dec 2018 18:24:41 +0100 Subject: [PATCH 26/35] Expose the PSA key slot structure to internal modules Move psa_key_slot_t to a new header psa_crypto_core.h, to prepare for moving the responsibility for some fields to psa_crypto_slot_management.c. --- library/psa_crypto.c | 24 +------------ library/psa_crypto_core.h | 62 ++++++++++++++++++++++++++++++++++ visualc/VS2010/mbedTLS.vcxproj | 1 + 3 files changed, 64 insertions(+), 23 deletions(-) create mode 100644 library/psa_crypto_core.h diff --git a/library/psa_crypto.c b/library/psa_crypto.c index afb4d325c..2712c6778 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -43,6 +43,7 @@ #include "psa/crypto.h" +#include "psa_crypto_core.h" #include "psa_crypto_invasive.h" #include "psa_crypto_slot_management.h" /* Include internal declarations that are useful for implementing persistently @@ -113,29 +114,6 @@ static inline int safer_memcmp( const uint8_t *a, const uint8_t *b, size_t n ) /* Global data, support functions and library management */ /****************************************************************/ -typedef struct -{ - psa_key_type_t type; - psa_key_policy_t policy; - psa_key_lifetime_t lifetime; - psa_key_id_t persistent_storage_id; - unsigned allocated : 1; - union - { - struct raw_data - { - uint8_t *data; - size_t bytes; - } raw; -#if defined(MBEDTLS_RSA_C) - mbedtls_rsa_context *rsa; -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) - mbedtls_ecp_keypair *ecp; -#endif /* MBEDTLS_ECP_C */ - } data; -} psa_key_slot_t; - static int key_type_is_raw_bytes( psa_key_type_t type ) { return( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) ); diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h new file mode 100644 index 000000000..de877d344 --- /dev/null +++ b/library/psa_crypto_core.h @@ -0,0 +1,62 @@ +/* + * PSA crypto core internal interfaces + */ +/* Copyright (C) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_CORE_H +#define PSA_CRYPTO_CORE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "psa/crypto.h" + +#include "mbedtls/ecp.h" +#include "mbedtls/rsa.h" + +/** The data structure representing a key slot, containing key material + * and metadata for one key. + */ +typedef struct +{ + psa_key_type_t type; + psa_key_policy_t policy; + psa_key_lifetime_t lifetime; + psa_key_id_t persistent_storage_id; + unsigned allocated : 1; + union + { + struct raw_data + { + uint8_t *data; + size_t bytes; + } raw; +#if defined(MBEDTLS_RSA_C) + mbedtls_rsa_context *rsa; +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + mbedtls_ecp_keypair *ecp; +#endif /* MBEDTLS_ECP_C */ + } data; +} psa_key_slot_t; + +#endif /* PSA_CRYPTO_CORE_H */ diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj index 341e058a8..366b97e55 100644 --- a/visualc/VS2010/mbedTLS.vcxproj +++ b/visualc/VS2010/mbedTLS.vcxproj @@ -231,6 +231,7 @@ + From 48868129cde07ad7bd54d0cd8fdc948850fc43b8 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 10 Dec 2018 17:30:29 +0100 Subject: [PATCH 27/35] Document the maximum key identifier Give it a name and explain why it was chosen. --- library/psa_crypto.c | 2 +- library/psa_crypto_storage.h | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 2712c6778..d272334d4 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -871,7 +871,7 @@ psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle, return( PSA_ERROR_INVALID_ARGUMENT ); /* Reject high values because the file names are reserved for the * library's internal use. */ - if( id >= 0xffff0000 ) + if( id >= PSA_MAX_PERSISTENT_KEY_IDENTIFIER ) return( PSA_ERROR_INVALID_ARGUMENT ); status = psa_get_key_slot( handle, &slot ); diff --git a/library/psa_crypto_storage.h b/library/psa_crypto_storage.h index 478daef8f..85881c164 100644 --- a/library/psa_crypto_storage.h +++ b/library/psa_crypto_storage.h @@ -44,6 +44,23 @@ extern "C" { * inadvertently store an obscene amount of data) */ #define PSA_CRYPTO_MAX_STORAGE_SIZE ( 30 * 1024 ) +/** The maximum permitted persistent slot number. + * + * In Mbed Crypto 0.1.0b: + * - Using the file backend, all key ids are ok except 0. + * - Using the ITS backend, all key ids are ok except 0xFFFFFF52 + * (#PSA_CRYPTO_ITS_RANDOM_SEED_UID) for which the file contains the + * device's random seed (if this feature is enabled). + * - Only key ids from 1 to #PSA_KEY_SLOT_COUNT are actually used. + * + * Since we need to preserve the random seed, avoid using that key slot. + * Reserve a whole range of key slots just in case something else comes up. + * + * This limitation will probably become moot when we implement client + * separation for key storage. + */ +#define PSA_MAX_PERSISTENT_KEY_IDENTIFIER 0xffff0000 + /** * \brief Format key data and metadata and save to a location for given key * slot. From 539cda57df9a7f36b03b46075016a6ce91166760 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 10 Dec 2018 17:31:59 +0100 Subject: [PATCH 28/35] Add tests with invalid key identifiers Test that 0 and PSA_CRYPTO_ITS_RANDOM_SEED_UID are not accepted as key identifiers. --- .../test_suite_psa_crypto_slot_management.data | 16 ++++++++++++++++ ...est_suite_psa_crypto_slot_management.function | 8 ++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto_slot_management.data b/tests/suites/test_suite_psa_crypto_slot_management.data index 39e05abf8..46dbea2c0 100644 --- a/tests/suites/test_suite_psa_crypto_slot_management.data +++ b/tests/suites/test_suite_psa_crypto_slot_management.data @@ -37,6 +37,14 @@ Attempt to overwrite: keep open, different type depends_on:MBEDTLS_AES_C create_existent:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_AES:KEEP_OPEN +Open failure: invalid identifier (0) +depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C +open_fail:PSA_KEY_LIFETIME_PERSISTENT:0:PSA_ERROR_INVALID_ARGUMENT + +Open failure: invalid identifier (random seed UID) +depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C +open_fail:PSA_KEY_LIFETIME_PERSISTENT:PSA_CRYPTO_ITS_RANDOM_SEED_UID:PSA_ERROR_INVALID_ARGUMENT + Open failure: non-existent identifier depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C open_fail:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_ERROR_EMPTY_SLOT @@ -57,6 +65,14 @@ Create failure: invalid lifetime depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C create_fail:0x7fffffff:0:PSA_KEY_TYPE_RAW_DATA:8:PSA_ERROR_INVALID_ARGUMENT +Create failure: invalid key id (0) +depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C +create_fail:PSA_KEY_LIFETIME_PERSISTENT:0:PSA_KEY_TYPE_RAW_DATA:8:PSA_ERROR_INVALID_ARGUMENT + +Create failure: invalid key id (random seed UID) +depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C +create_fail:PSA_KEY_LIFETIME_PERSISTENT:PSA_CRYPTO_ITS_RANDOM_SEED_UID:PSA_KEY_TYPE_RAW_DATA:8:PSA_ERROR_INVALID_ARGUMENT + Open not supported depends_on:!MBEDTLS_PSA_CRYPTO_STORAGE_C open_fail:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_ERROR_NOT_SUPPORTED diff --git a/tests/suites/test_suite_psa_crypto_slot_management.function b/tests/suites/test_suite_psa_crypto_slot_management.function index 754aae08d..fdcb5a949 100644 --- a/tests/suites/test_suite_psa_crypto_slot_management.function +++ b/tests/suites/test_suite_psa_crypto_slot_management.function @@ -31,10 +31,14 @@ typedef enum #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) /* There is no API to purge all keys. For this test suite, require that - * all key IDs be less than a certain maximum. */ + * all key IDs be less than a certain maximum, or a well-known value + * which corresponds to a file that does not contain a key. */ #define MAX_KEY_ID_FOR_TEST 32 +#define KEY_ID_IS_WELL_KNOWN( key_id ) \ + ( ( key_id ) == PSA_CRYPTO_ITS_RANDOM_SEED_UID ) #define TEST_MAX_KEY_ID( key_id ) \ - TEST_ASSERT( ( key_id ) <= MAX_KEY_ID_FOR_TEST ) + TEST_ASSERT( ( key_id ) <= MAX_KEY_ID_FOR_TEST || \ + KEY_ID_IS_WELL_KNOWN( key_id ) ) void psa_purge_key_storage( void ) { psa_key_id_t i; From 408319be3ab32f70af5b0d1fa6a9942ec64fe37d Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 10 Dec 2018 17:34:00 +0100 Subject: [PATCH 29/35] Remove redundant check for slot->allocated This check became redundant when support for direct access to key slots was removed. --- library/psa_crypto.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index d272334d4..554da4bb4 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -899,8 +899,6 @@ psa_status_t psa_internal_release_key_slot( psa_key_handle_t handle ) status = psa_get_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); - if( ! slot->allocated ) - return( PSA_ERROR_INVALID_HANDLE ); return( psa_wipe_key_slot( slot ) ); } From 66fb126e87bb5ff67cc0fbe31ad2a4cc5c6ca08b Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 10 Dec 2018 16:29:04 +0100 Subject: [PATCH 30/35] Move the key slot array to the slot management module Move the key slot array and its initialization and wiping to the slot management module. Also move the lowest-level key slot access function psa_get_key_slot and the auxiliary function for slot allocation psa_internal_allocate_key_slot to the slot management module. --- library/psa_crypto.c | 76 +++++----------------------- library/psa_crypto_core.h | 4 ++ library/psa_crypto_slot_management.c | 76 ++++++++++++++++++++++++++++ library/psa_crypto_slot_management.h | 20 ++++---- 4 files changed, 105 insertions(+), 71 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 554da4bb4..0ac1c2707 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -130,10 +130,8 @@ typedef struct void (* entropy_free )( mbedtls_entropy_context *ctx ); mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; - psa_key_slot_t key_slots[PSA_KEY_SLOT_COUNT]; unsigned initialized : 1; unsigned rng_state : 2; - unsigned key_slots_initialized : 1; } psa_global_data_t; static psa_global_data_t global_data; @@ -715,31 +713,6 @@ exit: } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ -/* Access a key slot at the given handle. The handle of a key slot is - * the index of the slot in the global slot array, plus one so that handles - * start at 1 and not 0. */ -static psa_status_t psa_get_key_slot( psa_key_handle_t handle, - psa_key_slot_t **p_slot ) -{ - psa_key_slot_t *slot = NULL; - - GUARD_MODULE_INITIALIZED; - - /* 0 is not a valid handle under any circumstance. This - * implementation provides slots number 1 to N where N is the - * number of available slots. */ - if( handle == 0 || handle > ARRAY_LENGTH( global_data.key_slots ) ) - return( PSA_ERROR_INVALID_HANDLE ); - slot = &global_data.key_slots[handle - 1]; - - /* If the slot hasn't been allocated, the handle is invalid. */ - if( ! slot->allocated ) - return( PSA_ERROR_INVALID_HANDLE ); - - *p_slot = slot; - return( PSA_SUCCESS ); -} - /* Retrieve an empty key slot (slot with no key data, but possibly * with some metadata such as a policy). */ static psa_status_t psa_get_empty_key_slot( psa_key_handle_t handle, @@ -834,7 +807,7 @@ static psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot ) /** Completely wipe a slot in memory, including its policy. * Persistent storage is not affected. */ -static psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ) +psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ) { psa_status_t status = psa_remove_key_data_from_memory( slot ); /* At this point, key material and other type-specific content has @@ -844,20 +817,6 @@ static psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ) return( status ); } -psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle ) -{ - for( *handle = PSA_KEY_SLOT_COUNT; *handle != 0; --( *handle ) ) - { - psa_key_slot_t *slot = &global_data.key_slots[*handle - 1]; - if( ! slot->allocated ) - { - slot->allocated = 1; - return( PSA_SUCCESS ); - } - } - return( PSA_ERROR_INSUFFICIENT_MEMORY ); -} - psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle, psa_key_id_t id ) { @@ -4473,15 +4432,7 @@ psa_status_t mbedtls_psa_crypto_configure_entropy_sources( void mbedtls_psa_crypto_free( void ) { - if( global_data.key_slots_initialized ) - { - psa_key_handle_t key; - for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ ) - { - psa_key_slot_t *slot = &global_data.key_slots[key - 1]; - (void) psa_wipe_key_slot( slot ); - } - } + psa_wipe_all_key_slots( ); if( global_data.rng_state != RNG_NOT_INITIALIZED ) { mbedtls_ctr_drbg_free( &global_data.ctr_drbg ); @@ -4495,7 +4446,7 @@ void mbedtls_psa_crypto_free( void ) psa_status_t psa_crypto_init( void ) { - int ret; + psa_status_t status; const unsigned char drbg_seed[] = "PSA"; /* Double initialization is explicitly allowed. */ @@ -4513,25 +4464,26 @@ psa_status_t psa_crypto_init( void ) global_data.entropy_init( &global_data.entropy ); mbedtls_ctr_drbg_init( &global_data.ctr_drbg ); global_data.rng_state = RNG_INITIALIZED; - ret = mbedtls_ctr_drbg_seed( &global_data.ctr_drbg, - mbedtls_entropy_func, - &global_data.entropy, - drbg_seed, sizeof( drbg_seed ) - 1 ); - if( ret != 0 ) + status = mbedtls_to_psa_error( + mbedtls_ctr_drbg_seed( &global_data.ctr_drbg, + mbedtls_entropy_func, + &global_data.entropy, + drbg_seed, sizeof( drbg_seed ) - 1 ) ); + if( status != PSA_SUCCESS ) goto exit; global_data.rng_state = RNG_SEEDED; - /* Initialize the key slots. Zero-initialization has made all key - * slots empty, so there is nothing to do. */ - global_data.key_slots_initialized = 1; + status = psa_initialize_key_slots( ); + if( status != PSA_SUCCESS ) + goto exit; /* All done. */ global_data.initialized = 1; exit: - if( ret != 0 ) + if( status != PSA_SUCCESS ) mbedtls_psa_crypto_free( ); - return( mbedtls_to_psa_error( ret ) ); + return( status ); } #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index de877d344..ba6623564 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -59,4 +59,8 @@ typedef struct } data; } psa_key_slot_t; +/** Completely wipe a slot in memory, including its policy. + * Persistent storage is not affected. */ +psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ); + #endif /* PSA_CRYPTO_CORE_H */ diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index ae5e146b9..6d5c7d4fa 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -29,6 +29,7 @@ #include "psa/crypto.h" +#include "psa_crypto_core.h" #include "psa_crypto_slot_management.h" #include "psa_crypto_storage.h" @@ -43,6 +44,81 @@ #define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) ) +typedef struct +{ + psa_key_slot_t key_slots[PSA_KEY_SLOT_COUNT]; + unsigned key_slots_initialized : 1; +} psa_global_data_t; + +psa_global_data_t global_data; + +/* Access a key slot at the given handle. The handle of a key slot is + * the index of the slot in the global slot array, plus one so that handles + * start at 1 and not 0. */ +psa_status_t psa_get_key_slot( psa_key_handle_t handle, + psa_key_slot_t **p_slot ) +{ + psa_key_slot_t *slot = NULL; + + if( ! global_data.key_slots_initialized ) + return( PSA_ERROR_BAD_STATE ); + + /* 0 is not a valid handle under any circumstance. This + * implementation provides slots number 1 to N where N is the + * number of available slots. */ + if( handle == 0 || handle > ARRAY_LENGTH( global_data.key_slots ) ) + return( PSA_ERROR_INVALID_HANDLE ); + slot = &global_data.key_slots[handle - 1]; + + /* If the slot hasn't been allocated, the handle is invalid. */ + if( ! slot->allocated ) + return( PSA_ERROR_INVALID_HANDLE ); + + *p_slot = slot; + return( PSA_SUCCESS ); +} + +psa_status_t psa_initialize_key_slots( void ) +{ + /* Nothing to do: program startup and psa_wipe_all_key_slots() both + * guarantee that the key slots are initialized to all-zero, which + * means that all the key slots are in a valid, empty state. */ + global_data.key_slots_initialized = 1; + return( PSA_SUCCESS ); +} + +void psa_wipe_all_key_slots( void ) +{ + psa_key_handle_t key; + for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ ) + { + psa_key_slot_t *slot = &global_data.key_slots[key - 1]; + (void) psa_wipe_key_slot( slot ); + } + global_data.key_slots_initialized = 0; +} + +/** Find a free key slot and mark it as in use. + * + * \param[out] handle On success, a slot number that is not in use. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +static psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle ) +{ + for( *handle = PSA_KEY_SLOT_COUNT; *handle != 0; --( *handle ) ) + { + psa_key_slot_t *slot = &global_data.key_slots[*handle - 1]; + if( ! slot->allocated ) + { + slot->allocated = 1; + return( PSA_SUCCESS ); + } + } + return( PSA_ERROR_INSUFFICIENT_MEMORY ); +} + psa_status_t psa_allocate_key( psa_key_type_t type, size_t max_bits, psa_key_handle_t *handle ) diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h index cf244f266..ee37a2010 100644 --- a/library/psa_crypto_slot_management.h +++ b/library/psa_crypto_slot_management.h @@ -26,19 +26,21 @@ * The value is a compile-time constant for now, for simplicity. */ #define PSA_KEY_SLOT_COUNT 32 +/** Access a key slot at the given handle. */ +psa_status_t psa_get_key_slot( psa_key_handle_t handle, + psa_key_slot_t **p_slot ); + +/** Initialize the key slot structures. */ +psa_status_t psa_initialize_key_slots( void ); + +/** Delete all data from key slots in memory. This does not affect persistent + * storage. */ +void psa_wipe_all_key_slots( void ); + /** \defgroup core_slot_management Internal functions exposed by the core * @{ */ -/** Find a free key slot and mark it as in use. - * - * \param[out] handle On success, a slot number that is not in use. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - */ -psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle ); - /** Wipe an a key slot and mark it as available. * * This does not affect persistent storage. From fa4135b13537840714fda55839ebc9822f2d0f51 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 10 Dec 2018 16:48:53 +0100 Subject: [PATCH 31/35] Move more slot management functions to the proper module Move psa_load_persistent_key_into_slot, psa_internal_make_key_persistent and psa_internal_release_key_slot to the slot management module. Expose psa_import_key_into_slot from the core. After this commit, there are no longer any functions declared in psa_crypto_slot_management.h and defined in psa_crypto.c. There are still function calls in both directions between psa_crypto.c and psa_crypto_slot_management.c. --- library/psa_crypto.c | 72 +-------------------- library/psa_crypto_core.h | 7 +++ library/psa_crypto_slot_management.c | 94 ++++++++++++++++++++++++++++ library/psa_crypto_slot_management.h | 39 ------------ 4 files changed, 104 insertions(+), 108 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 0ac1c2707..2c49eadcc 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -611,9 +611,9 @@ exit: /** Import key data into a slot. `slot->type` must have been set * previously. This function assumes that the slot does not contain * any key material yet. On failure, the slot content is unchanged. */ -static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, - const uint8_t *data, - size_t data_length ) +psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, + const uint8_t *data, + size_t data_length ) { psa_status_t status = PSA_SUCCESS; @@ -692,27 +692,6 @@ static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, return( PSA_SUCCESS ); } -#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) -static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *p_slot ) -{ - psa_status_t status = PSA_SUCCESS; - uint8_t *key_data = NULL; - size_t key_data_length = 0; - - status = psa_load_persistent_key( p_slot->persistent_storage_id, - &( p_slot )->type, - &( p_slot )->policy, &key_data, - &key_data_length ); - if( status != PSA_SUCCESS ) - goto exit; - status = psa_import_key_into_slot( p_slot, - key_data, key_data_length ); -exit: - psa_free_persistent_key_data( key_data, key_data_length ); - return( status ); -} -#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ - /* Retrieve an empty key slot (slot with no key data, but possibly * with some metadata such as a policy). */ static psa_status_t psa_get_empty_key_slot( psa_key_handle_t handle, @@ -817,51 +796,6 @@ psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ) return( status ); } -psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle, - psa_key_id_t id ) -{ -#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) - psa_key_slot_t *slot; - psa_status_t status; - - /* Reject id=0 because by general library conventions, 0 is an invalid - * value wherever possible. */ - if( id == 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - /* Reject high values because the file names are reserved for the - * library's internal use. */ - if( id >= PSA_MAX_PERSISTENT_KEY_IDENTIFIER ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - status = psa_get_key_slot( handle, &slot ); - if( status != PSA_SUCCESS ) - return( status ); - - slot->lifetime = PSA_KEY_LIFETIME_PERSISTENT; - slot->persistent_storage_id = id; - status = psa_load_persistent_key_into_slot( slot ); - - return( status ); - -#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ - (void) handle; - (void) id; - return( PSA_ERROR_NOT_SUPPORTED ); -#endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */ -} - -psa_status_t psa_internal_release_key_slot( psa_key_handle_t handle ) -{ - psa_key_slot_t *slot; - psa_status_t status; - - status = psa_get_key_slot( handle, &slot ); - if( status != PSA_SUCCESS ) - return( status ); - - return( psa_wipe_key_slot( slot ) ); -} - psa_status_t psa_import_key( psa_key_handle_t handle, psa_key_type_t type, const uint8_t *data, diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index ba6623564..24140b517 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -63,4 +63,11 @@ typedef struct * Persistent storage is not affected. */ psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ); +/** Import key data into a slot. `slot->type` must have been set + * previously. This function assumes that the slot does not contain + * any key material yet. On failure, the slot content is unchanged. */ +psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, + const uint8_t *data, + size_t data_length ); + #endif /* PSA_CRYPTO_CORE_H */ diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index 6d5c7d4fa..f623cc988 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -119,6 +119,28 @@ static psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle ) return( PSA_ERROR_INSUFFICIENT_MEMORY ); } +/** Wipe a key slot and mark it as available. + * + * This does not affect persistent storage. + * + * \param handle The key slot number to release. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_TAMPERING_DETECTED + */ +static psa_status_t psa_internal_release_key_slot( psa_key_handle_t handle ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + status = psa_get_key_slot( handle, &slot ); + if( status != PSA_SUCCESS ) + return( status ); + + return( psa_wipe_key_slot( slot ) ); +} + psa_status_t psa_allocate_key( psa_key_type_t type, size_t max_bits, psa_key_handle_t *handle ) @@ -130,6 +152,78 @@ psa_status_t psa_allocate_key( psa_key_type_t type, return( psa_internal_allocate_key_slot( handle ) ); } +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) +static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *p_slot ) +{ + psa_status_t status = PSA_SUCCESS; + uint8_t *key_data = NULL; + size_t key_data_length = 0; + + status = psa_load_persistent_key( p_slot->persistent_storage_id, + &( p_slot )->type, + &( p_slot )->policy, &key_data, + &key_data_length ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_import_key_into_slot( p_slot, + key_data, key_data_length ); +exit: + psa_free_persistent_key_data( key_data, key_data_length ); + return( status ); +} +#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + +/** Declare a slot as persistent and load it from storage. + * + * This function may only be called immediately after a successful call + * to psa_internal_allocate_key_slot(). + * + * \param handle A handle to a key slot freshly allocated with + * psa_internal_allocate_key_slot(). + * + * \retval #PSA_SUCCESS + * The slot content was loaded successfully. + * \retval #PSA_ERROR_EMPTY_SLOT + * There is no content for this slot in persistent storage. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p id is not acceptable. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_STORAGE_FAILURE + */ +static psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle, + psa_key_id_t id ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + psa_key_slot_t *slot; + psa_status_t status; + + /* Reject id=0 because by general library conventions, 0 is an invalid + * value wherever possible. */ + if( id == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + /* Reject high values because the file names are reserved for the + * library's internal use. */ + if( id >= PSA_MAX_PERSISTENT_KEY_IDENTIFIER ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_get_key_slot( handle, &slot ); + if( status != PSA_SUCCESS ) + return( status ); + + slot->lifetime = PSA_KEY_LIFETIME_PERSISTENT; + slot->persistent_storage_id = id; + status = psa_load_persistent_key_into_slot( slot ); + + return( status ); + +#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ + (void) handle; + (void) id; + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */ +} + static psa_status_t persistent_key_setup( psa_key_lifetime_t lifetime, psa_key_id_t id, psa_key_handle_t *handle, diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h index ee37a2010..a2e52ba32 100644 --- a/library/psa_crypto_slot_management.h +++ b/library/psa_crypto_slot_management.h @@ -37,43 +37,4 @@ psa_status_t psa_initialize_key_slots( void ); * storage. */ void psa_wipe_all_key_slots( void ); -/** \defgroup core_slot_management Internal functions exposed by the core - * @{ - */ - -/** Wipe an a key slot and mark it as available. - * - * This does not affect persistent storage. - * - * \param handle The key slot number to release. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \retval #PSA_ERROR_TAMPERING_DETECTED - */ -psa_status_t psa_internal_release_key_slot( psa_key_handle_t handle ); - -/** Declare a slot as persistent and load it from storage. - * - * This function may only be called immediately after a successful call - * to psa_internal_allocate_key_slot(). - * - * \param handle A handle to a key slot freshly allocated with - * psa_internal_allocate_key_slot(). - * - * \retval #PSA_SUCCESS - * The slot content was loaded successfully. - * \retval #PSA_ERROR_EMPTY_SLOT - * There is no content for this slot in persistent storage. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p id is not acceptable. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_STORAGE_FAILURE - */ -psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle, - psa_key_id_t id ); - -/**@}*/ - #endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */ From 09829036ab8e2757c00848c72c724fa7bf728deb Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 10 Dec 2018 17:00:38 +0100 Subject: [PATCH 32/35] Document some functions in internal headers --- library/psa_crypto_core.h | 34 ++++++++++++++++++++++++---- library/psa_crypto_slot_management.h | 26 +++++++++++++++++---- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index 24140b517..c28968197 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -60,12 +60,38 @@ typedef struct } psa_key_slot_t; /** Completely wipe a slot in memory, including its policy. - * Persistent storage is not affected. */ + * + * Persistent storage is not affected. + * + * \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_TAMPERING_DETECTED + */ psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ); -/** Import key data into a slot. `slot->type` must have been set - * previously. This function assumes that the slot does not contain - * any key material yet. On failure, the slot content is unchanged. */ +/** Import key data into a slot. + * + * `slot->type` must have been set previously. + * This function assumes that the slot does not contain any key material yet. + * On failure, the slot content is unchanged. + * + * Persistent storage is not affected. + * + * \param[in,out] slot The key slot to import data into. + * Its `type` field must have previously been set to + * the desired key type. + * It must not contain any key material yet. + * \param[in] data Buffer containing the key material to parse and import. + * \param data_length Size of \p data in bytes. + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_INVALID_ARGUMENT + * \retval PSA_ERROR_NOT_SUPPORTED + * \retval PSA_ERROR_INSUFFICIENT_MEMORY + */ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, const uint8_t *data, size_t data_length ); diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h index a2e52ba32..6746bad91 100644 --- a/library/psa_crypto_slot_management.h +++ b/library/psa_crypto_slot_management.h @@ -26,15 +26,33 @@ * The value is a compile-time constant for now, for simplicity. */ #define PSA_KEY_SLOT_COUNT 32 -/** Access a key slot at the given handle. */ +/** Access a key slot at the given handle. + * + * \param handle Key handle to query. + * \param[out] p_slot On success, `*p_slot` contains a pointer to the + * key slot in memory designated by \p handle. + * + * \retval PSA_SUCCESS + * Success: \p handle is a handle to `*p_slot`. Note that `*p_slot` + * may be empty or occupied. + * \retval PSA_ERROR_INVALID_HANDLE + * \p handle is out of range or is not in use. + * \retval PSA_ERROR_BAD_STATE + * The library has not been initialized. + */ psa_status_t psa_get_key_slot( psa_key_handle_t handle, psa_key_slot_t **p_slot ); -/** Initialize the key slot structures. */ +/** Initialize the key slot structures. + * + * \retval PSA_SUCCESS + * Currently this function always succeeds. + */ psa_status_t psa_initialize_key_slots( void ); -/** Delete all data from key slots in memory. This does not affect persistent - * storage. */ +/** Delete all data from key slots in memory. + * + * This does not affect persistent storage. */ void psa_wipe_all_key_slots( void ); #endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */ From 79a11d6c422be6662cb17a9bdd1255807f33549f Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 11 Dec 2018 15:33:21 +0100 Subject: [PATCH 33/35] Test invalid lifetime regardless of support for persistent keys Even if persistent keys are not supported, psa_open_key and psa_create_key must fail if invoked with an invalid lifetime value. --- tests/suites/test_suite_psa_crypto_slot_management.data | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto_slot_management.data b/tests/suites/test_suite_psa_crypto_slot_management.data index 46dbea2c0..39661b9ed 100644 --- a/tests/suites/test_suite_psa_crypto_slot_management.data +++ b/tests/suites/test_suite_psa_crypto_slot_management.data @@ -50,19 +50,15 @@ depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C open_fail:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_ERROR_EMPTY_SLOT Open failure: volatile lifetime -depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C open_fail:PSA_KEY_LIFETIME_VOLATILE:1:PSA_ERROR_INVALID_ARGUMENT Open failure: invalid lifetime -depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C open_fail:0x7fffffff:0:PSA_ERROR_INVALID_ARGUMENT Create failure: volatile lifetime -depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C create_fail:PSA_KEY_LIFETIME_VOLATILE:1:PSA_KEY_TYPE_RAW_DATA:8:PSA_ERROR_INVALID_ARGUMENT Create failure: invalid lifetime -depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C create_fail:0x7fffffff:0:PSA_KEY_TYPE_RAW_DATA:8:PSA_ERROR_INVALID_ARGUMENT Create failure: invalid key id (0) From 23fd2bdb94c8f182ba14471d857d248236129bbd Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 11 Dec 2018 15:51:32 +0100 Subject: [PATCH 34/35] Update some documentation related to key slots Some of the documentation is obsolete in its reference to key slots when it should discuss key handles. This may require a further pass, possibly with some reorganization of error codes. Update the documentation of functions that modify key slots (key material creation and psa_set_key_policy()) to discuss how they affect storage. --- include/psa/crypto.h | 51 +++++++++++++++++++++------- library/psa_crypto_slot_management.c | 5 +-- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 4aea9905d..c58d22ae4 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -41,8 +41,8 @@ * This type represents open handles to keys. It must be an unsigned integral * type. The choice of type is implementation-dependent. * - * 0 is not a valid key slot number. The meaning of other values is - * implementation dependent. + * 0 is not a valid key handle. How other handle values are assigned is + * implementation-dependent. */ typedef _unsigned_integral_type_ psa_key_handle_t; @@ -129,17 +129,17 @@ typedef int32_t psa_status_t; /** A slot is occupied, but must be empty to carry out the * requested action. * - * If the slot number is invalid (i.e. the requested action could - * not be performed even after erasing the slot's content), - * implementations shall return #PSA_ERROR_INVALID_ARGUMENT instead. */ + * If a handle is invalid, it does not designate an occupied slot. + * The error for an invalid handle is #PSA_ERROR_INVALID_HANDLE. + */ #define PSA_ERROR_OCCUPIED_SLOT ((psa_status_t)5) /** A slot is empty, but must be occupied to carry out the * requested action. * - * If the slot number is invalid (i.e. the requested action could - * not be performed even after creating appropriate content in the slot), - * implementations shall return #PSA_ERROR_INVALID_ARGUMENT instead. */ + * If a handle is invalid, it does not designate an empty slot. + * The error for an invalid handle is #PSA_ERROR_INVALID_HANDLE. + */ #define PSA_ERROR_EMPTY_SLOT ((psa_status_t)6) /** The requested action cannot be performed in the current state. @@ -162,7 +162,12 @@ typedef int32_t psa_status_t; * Implementations shall not return this error code to indicate * that a key slot is occupied when it needs to be free or vice versa, * but shall return #PSA_ERROR_OCCUPIED_SLOT or #PSA_ERROR_EMPTY_SLOT - * as applicable. */ + * as applicable. + * + * Implementation shall not return this error code to indicate that a + * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE + * instead. + */ #define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)8) /** There is not enough runtime memory. @@ -1409,13 +1414,22 @@ typedef uint32_t psa_key_lifetime_t; */ typedef uint32_t psa_key_id_t; -/** A volatile key slot retains its content as long as the application is - * running. It is guaranteed to be erased on a power reset. +/** A volatile key only exists as long as the handle to it is not closed. + * The key material is guaranteed to be erased on a power reset. */ #define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t)0x00000000) -/** A persistent key slot retains its content as long as it is not explicitly - * destroyed. +/** The default storage area for persistent keys. + * + * A persistent key remains in storage until it is explicitly destroyed or + * until the corresponding storage area is wiped. This specification does + * not define any mechanism to wipe a storage area, but implementations may + * provide their own mechanism (for example to perform a factory reset, + * to prepare for device refurbishment, or to uninstall an application). + * + * This lifetime value is the default storage area for the calling + * application. Implementations may offer other storage areas designated + * by other lifetime values as implementation-specific extensions. */ #define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001) @@ -1599,6 +1613,8 @@ psa_status_t psa_close_key(psa_key_handle_t handle); * * \retval #PSA_SUCCESS * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_NOT_SUPPORTED * The key type or key size is not supported, either by the @@ -2009,6 +2025,10 @@ psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy); * \param[in] policy The policy object to query. * * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, it is implementation-defined whether + * the policy has been saved to persistent storage. Implementations + * may defer saving the policy until the key material is created. * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_OCCUPIED_SLOT * \retval #PSA_ERROR_NOT_SUPPORTED @@ -3292,6 +3312,8 @@ psa_status_t psa_generator_read(psa_crypto_generator_t *generator, * * \retval #PSA_SUCCESS * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. * \retval #PSA_ERROR_INSUFFICIENT_CAPACITY * There were fewer than \p output_length bytes * in the generator. Note that in this case, no @@ -3542,6 +3564,9 @@ typedef struct { * \c NULL then \p extra_size must be zero. * * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_OCCUPIED_SLOT * There is already a key in the specified slot. diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index f623cc988..4e193b56b 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -100,7 +100,8 @@ void psa_wipe_all_key_slots( void ) /** Find a free key slot and mark it as in use. * - * \param[out] handle On success, a slot number that is not in use. + * \param[out] handle On success, a slot number that is not in use. This + * value can be used as a handle to the slot. * * \retval #PSA_SUCCESS * \retval #PSA_ERROR_INSUFFICIENT_MEMORY @@ -123,7 +124,7 @@ static psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle ) * * This does not affect persistent storage. * - * \param handle The key slot number to release. + * \param handle The handle to the key slot to release. * * \retval #PSA_SUCCESS * \retval #PSA_ERROR_INVALID_ARGUMENT From 2e14bd3aaff4e00ba330763f89b3109783e20303 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 12 Dec 2018 14:05:08 +0100 Subject: [PATCH 35/35] Add missing static on file-scope variable --- 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 4e193b56b..0b4399f5e 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -50,7 +50,7 @@ typedef struct unsigned key_slots_initialized : 1; } psa_global_data_t; -psa_global_data_t global_data; +static psa_global_data_t global_data; /* Access a key slot at the given handle. The handle of a key slot is * the index of the slot in the global slot array, plus one so that handles