Merge remote-tracking branch 'psa/pr/230' into feature-psa

Implement a key handle mechanism
This commit is contained in:
Gilles Peskine 2018-12-12 16:15:34 +01:00
commit 1a76f3971c
25 changed files with 2203 additions and 1189 deletions

View file

@ -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.
* 0 is not a valid key handle. How other handle values are assigned is
* implementation-dependent.
*/
typedef _unsigned_integral_type_ psa_key_slot_t;
typedef _unsigned_integral_type_ psa_key_handle_t;
/**@}*/
#endif /* __DOXYGEN_ONLY__ */
@ -133,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.
@ -166,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.
@ -314,6 +315,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.
*
@ -1401,6 +1406,181 @@ 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 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)
/** 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)
/** \brief Retrieve the lifetime of an open key.
*
* \param handle Handle to query.
* \param[out] lifetime On success, the lifetime value.
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_INVALID_HANDLE
* \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_handle_t handle,
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
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
*/
psa_status_t psa_close_key(psa_key_handle_t handle);
/**@}*/
/** \defgroup import_export Key import and export
* @{
*/
/**
* \brief Import a key in binary format.
*
@ -1416,9 +1596,12 @@ typedef uint32_t psa_algorithm_t;
* 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
@ -1430,6 +1613,9 @@ typedef uint32_t psa_algorithm_t;
*
* \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
* implementation in general or in this particular slot.
@ -1449,31 +1635,30 @@ typedef uint32_t psa_algorithm_t;
* 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.
@ -1491,13 +1676,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.
@ -1506,7 +1690,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
@ -1515,7 +1701,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);
@ -1581,14 +1767,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
@ -1606,7 +1792,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);
@ -1683,14 +1869,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.
@ -1709,7 +1895,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);
@ -1835,10 +2021,15 @@ 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
* 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
* \retval #PSA_ERROR_INVALID_ARGUMENT
@ -1850,15 +2041,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
@ -1867,99 +2059,11 @@ 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);
/**@}*/
/** \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
* @{
*/
@ -2212,12 +2316,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
@ -2234,7 +2339,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.
@ -2264,12 +2369,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
@ -2286,7 +2392,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.
@ -2463,13 +2569,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
@ -2486,7 +2593,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.
@ -2516,13 +2623,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
@ -2539,7 +2647,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.
@ -2742,7 +2850,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).
@ -2770,6 +2878,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
@ -2785,7 +2894,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,
@ -2799,7 +2908,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).
@ -2825,6 +2934,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.
@ -2842,7 +2952,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,
@ -2880,7 +2990,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.
@ -2909,7 +3020,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,
@ -2926,8 +3037,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
@ -2952,7 +3063,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,
@ -2967,8 +3078,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.
@ -3010,7 +3122,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,
@ -3023,7 +3135,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.
@ -3066,7 +3179,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,
@ -3137,9 +3250,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);
@ -3155,19 +3268,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,
@ -3185,42 +3298,47 @@ 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.
* \param[in,out] generator The generator object to read from.
*
* \retval PSA_SUCCESS
* \retval #PSA_SUCCESS
* Success.
* \retval PSA_ERROR_INSUFFICIENT_CAPACITY
* 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
* 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
* The key slot is invalid.
* \retval PSA_ERROR_OCCUPIED_SLOT
* \retval #PSA_ERROR_BAD_STATE
* \retval #PSA_ERROR_INVALID_HANDLE
* \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
* 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);
@ -3241,11 +3359,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);
@ -3280,7 +3398,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).
@ -3293,6 +3411,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
@ -3310,7 +3429,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,
@ -3333,7 +3452,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
@ -3346,6 +3465,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
@ -3360,7 +3480,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);
@ -3409,9 +3529,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
@ -3440,6 +3564,12 @@ 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.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
@ -3452,7 +3582,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,

View file

@ -46,7 +46,7 @@
/* PSA requires several types which C99 provides in stdint.h. */
#include <stdint.h>
/* 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 */

View file

@ -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

View file

@ -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 \

View file

@ -43,7 +43,9 @@
#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
* stored keys. */
#include "psa_crypto_storage.h"
@ -80,6 +82,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"
@ -93,12 +96,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 )
{
@ -117,31 +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 */
/****************************************************************/
/* 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;
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;
} key_slot_t;
static int key_type_is_raw_bytes( psa_key_type_t type )
{
return( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) );
@ -158,10 +130,8 @@ 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];
unsigned initialized : 1;
unsigned rng_state : 2;
unsigned key_slots_initialized : 1;
} psa_global_data_t;
static psa_global_data_t global_data;
@ -638,9 +608,12 @@ exit:
}
#endif /* defined(MBEDTLS_ECP_C) */
static psa_status_t psa_import_key_into_slot( key_slot_t *slot,
const uint8_t *data,
size_t data_length )
/** 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 )
{
psa_status_t status = PSA_SUCCESS;
@ -719,71 +692,17 @@ static psa_status_t psa_import_key_into_slot( 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 key,
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,
&( 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 a key slot, occupied or not. */
static psa_status_t psa_get_key_slot( psa_key_slot_t key,
key_slot_t **p_slot )
{
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 );
*p_slot = &global_data.key_slots[key - 1];
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
if( ( *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( key, *p_slot );
if( status != PSA_ERROR_EMPTY_SLOT )
return( status );
}
}
#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
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,
key_slot_t **p_slot )
static psa_status_t psa_get_empty_key_slot( psa_key_handle_t handle,
psa_key_slot_t **p_slot )
{
psa_status_t status;
key_slot_t *slot = NULL;
psa_key_slot_t *slot = NULL;
*p_slot = NULL;
status = psa_get_key_slot( key, &slot );
status = psa_get_key_slot( handle, &slot );
if( status != PSA_SUCCESS )
return( status );
@ -797,17 +716,17 @@ 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,
key_slot_t **p_slot,
static psa_status_t psa_get_key_from_slot( psa_key_handle_t handle,
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;
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 )
@ -828,7 +747,8 @@ static psa_status_t psa_get_key_from_slot( psa_key_slot_t key,
return( PSA_SUCCESS );
}
static psa_status_t psa_remove_key_data_from_memory( key_slot_t *slot )
/** Wipe key data from a slot. Preserve metadata such as the policy. */
static psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot )
{
if( slot->type == PSA_KEY_TYPE_NONE )
{
@ -864,15 +784,27 @@ static psa_status_t psa_remove_key_data_from_memory( key_slot_t *slot )
return( PSA_SUCCESS );
}
psa_status_t psa_import_key( psa_key_slot_t key,
/** 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 )
{
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 );
}
psa_status_t psa_import_key( psa_key_handle_t handle,
psa_key_type_t type,
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( key, &slot );
status = psa_get_empty_key_slot( handle, &slot );
if( status != PSA_SUCCESS )
return( status );
@ -889,7 +821,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 )
{
@ -902,31 +835,30 @@ 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_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)
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 );
/* 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 );
}
/* 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 );
@ -942,18 +874,18 @@ 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 )
{
key_slot_t *slot;
psa_key_slot_t *slot;
psa_status_t status;
if( type != NULL )
*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 );
@ -966,7 +898,7 @@ psa_status_t psa_get_key_information( psa_key_slot_t key,
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,
@ -1074,12 +1006,12 @@ 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 )
{
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
@ -1091,19 +1023,19 @@ 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 )
{
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
@ -1113,7 +1045,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,
@ -1121,8 +1053,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( psa_key_slot_t *slot,
size_t bits )
{
psa_status_t status;
@ -1140,14 +1071,15 @@ 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 )
{
slot->type = PSA_KEY_TYPE_NONE;
}
exit:
mbedtls_zeroize( data, key_length );
mbedtls_platform_zeroize( data, key_length );
mbedtls_free( data );
return( status );
}
@ -1654,7 +1586,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 ) );
}
@ -1716,7 +1648,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;
@ -1798,19 +1730,19 @@ 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 );
}
#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 )
{
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;
@ -1823,7 +1755,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 );
@ -1916,17 +1848,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,
@ -2004,7 +1936,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 */
@ -2028,7 +1960,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
@ -2116,7 +2048,7 @@ cleanup:
else
psa_mac_abort( operation );
mbedtls_zeroize( actual_mac, sizeof( actual_mac ) );
mbedtls_platform_zeroize( actual_mac, sizeof( actual_mac ) );
return( status );
}
@ -2383,7 +2315,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,
@ -2391,12 +2323,12 @@ psa_status_t psa_asymmetric_sign( psa_key_slot_t key,
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;
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 ) )
@ -2459,17 +2391,17 @@ 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,
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( 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 );
@ -2515,7 +2447,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,
@ -2525,7 +2457,7 @@ psa_status_t psa_asymmetric_encrypt( psa_key_slot_t key,
size_t output_size,
size_t *output_length )
{
key_slot_t *slot;
psa_key_slot_t *slot;
psa_status_t status;
(void) input;
@ -2539,7 +2471,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 ) ||
@ -2595,7 +2527,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,
@ -2605,7 +2537,7 @@ psa_status_t psa_asymmetric_decrypt( psa_key_slot_t key,
size_t output_size,
size_t *output_length )
{
key_slot_t *slot;
psa_key_slot_t *slot;
psa_status_t status;
(void) input;
@ -2619,7 +2551,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 ) )
@ -2705,13 +2637,13 @@ 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 )
{
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 ?
@ -2722,7 +2654,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 );
@ -2797,17 +2729,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,
@ -2957,7 +2889,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 );
@ -2966,7 +2898,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 );
@ -3030,16 +2962,16 @@ 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;
psa_key_slot_t *slot;
psa_status_t status;
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 );
@ -3056,16 +2988,16 @@ 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;
psa_key_slot_t *slot;
psa_status_t status;
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 );
@ -3080,13 +3012,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_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 );
@ -3095,34 +3027,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;
return( PSA_SUCCESS );
}
/****************************************************************/
@ -3131,7 +3035,7 @@ psa_status_t psa_set_key_lifetime( psa_key_slot_t key,
typedef struct
{
key_slot_t *slot;
psa_key_slot_t *slot;
const mbedtls_cipher_info_t *cipher_info;
union
{
@ -3165,7 +3069,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 )
{
@ -3173,7 +3077,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 );
@ -3238,7 +3142,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,
@ -3256,7 +3160,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 );
@ -3332,7 +3236,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,
@ -3350,7 +3254,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 );
@ -3428,7 +3332,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 );
}
@ -3446,14 +3350,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 );
}
@ -3779,7 +3683,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 )
@ -3803,7 +3707,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 );
@ -3955,7 +3859,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 */
@ -4060,7 +3964,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,
@ -4068,7 +3972,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 )
@ -4080,7 +3984,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 );
@ -4165,7 +4069,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 )
@ -4206,17 +4110,17 @@ 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 );
}
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 )
{
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 );
@ -4316,19 +4220,19 @@ 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,
size_t extra_size )
{
key_slot_t *slot;
psa_key_slot_t *slot;
psa_status_t status;
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 );
@ -4437,7 +4341,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) */
@ -4462,21 +4366,7 @@ 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 )
{
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 );
/* Zeroize the slot to wipe metadata such as policies. */
mbedtls_zeroize( slot, sizeof( *slot ) );
}
}
psa_wipe_all_key_slots( );
if( global_data.rng_state != RNG_NOT_INITIALIZED )
{
mbedtls_ctr_drbg_free( &global_data.ctr_drbg );
@ -4485,12 +4375,12 @@ 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 )
{
int ret;
psa_status_t status;
const unsigned char drbg_seed[] = "PSA";
/* Double initialization is explicitly allowed. */
@ -4508,26 +4398,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. In a future version we will
* load data from storage. */
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 */

99
library/psa_crypto_core.h Normal file
View file

@ -0,0 +1,99 @@
/*
* 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;
/** Completely wipe a slot in memory, including its policy.
*
* 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.
*
* 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 );
#endif /* PSA_CRYPTO_CORE_H */

View file

@ -0,0 +1,287 @@
/*
* 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_core.h"
#include "psa_crypto_slot_management.h"
#include "psa_crypto_storage.h"
#include <stdlib.h>
#include <string.h>
#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 ) ) )
typedef struct
{
psa_key_slot_t key_slots[PSA_KEY_SLOT_COUNT];
unsigned key_slots_initialized : 1;
} psa_global_data_t;
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
* 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. This
* value can be used as a handle to the slot.
*
* \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 );
}
/** Wipe a key slot and mark it as available.
*
* This does not affect persistent storage.
*
* \param handle The handle to the key slot 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 )
{
/* This implementation doesn't reserve memory for the keys. */
(void) type;
(void) max_bits;
*handle = 0;
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,
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 */

View file

@ -0,0 +1,58 @@
/*
* 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
/** 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.
*
* \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. */
void psa_wipe_all_key_slots( void );
#endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */

View file

@ -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,

View file

@ -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.
@ -56,20 +73,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 +104,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 +115,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 +126,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.

View file

@ -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 );

View file

@ -48,15 +48,16 @@
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 );
CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_%lu",
(unsigned long) 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 +65,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 +82,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 +100,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 +115,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 +155,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 +174,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 +182,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 )

View file

@ -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;

View file

@ -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 );
}

View file

@ -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 );

View file

@ -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)

View file

@ -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.

View file

@ -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
@ -32,14 +29,14 @@ 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_HANDLE
PSA export out of range key slot - lower bound
export_invalid_slot:0:PSA_ERROR_INVALID_ARGUMENT
PSA export invalid handle (smallest plausible handle)
export_invalid_handle:1:PSA_ERROR_INVALID_HANDLE
PSA export out of range key slot - upper bound
export_invalid_slot:(psa_key_slot_t)(-1):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
@ -320,6 +317,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
@ -467,18 +468,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

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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 */

View file

@ -0,0 +1,84 @@
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: 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
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
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
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:
Open many transient handles
many_transient_handles:42

View file

@ -0,0 +1,398 @@
/* BEGIN_HEADER */
#include <stdint.h>
#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. */
#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, 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 || \
KEY_ID_IS_WELL_KNOWN( key_id ) )
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 );
}
#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 )
{
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 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,
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 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */
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( );
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
psa_purge_key_storage( );
#endif
}
/* 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 );
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 );
/* 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 */

View file

@ -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 );

View file

@ -231,7 +231,9 @@
<ClInclude Include="..\..\include\psa\crypto_platform.h" />
<ClInclude Include="..\..\include\psa\crypto_sizes.h" />
<ClInclude Include="..\..\include\psa\crypto_struct.h" />
<ClInclude Include="..\..\library/psa_crypto_core.h" />
<ClInclude Include="..\..\library/psa_crypto_invasive.h" />
<ClInclude Include="..\..\library/psa_crypto_slot_management.h" />
<ClInclude Include="..\..\library/psa_crypto_storage.h" />
<ClInclude Include="..\..\library/psa_crypto_storage_backend.h" />
</ItemGroup>
@ -291,6 +293,7 @@
<ClCompile Include="..\..\library\platform_util.c" />
<ClCompile Include="..\..\library\poly1305.c" />
<ClCompile Include="..\..\library\psa_crypto.c" />
<ClCompile Include="..\..\library\psa_crypto_slot_management.c" />
<ClCompile Include="..\..\library\psa_crypto_storage.c" />
<ClCompile Include="..\..\library\psa_crypto_storage_file.c" />
<ClCompile Include="..\..\library\psa_crypto_storage_its.c" />