diff options
author | Antonio de Angelis <antonio.deangelis@arm.com> | 2019-10-14 12:12:52 +0100 |
---|---|---|
committer | Soby Mathew <soby.mathew@arm.com> | 2020-02-24 11:53:56 +0000 |
commit | 04debbd6e157d8ab9f80525e296303e830838c50 (patch) | |
tree | f9f6f70898661ee377943ea65c23d8560bca7e00 /interface | |
parent | dad6ca656729478d199434a090b55bb3d36d4e86 (diff) | |
download | trusted-firmware-m-04debbd6e157d8ab9f80525e296303e830838c50.tar.gz |
Crypto: Align to Mbed Crypto 3.0.1
This patch upgrades the Crypto service to be able
to use Mbed Crypto 3.0.1:
- Updates the PSA crypto headers to latest available in mbed-crypto
- Updates the service implementation
- Updates the test suites where needed
- Updates the SST and Attestation interfaces
towards cryptographic functionalities
- Updates documentation to reflect updated
requirements, and changes in the integration guide
This patch migrates the use of psa_asymmetric_sign() and
psa_asymmetric_verify() to the non-deprecated versions of
the API psa_sign_hash() and psa_verify_hash().
Signed-off-by: Antonio de Angelis <antonio.deangelis@arm.com>
Change-Id: I7d8275def2336c1b5cfb8847b2842c305cfab116
Diffstat (limited to 'interface')
-rw-r--r-- | interface/include/psa/crypto.h | 2886 | ||||
-rw-r--r-- | interface/include/psa/crypto_compat.h | 93 | ||||
-rw-r--r-- | interface/include/psa/crypto_extra.h | 10 | ||||
-rw-r--r-- | interface/include/psa/crypto_platform.h | 23 | ||||
-rw-r--r-- | interface/include/psa/crypto_sizes.h | 229 | ||||
-rw-r--r-- | interface/include/psa/crypto_struct.h | 223 | ||||
-rw-r--r-- | interface/include/psa/crypto_types.h | 229 | ||||
-rw-r--r-- | interface/include/psa/crypto_values.h | 598 | ||||
-rw-r--r-- | interface/include/tfm_crypto_defs.h | 67 | ||||
-rw-r--r-- | interface/include/tfm_veneers.h | 59 | ||||
-rw-r--r-- | interface/include/tfm_veneers.h.template | 2 | ||||
-rw-r--r-- | interface/src/tfm_crypto_func_api.c | 696 | ||||
-rw-r--r-- | interface/src/tfm_crypto_ipc_api.c | 789 |
13 files changed, 4335 insertions, 1569 deletions
diff --git a/interface/include/psa/crypto.h b/interface/include/psa/crypto.h index 1e0c9d09f0..91581172c2 100644 --- a/interface/include/psa/crypto.h +++ b/interface/include/psa/crypto.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -47,6 +47,22 @@ extern "C" { * algorithms, key types, policies, etc. */ #include "psa/crypto_types.h" +/** \defgroup version API version + * @{ + */ + +/** + * The major version of this implementation of the PSA Crypto API + */ +#define PSA_CRYPTO_API_VERSION_MAJOR 1 + +/** + * The minor version of this implementation of the PSA Crypto API + */ +#define PSA_CRYPTO_API_VERSION_MINOR 0 + +/**@}*/ + /* The file "crypto_values.h" declares macros to build and analyze values * of integral types defined in "crypto_types.h". */ #include "psa/crypto_values.h" @@ -76,358 +92,497 @@ extern "C" { * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY */ psa_status_t psa_crypto_init(void); /**@}*/ -/** \defgroup policy Key policies +/** \addtogroup attributes * @{ */ -/** The type of the key policy data structure. - * - * Before calling any function on a key policy, the application must initialize - * it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_key_policy_t policy; - * memset(&policy, 0, sizeof(policy)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_key_policy_t policy = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_KEY_POLICY_INIT, - * for example: - * \code - * psa_key_policy_t policy = PSA_KEY_POLICY_INIT; - * \endcode - * - Assign the result of the function psa_key_policy_init() - * to the structure, for example: - * \code - * psa_key_policy_t policy; - * policy = psa_key_policy_init(); - * \endcode - * - * This is an implementation-defined \c struct. Applications should not - * make any assumptions about the content of this structure except - * as directed by the documentation of a specific implementation. */ -typedef struct psa_key_policy_s psa_key_policy_t; - -/** \def PSA_KEY_POLICY_INIT +/** \def PSA_KEY_ATTRIBUTES_INIT * - * This macro returns a suitable initializer for a key policy object of type - * #psa_key_policy_t. + * This macro returns a suitable initializer for a key attribute structure + * of type #psa_key_attributes_t. */ #ifdef __DOXYGEN_ONLY__ /* This is an example definition for documentation purposes. * Implementations should define a suitable value in `crypto_struct.h`. */ -#define PSA_KEY_POLICY_INIT {0} +#define PSA_KEY_ATTRIBUTES_INIT {0} #endif -/** Return an initial value for a key policy that forbids all usage of the key. +/** Return an initial value for a key attributes structure. */ -static psa_key_policy_t psa_key_policy_init(void); +static psa_key_attributes_t psa_key_attributes_init(void); -/** \brief Set the standard fields of a policy structure. +/** Declare a key as persistent and set its key identifier. + * + * If the attribute structure currently declares the key as volatile (which + * is the default content of an attribute structure), this function sets + * the lifetime attribute to #PSA_KEY_LIFETIME_PERSISTENT. * - * Note that this function does not make any consistency check of the - * parameters. The values are only checked when applying the policy to - * a key slot with psa_set_key_policy(). + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). * - * \param[in,out] policy The key policy to modify. It must have been - * initialized as per the documentation for - * #psa_key_policy_t. - * \param usage The permitted uses for the key. - * \param alg The algorithm that the key may be used for. + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param id The persistent identifier for the key. */ -void psa_key_policy_set_usage(psa_key_policy_t *policy, - psa_key_usage_t usage, - psa_algorithm_t alg); +static void psa_set_key_id(psa_key_attributes_t *attributes, + psa_key_id_t id); -/** \brief Retrieve the usage field of a policy structure. +/** Set the location of a persistent key. + * + * To make a key persistent, you must give it a persistent key identifier + * with psa_set_key_id(). By default, a key that has a persistent identifier + * is stored in the default storage area identifier by + * #PSA_KEY_LIFETIME_PERSISTENT. Call this function to choose a storage + * area, or to explicitly declare the key as volatile. * - * \param[in] policy The policy object to query. + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). * - * \return The permitted uses for a key with this policy. + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param lifetime The lifetime for the key. + * If this is #PSA_KEY_LIFETIME_VOLATILE, the + * key will be volatile, and the key identifier + * attribute is reset to 0. */ -psa_key_usage_t psa_key_policy_get_usage(const psa_key_policy_t *policy); +static void psa_set_key_lifetime(psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime); -/** \brief Retrieve the algorithm field of a policy structure. +/** Retrieve the key identifier from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. * - * \param[in] policy The policy object to query. + * \param[in] attributes The key attribute structure to query. * - * \return The permitted algorithm for a key with this policy. + * \return The persistent identifier stored in the attribute structure. + * This value is unspecified if the attribute structure declares + * the key as volatile. */ -psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy); +static psa_key_id_t psa_get_key_id(const psa_key_attributes_t *attributes); -/** \brief Set the usage policy on a key slot. +/** Retrieve the lifetime from key attributes. * - * This function must be called on an empty key slot, before importing, - * generating or creating a key in the slot. Changing the policy of an - * existing key is not permitted. + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. * - * Implementations may set restrictions on supported key policies - * depending on the key type and the key slot. + * \param[in] attributes The key attribute structure to query. * - * \param handle Handle to the key whose policy is to be changed. - * \param[in] policy The policy object to query. + * \return The lifetime value stored in the attribute structure. + */ +static psa_key_lifetime_t psa_get_key_lifetime( + const psa_key_attributes_t *attributes); + +/** Declare usage flags for a key. * - * \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_ALREADY_EXISTS - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \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. + * Usage flags are part of a key's usage policy. They encode what + * kind of operations are permitted on the key. For more details, + * refer to the documentation of the type #psa_key_usage_t. + * + * This function overwrites any usage flags + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param usage_flags The usage flags to write. */ -psa_status_t psa_set_key_policy(psa_key_handle_t handle, - const psa_key_policy_t *policy); +static void psa_set_key_usage_flags(psa_key_attributes_t *attributes, + psa_key_usage_t usage_flags); -/** \brief Get the usage policy for a key slot. +/** Retrieve the usage flags from key attributes. * - * \param handle Handle to the key slot whose policy is being queried. - * \param[out] policy On success, the key's policy. + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. * - * \retval #PSA_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. + * \param[in] attributes The key attribute structure to query. + * + * \return The usage flags stored in the attribute structure. */ -psa_status_t psa_get_key_policy(psa_key_handle_t handle, - psa_key_policy_t *policy); +static psa_key_usage_t psa_get_key_usage_flags( + const psa_key_attributes_t *attributes); -/**@}*/ +/** Declare the permitted algorithm policy for a key. + * + * The permitted algorithm policy of a key encodes which algorithm or + * algorithms are permitted to be used with this key. The following + * algorithm policies are supported: + * - 0 does not allow any cryptographic operation with the key. The key + * may be used for non-cryptographic actions such as exporting (if + * permitted by the usage flags). + * - An algorithm value permits this particular algorithm. + * - An algorithm wildcard built from #PSA_ALG_ANY_HASH allows the specified + * signature scheme with any hash algorithm. + * + * This function overwrites any algorithm policy + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param alg The permitted algorithm policy to write. + */ +static void psa_set_key_algorithm(psa_key_attributes_t *attributes, + psa_algorithm_t alg); -/** \defgroup key_management Key management - * @{ + +/** Retrieve the algorithm policy from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The algorithm stored in the attribute structure. + */ +static psa_algorithm_t psa_get_key_algorithm( + const psa_key_attributes_t *attributes); + +/** Declare the type of a key. + * + * This function overwrites any key type + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param type The key type to write. + * If this is 0, the key type in \p attributes + * becomes unspecified. + */ +static void psa_set_key_type(psa_key_attributes_t *attributes, + psa_key_type_t type); + + +/** Declare the size of a key. + * + * This function overwrites any key size previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param bits The key size in bits. + * If this is 0, the key size in \p attributes + * becomes unspecified. Keys of size 0 are + * not supported. + */ +static void psa_set_key_bits(psa_key_attributes_t *attributes, + size_t bits); + +/** Retrieve the key type from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The key type stored in the attribute structure. + */ +static psa_key_type_t psa_get_key_type(const psa_key_attributes_t *attributes); + +/** Retrieve the key size from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The key size stored in the attribute structure, in bits. */ +static size_t psa_get_key_bits(const psa_key_attributes_t *attributes); -/** \brief Retrieve the lifetime of an open key. +/** Retrieve the attributes of a key. * - * \param handle Handle to query. - * \param[out] lifetime On success, the lifetime value. + * This function first resets the attribute structure as with + * psa_reset_key_attributes(). It then copies the attributes of + * the given key into the given attribute structure. + * + * \note This function may allocate memory or other resources. + * Once you have called this function on an attribute structure, + * you must call psa_reset_key_attributes() to free these resources. + * + * \param[in] handle Handle to the key to query. + * \param[in,out] attributes On success, the attributes of the key. + * On failure, equivalent to a + * freshly-initialized structure. * * \retval #PSA_SUCCESS - * Success. * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE * \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); +psa_status_t psa_get_key_attributes(psa_key_handle_t handle, + psa_key_attributes_t *attributes); - -/** Allocate a key slot for a transient key, i.e. a key which is only stored - * in volatile memory. +/** Reset a key attribute structure to a freshly initialized state. * - * 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. + * You must initialize the attribute structure as described in the + * documentation of the type #psa_key_attributes_t before calling this + * function. Once the structure has been initialized, you may call this + * function at any time. * - * \param[out] handle On success, a handle to a volatile key slot. + * This function frees any auxiliary resources that the structure + * may contain. * - * \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. + * \param[in,out] attributes The attribute structure to reset. + */ +void psa_reset_key_attributes(psa_key_attributes_t *attributes); + +/**@}*/ + +/** \defgroup key_management Key management + * @{ */ -psa_status_t psa_allocate_key(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(). + * Open a handle to a persistent key. A key is persistent if it was created + * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key + * always has a nonzero key identifier, set with psa_set_key_id() when + * creating the key. Implementations may provide additional pre-provisioned + * keys that can be opened with psa_open_key(). Such keys have a key identifier + * in the vendor range, as documented in the description of #psa_key_id_t. + * + * The application must eventually close the handle with psa_close_key() or + * psa_destroy_key() to release associated resources. If the application dies + * without calling one of these functions, the implementation should perform + * the equivalent of a call to psa_close_key(). + * + * Some implementations permit an application to open the same key multiple + * times. If this is successful, each call to psa_open_key() will return a + * different key handle. + * + * \note Applications that rely on opening a key multiple times will not be + * portable to implementations that only permit a single key handle to be + * opened. See also :ref:\`key-handles\`. * - * \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. + * \param[out] handle On success, a handle to the key. * * \retval #PSA_SUCCESS * Success. The application can now use the value of `*handle` - * to access the newly allocated key slot. + * to access the key. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * The implementation does not have sufficient resources to open the + * key. This can be due to reaching an implementation limit on the + * number of open keys, the number of open key handles, or available + * memory. * \retval #PSA_ERROR_DOES_NOT_EXIST + * There is no persistent key with key identifier \p id. * \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. + * \p id is not a valid persistent key identifier. * \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. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_open_key(psa_key_lifetime_t lifetime, - psa_key_id_t id, +psa_status_t psa_open_key(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[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_ALREADY_EXISTS - * 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_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 volatile key, this will destroy the key material + * and free all associated resources, just like psa_destroy_key(). + * + * If this is the last open handle to a persistent key, then closing the handle + * will free all resources associated with the key in volatile memory. The key + * data in persistent storage is not affected and can be opened again later + * with a call to psa_open_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(). + * Closing the key handle makes the handle invalid, and the key handle + * must not be used again by the application. + * + * \note If the key handle was used to set up an active + * :ref:\`multipart operation <multipart-operations>\`, then closing the + * key handle can cause the multipart operation to fail. Applications should + * maintain the key handle until after the multipart operation has finished. * * \param handle The key handle to close. + * If this is \c 0, do nothing and return \c PSA_SUCCESS. * * \retval #PSA_SUCCESS + * \p handle was a valid handle or \c 0. It is now closed. * \retval #PSA_ERROR_INVALID_HANDLE + * \p handle is not a valid handle nor \c 0. * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_close_key(psa_key_handle_t handle); -/**@}*/ - -/** \defgroup import_export Key import and export - * @{ - */ - -/** - * \brief Import a key in binary format. +/** Make a copy of a key. * - * This function supports any output from psa_export_key(). Refer to the - * documentation of psa_export_public_key() for the format of public keys - * and to the documentation of psa_export_key() for the format for - * other key types. + * Copy key material from one location to another. * - * This specification supports a single format for each key type. - * Implementations may support other formats as long as the standard - * format is supported. Implementations that support other formats - * should ensure that the formats are clearly unambiguous so as to - * minimize the risk that an invalid input is accidentally interpreted - * according to a different format. + * This function is primarily useful to copy a key from one location + * to another, since it populates a key using the material from + * another key which may have a different lifetime. * - * \param handle Handle to the slot where the key will be stored. - * It must have been obtained by calling - * psa_allocate_key() or psa_create_key() and must - * not contain key material yet. - * \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 - * buffer is interpreted according to \p type. It must - * contain the format described in the documentation - * of psa_export_key() or psa_export_public_key() for - * the chosen type. - * \param data_length Size of the \p data buffer in bytes. + * This function may be used to share a key with a different party, + * subject to implementation-defined restrictions on key sharing. + * + * The policy on the source key must have the usage flag + * #PSA_KEY_USAGE_COPY set. + * This flag is sufficient to permit the copy if the key has the lifetime + * #PSA_KEY_LIFETIME_VOLATILE or #PSA_KEY_LIFETIME_PERSISTENT. + * Some secure elements do not provide a way to copy a key without + * making it extractable from the secure element. If a key is located + * in such a secure element, then the key must have both usage flags + * #PSA_KEY_USAGE_COPY and #PSA_KEY_USAGE_EXPORT in order to make + * a copy of the key outside the secure element. + * + * The resulting key may only be used in a way that conforms to + * both the policy of the original key and the policy specified in + * the \p attributes parameter: + * - The usage flags on the resulting key are the bitwise-and of the + * usage flags on the source policy and the usage flags in \p attributes. + * - If both allow the same algorithm or wildcard-based + * algorithm policy, the resulting key has the same algorithm policy. + * - If either of the policies allows an algorithm and the other policy + * allows a wildcard-based algorithm policy that includes this algorithm, + * the resulting key allows the same algorithm. + * - If the policies do not allow any algorithm in common, this function + * fails with the status #PSA_ERROR_INVALID_ARGUMENT. + * + * The effect of this function on implementation-defined attributes is + * implementation-defined. + * + * \param source_handle The key to copy. It must be a valid key handle. + * \param[in] attributes The attributes for the new key. + * They are used as follows: + * - The key type and size may be 0. If either is + * nonzero, it must match the corresponding + * attribute of the source key. + * - The key location (the lifetime and, for + * persistent keys, the key identifier) is + * used directly. + * - The policy constraints (usage flags and + * algorithm policy) are combined from + * the source key and \p attributes so that + * both sets of restrictions apply, as + * described in the documentation of this function. + * \param[out] target_handle On success, a handle to the newly created key. + * \c 0 on failure. * * \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. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key slot is invalid, - * or the key data is not correctly formatted. + * \p source_handle is invalid. * \retval #PSA_ERROR_ALREADY_EXISTS - * There is already a key in the specified slot. + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The lifetime or identifier in \p attributes are invalid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The policy constraints on the source and specified in + * \p attributes are incompatible. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p attributes specifies a key type or key size + * which does not match the attributes of the source key. + * \retval #PSA_ERROR_NOT_PERMITTED + * The source key does not have the #PSA_KEY_USAGE_COPY usage flag. + * \retval #PSA_ERROR_NOT_PERMITTED + * The source key is not exportable and its lifetime does not + * allow copying it to the target's lifetime. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_INSUFFICIENT_STORAGE * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_STORAGE_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_import_key(psa_key_handle_t handle, - psa_key_type_t type, - const uint8_t *data, - size_t data_length); +psa_status_t psa_copy_key(psa_key_handle_t source_handle, + const psa_key_attributes_t *attributes, + psa_key_handle_t *target_handle); + /** * \brief Destroy a key. * - * This function destroys the content of the key slot from both volatile + * This function destroys a key 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. + * make a best effort to ensure that that the key material cannot be recovered. + * + * This function also erases any metadata such as policies and frees + * resources associated with the key. To free all resources associated with + * the key, all handles to the key must be closed or destroyed. + * + * Destroying the key makes the handle invalid, and the key handle + * must not be used again by the application. Using other open handles to the + * destroyed key in a cryptographic operation will result in an error. * - * This function also erases any metadata such as policies and frees all - * resources associated with the key. + * If a key is currently in use in a multipart operation, then destroying the + * key will cause the multipart operation to fail. * - * \param handle Handle to the key slot to erase. + * \param handle Handle to the key to erase. + * If this is \c 0, do nothing and return \c PSA_SUCCESS. * * \retval #PSA_SUCCESS - * The slot's content, if any, has been erased. + * \p handle was a valid handle and the key material that it + * referred to has been erased. + * Alternatively, \p handle is \c 0. * \retval #PSA_ERROR_NOT_PERMITTED - * The slot holds content and cannot be erased because it is + * The key cannot be erased because it is * read-only, either due to a policy or due to physical restrictions. * \retval #PSA_ERROR_INVALID_HANDLE + * \p handle is not a valid handle nor \c 0. * \retval #PSA_ERROR_COMMUNICATION_FAILURE * There was an failure in communication with the cryptoprocessor. * The key material may still be present in the cryptoprocessor. @@ -436,7 +591,7 @@ psa_status_t psa_import_key(psa_key_handle_t handle, * to erase key material even in this stage, however applications * should be aware that it may be impossible to guarantee that the * key material is not recoverable in such cases. - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED * An unexpected condition which is not a storage corruption or * a communication failure occurred. The cryptoprocessor may have * been compromised. @@ -447,32 +602,87 @@ psa_status_t psa_import_key(psa_key_handle_t handle, */ psa_status_t psa_destroy_key(psa_key_handle_t handle); +/**@}*/ + +/** \defgroup import_export Key import and export + * @{ + */ + /** - * \brief Get basic metadata about a key. + * \brief Import a key in binary format. * - * \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. - * \param[out] bits On success, the key size in bits. - * This may be a null pointer, in which case the key size - * is not written. + * This function supports any output from psa_export_key(). Refer to the + * documentation of psa_export_public_key() for the format of public keys + * and to the documentation of psa_export_key() for the format for + * other key types. + * + * The key data determines the key size. The attributes may optionally + * specify a key size; in this case it must match the size determined + * from the key data. A key size of 0 in \p attributes indicates that + * the key size is solely determined by the key data. + * + * Implementations must reject an attempt to import a key of size 0. + * + * This specification supports a single format for each key type. + * Implementations may support other formats as long as the standard + * format is supported. Implementations that support other formats + * should ensure that the formats are clearly unambiguous so as to + * minimize the risk that an invalid input is accidentally interpreted + * according to a different format. + * + * \param[in] attributes The attributes for the new key. + * The key size is always determined from the + * \p data buffer. + * If the key size in \p attributes is nonzero, + * it must be equal to the size from \p data. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. + * \param[in] data Buffer containing the key data. The content of this + * buffer is interpreted according to the type declared + * in \p attributes. + * All implementations must support at least the format + * described in the documentation + * of psa_export_key() or psa_export_public_key() for + * the chosen type. Implementations may allow other + * formats, but should be conservative: implementations + * should err on the side of rejecting content if it + * may be erroneous (e.g. wrong type or truncated data). + * \param data_length Size of the \p data buffer in bytes. * * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_DOES_NOT_EXIST - * The handle is to a key slot which does not contain key material yet. + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular persistent location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key attributes, as a whole, are invalid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key data is not correctly formatted. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size in \p attributes is nonzero and does not match the size + * of the key data. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_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_information(psa_key_handle_t handle, - psa_key_type_t *type, - size_t *bits); +psa_status_t psa_import_key(const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + psa_key_handle_t *handle); + + /** * \brief Export a key in binary format. @@ -493,7 +703,7 @@ psa_status_t psa_get_key_information(psa_key_handle_t handle, * correct. * - For Triple-DES, the format is the concatenation of the * two or three DES keys. - * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEYPAIR), the format + * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEY_PAIR), the format * is the non-encrypted DER encoding of the representation defined by * PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0. * ``` @@ -509,21 +719,8 @@ psa_status_t psa_get_key_information(psa_key_handle_t handle, * coefficient INTEGER, -- (inverse of q) mod p * } * ``` - * - For DSA private keys (#PSA_KEY_TYPE_DSA_KEYPAIR), the format - * is the non-encrypted DER encoding of the representation used by - * OpenSSL and OpenSSH, whose structure is described in ASN.1 as follows: - * ``` - * DSAPrivateKey ::= SEQUENCE { - * version INTEGER, -- must be 0 - * prime INTEGER, -- p - * subprime INTEGER, -- q - * generator INTEGER, -- g - * public INTEGER, -- y - * private INTEGER, -- x - * } - * ``` * - For elliptic curve key pairs (key types for which - * #PSA_KEY_TYPE_IS_ECC_KEYPAIR is true), the format is + * #PSA_KEY_TYPE_IS_ECC_KEY_PAIR is true), the format is * a representation of the private value as a `ceiling(m/8)`-byte string * where `m` is the bit size associated with the curve, i.e. the bit size * of the order of the curve's coordinate field. This byte string is @@ -533,9 +730,16 @@ psa_status_t psa_get_key_information(psa_key_handle_t handle, * and `PSA_ECC_CURVE_BRAINPOOL_PXXX`). * This is the content of the `privateKey` field of the `ECPrivateKey` * format defined by RFC 5915. + * - For Diffie-Hellman key exchange key pairs (key types for which + * #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the + * format is the representation of the private key `x` as a big-endian byte + * string. The length of the byte string is the private key size in bytes + * (leading zeroes are not stripped). * - 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(). * + * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set. + * * \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. @@ -544,8 +748,8 @@ psa_status_t psa_get_key_information(psa_key_handle_t handle, * * \retval #PSA_SUCCESS * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_EXPORT flag. * \retval #PSA_ERROR_NOT_SUPPORTED * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p data buffer is too small. You can determine a @@ -555,7 +759,9 @@ psa_status_t psa_get_key_information(psa_key_handle_t handle, * and \c bits is the key size in bits. * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \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 @@ -589,39 +795,20 @@ psa_status_t psa_export_key(psa_key_handle_t handle, * ``` * - For elliptic curve public keys (key types for which * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed - * representation defined by SEC1 §2.3.3 as the content of an ECPoint: + * representation defined by SEC1 §2.3.3 as the content of an ECPoint. * Let `m` be the bit size associated with the curve, i.e. the bit size of * `q` for a curve over `F_q`. The representation consists of: * - The byte 0x04; * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. + * - For Diffie-Hellman key exchange public keys (key types for which + * #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true), + * the format is the representation of the public key `y = g^x mod p` as a + * big-endian byte string. The length of the byte string is the length of the + * base prime `p` in bytes. * - * For other public key types, the format is the DER representation defined by - * RFC 5280 as `SubjectPublicKeyInfo`, with the `subjectPublicKey` format - * specified below. - * ``` - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL } - * ``` - * - For DSA public keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY), - * the `subjectPublicKey` format is defined by RFC 3279 §2.3.2 as - * `DSAPublicKey`, - * with the OID `id-dsa`, - * and with the parameters `DSS-Parms`. - * ``` - * id-dsa OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 1 } - * - * Dss-Parms ::= SEQUENCE { - * p INTEGER, - * q INTEGER, - * g INTEGER } - * DSAPublicKey ::= INTEGER -- public key, Y - * ``` + * Exporting a public key object or the public part of a key pair is + * always permitted, regardless of the key's usage flags. * * \param handle Handle to the key to export. * \param[out] data Buffer where the key data is to be written. @@ -631,19 +818,20 @@ psa_status_t psa_export_key(psa_key_handle_t handle, * * \retval #PSA_SUCCESS * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_INVALID_ARGUMENT * The key is neither a public key nor a key pair. * \retval #PSA_ERROR_NOT_SUPPORTED * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p data buffer is too small. You can determine a * sufficient buffer size by calling - * #PSA_KEY_EXPORT_MAX_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(\c type), \c bits) + * #PSA_KEY_EXPORT_MAX_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits) * where \c type is the key type * and \c bits is the key size in bits. * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \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 @@ -654,77 +842,87 @@ psa_status_t psa_export_public_key(psa_key_handle_t handle, size_t data_size, size_t *data_length); -/** Make a copy of a key. - * - * Copy key material from one location to another. - * - * This function is primarily useful to copy a key from one location - * to another, since it populates a key using the material from - * another key which may have a different lifetime. - * - * In an implementation where slots have different ownerships, - * this function may be used to share a key with a different party, - * subject to implementation-defined restrictions on key sharing. - * In this case \p constraint would typically prevent the recipient - * from exporting the key. - * - * The resulting key may only be used in a way that conforms to all - * three of: the policy of the source key, the policy previously set - * on the target, and the \p constraint parameter passed when calling - * this function. - * - The usage flags on the resulting key are the bitwise-and of the - * usage flags on the source policy, the previously-set target policy - * and the policy constraint. - * - If all three policies allow the same algorithm or wildcard-based - * algorithm policy, the resulting key has the same algorithm policy. - * - If one of the policies allows an algorithm and all the other policies - * either allow the same algorithm or a wildcard-based algorithm policy - * that includes this algorithm, the resulting key allows the same - * algorithm. + + +/**@}*/ + +/** \defgroup hash Message digests + * @{ + */ + +/** Calculate the hash (digest) of a message. * - * The effect of this function on implementation-defined metadata is - * implementation-defined. + * \note To verify the hash of a message against an + * expected value, use psa_hash_compare() instead. * - * \param source_handle The key to copy. It must be a handle to an - * occupied slot. - * \param target_handle A handle to the target slot. It must not contain - * key material yet. - * \param[in] constraint An optional policy constraint. If this parameter - * is non-null then the resulting key will conform - * to this policy in addition to the source policy - * and the policy already present on the target - * slot. If this parameter is null then the - * function behaves in the same way as if it was - * the target policy, i.e. only the source and - * target policies apply. + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * \param[in] input Buffer containing the message to hash. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] hash Buffer where the hash is to be written. + * \param hash_size Size of the \p hash buffer in bytes. + * \param[out] hash_length On success, the number of bytes + * that make up the hash value. This is always + * #PSA_HASH_SIZE(\p alg). * * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_ALREADY_EXISTS - * \p target already contains key material. - * \retval #PSA_ERROR_DOES_NOT_EXIST - * \p source does not contain key material. + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a hash algorithm. * \retval #PSA_ERROR_INVALID_ARGUMENT - * The policy constraints on the source, on the target and - * \p constraints are incompatible. - * \retval #PSA_ERROR_NOT_PERMITTED - * The source key is not exportable and its lifetime does not - * allow copying it to the target's lifetime. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p hash_size is too small * \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_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \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_copy_key(psa_key_handle_t source_handle, - psa_key_handle_t target_handle, - const psa_key_policy_t *constraint); - -/**@}*/ +psa_status_t psa_hash_compute(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); -/** \defgroup hash Message digests - * @{ +/** Calculate the hash (digest) of a message and compare it with a + * reference value. + * + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * \param[in] input Buffer containing the message to hash. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] hash Buffer containing the expected hash value. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected hash is identical to the actual hash of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The hash of the message was calculated successfully, but it + * differs from the expected hash. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p input_length or \p hash_length do not match the hash size for \p alg + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \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_hash_compare(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *hash, + const size_t hash_length); /** The type of the state data structure for multipart hash operations. * @@ -779,7 +977,7 @@ static psa_hash_operation_t psa_hash_operation_init(void); * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_hash_operation_t, e.g. PSA_HASH_OPERATION_INIT. + * documentation for #psa_hash_operation_t, e.g. #PSA_HASH_OPERATION_INIT. * -# Call psa_hash_setup() to specify the algorithm. * -# Call psa_hash_update() zero, one or more times, passing a fragment * of the message each time. The hash that is calculated is the hash @@ -787,14 +985,16 @@ static psa_hash_operation_t psa_hash_operation_init(void); * -# To calculate the hash, call psa_hash_finish(). * To compare the hash with an expected value, call psa_hash_verify(). * - * The application may call psa_hash_abort() at any time after the operation + * If an error occurs at any step after a call to psa_hash_setup(), the + * operation will need to be reset by a call to psa_hash_abort(). The + * application may call psa_hash_abort() at any time after the operation * has been initialized. * * After a successful call to psa_hash_setup(), the application must * eventually terminate the operation. The following events terminate an * operation: - * - A failed call to psa_hash_update(). - * - A call to psa_hash_finish(), psa_hash_verify() or psa_hash_abort(). + * - A successful call to psa_hash_finish() or psa_hash_verify(). + * - A call to psa_hash_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for @@ -805,14 +1005,19 @@ static psa_hash_operation_t psa_hash_operation_init(void); * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a hash algorithm. + * \p alg is not a supported hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a hash algorithm. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (already set up and not - * subsequently completed). + * The operation state is not valid (it must be inactive). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_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_hash_setup(psa_hash_operation_t *operation, psa_algorithm_t alg); @@ -821,7 +1026,8 @@ psa_status_t psa_hash_setup(psa_hash_operation_t *operation, * * The application must call psa_hash_setup() before calling this function. * - * If this function returns an error status, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). * * \param[in,out] operation Active hash operation. * \param[in] input Buffer containing the message fragment to hash. @@ -830,11 +1036,15 @@ psa_status_t psa_hash_setup(psa_hash_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not set up, or already completed). + * The operation state is not valid (it muct be active). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_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_hash_update(psa_hash_operation_t *operation, const uint8_t *input, @@ -846,7 +1056,9 @@ psa_status_t psa_hash_update(psa_hash_operation_t *operation, * This function calculates the hash of the message formed by concatenating * the inputs passed to preceding calls to psa_hash_update(). * - * When this function returns, the operation becomes inactive. + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). * * \warning Applications should not call this function if they expect * a specific value for the hash. Call psa_hash_verify() instead. @@ -867,7 +1079,7 @@ psa_status_t psa_hash_update(psa_hash_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not set up, or already completed). + * The operation state is not valid (it must be active). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p hash buffer is too small. You can determine a * sufficient buffer size by calling #PSA_HASH_SIZE(\c alg) @@ -875,7 +1087,11 @@ psa_status_t psa_hash_update(psa_hash_operation_t *operation, * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_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_hash_finish(psa_hash_operation_t *operation, uint8_t *hash, @@ -891,7 +1107,9 @@ psa_status_t psa_hash_finish(psa_hash_operation_t *operation, * compares the calculated hash with the expected hash passed as a * parameter to this function. * - * When this function returns, the operation becomes inactive. + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). * * \note Implementations shall make the best effort to ensure that the * comparison between the actual hash and the expected hash is performed @@ -907,11 +1125,15 @@ psa_status_t psa_hash_finish(psa_hash_operation_t *operation, * The hash of the message was calculated successfully, but it * differs from the expected hash. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not set up, or already completed). + * The operation state is not valid (it must be active). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_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_hash_verify(psa_hash_operation_t *operation, const uint8_t *hash, @@ -925,11 +1147,7 @@ psa_status_t psa_hash_verify(psa_hash_operation_t *operation, * psa_hash_setup() again. * * You may call this function any time after the operation object has - * been initialized by any of the following methods: - * - A call to psa_hash_setup(), whether it succeeds or not. - * - Initializing the \c struct to all-bits-zero. - * - Initializing the \c struct to logical zeros, e.g. - * `psa_hash_operation_t operation = {0}`. + * been initialized by one of the methods described in #psa_hash_operation_t. * * In particular, calling psa_hash_abort() after the operation has been * terminated by a call to psa_hash_abort(), psa_hash_finish() or @@ -938,11 +1156,13 @@ psa_status_t psa_hash_verify(psa_hash_operation_t *operation, * \param[in,out] operation Initialized hash operation. * * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_BAD_STATE - * \p operation is not an active hash operation. * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_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_hash_abort(psa_hash_operation_t *operation); @@ -963,12 +1183,17 @@ psa_status_t psa_hash_abort(psa_hash_operation_t *operation); * * \retval #PSA_SUCCESS * \retval #PSA_ERROR_BAD_STATE - * \p source_operation is not an active hash operation. + * The \p source_operation state is not valid (it must be active). * \retval #PSA_ERROR_BAD_STATE - * \p target_operation is active. + * The \p target_operation state is not valid (it must be inactive). * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \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_hash_clone(const psa_hash_operation_t *source_operation, psa_hash_operation_t *target_operation); @@ -979,6 +1204,94 @@ psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, * @{ */ +/** Calculate the MAC (message authentication code) of a message. + * + * \note To verify the MAC of a message against an + * expected value, use psa_mac_verify() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \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). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p mac_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \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_mac_compute(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Calculate the MAC of a message and compare it with a reference value. + * + * \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). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected value. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \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_mac_verify(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *mac, + const size_t mac_length); + /** The type of the state data structure for multipart MAC operations. * * Before calling any function on a MAC operation object, the application must @@ -1036,47 +1349,49 @@ static psa_mac_operation_t psa_mac_operation_init(void); * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_mac_operation_t, e.g. PSA_MAC_OPERATION_INIT. + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. * -# Call psa_mac_sign_setup() to specify the algorithm and key. - * The key remains associated with the operation even if the content - * of the key slot changes. * -# Call psa_mac_update() zero, one or more times, passing a fragment * of the message each time. The MAC that is calculated is the MAC * of the concatenation of these messages in order. * -# At the end of the message, call psa_mac_sign_finish() to finish * calculating the MAC value and retrieve it. * - * The application may call psa_mac_abort() at any time after the operation + * If an error occurs at any step after a call to psa_mac_sign_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation * has been initialized. * * After a successful call to psa_mac_sign_setup(), the application must * eventually terminate the operation through one of the following methods: - * - A failed call to psa_mac_update(). - * - A call to psa_mac_sign_finish() or psa_mac_abort(). + * - A successful call to psa_mac_sign_finish(). + * - A call to psa_mac_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_mac_operation_t and not yet in use. * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value - * such that #PSA_ALG_IS_MAC(alg) is true). + * such that #PSA_ALG_IS_MAC(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p key is not compatible with \p alg. + * \p handle is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a MAC algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (already set up and not - * subsequently completed). + * The operation state is not valid (it must be inactive). * \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 @@ -1095,10 +1410,8 @@ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the - * documentation for #psa_mac_operation_t, e.g. PSA_MAC_OPERATION_INIT. + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. * -# Call psa_mac_verify_setup() to specify the algorithm and key. - * The key remains associated with the operation even if the content - * of the key slot changes. * -# Call psa_mac_update() zero, one or more times, passing a fragment * of the message each time. The MAC that is calculated is the MAC * of the concatenation of these messages in order. @@ -1106,25 +1419,28 @@ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, * calculating the actual MAC of the message and verify it against * the expected value. * - * The application may call psa_mac_abort() at any time after the operation + * If an error occurs at any step after a call to psa_mac_verify_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation * has been initialized. * * After a successful call to psa_mac_verify_setup(), the application must * eventually terminate the operation through one of the following methods: - * - A failed call to psa_mac_update(). - * - A call to psa_mac_verify_finish() or psa_mac_abort(). + * - A successful call to psa_mac_verify_finish(). + * - A call to psa_mac_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_mac_operation_t and not yet in use. * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. * \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_DOES_NOT_EXIST * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT * \c key is not compatible with \c alg. @@ -1133,10 +1449,11 @@ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (already set up and not - * subsequently completed). + * The operation state is not valid (it must be inactive). * \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 @@ -1151,7 +1468,8 @@ psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, * The application must call psa_mac_sign_setup() or psa_mac_verify_setup() * before calling this function. * - * If this function returns an error status, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). * * \param[in,out] operation Active MAC operation. * \param[in] input Buffer containing the message fragment to add to @@ -1161,11 +1479,16 @@ psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not set up, or already completed). + * The operation state is not valid (it must be active). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_mac_update(psa_mac_operation_t *operation, const uint8_t *input, @@ -1177,7 +1500,9 @@ psa_status_t psa_mac_update(psa_mac_operation_t *operation, * This function calculates the MAC of the message formed by concatenating * the inputs passed to preceding calls to psa_mac_update(). * - * When this function returns, the operation becomes inactive. + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). * * \warning Applications should not call this function if they expect * a specific value for the MAC. Call psa_mac_verify_finish() instead. @@ -1200,14 +1525,20 @@ psa_status_t psa_mac_update(psa_mac_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not set up, or already completed). + * The operation state is not valid (it must be an active mac sign + * operation). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p mac buffer is too small. You can determine a * sufficient buffer size by calling PSA_MAC_FINAL_SIZE(). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_mac_sign_finish(psa_mac_operation_t *operation, uint8_t *mac, @@ -1223,7 +1554,9 @@ psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, * compares the calculated MAC with the expected MAC passed as a * parameter to this function. * - * When this function returns, the operation becomes inactive. + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). * * \note Implementations shall make the best effort to ensure that the * comparison between the actual MAC and the expected MAC is performed @@ -1239,11 +1572,17 @@ psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, * The MAC of the message was calculated successfully, but it * differs from the expected MAC. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not set up, or already completed). + * The operation state is not valid (it must be an active mac verify + * operation). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_mac_verify_finish(psa_mac_operation_t *operation, const uint8_t *mac, @@ -1257,12 +1596,7 @@ psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, * psa_mac_sign_setup() or psa_mac_verify_setup() again. * * You may call this function any time after the operation object has - * been initialized by any of the following methods: - * - A call to psa_mac_sign_setup() or psa_mac_verify_setup(), whether - * it succeeds or not. - * - Initializing the \c struct to all-bits-zero. - * - Initializing the \c struct to logical zeros, e.g. - * `psa_mac_operation_t operation = {0}`. + * been initialized by one of the methods described in #psa_mac_operation_t. * * In particular, calling psa_mac_abort() after the operation has been * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or @@ -1271,11 +1605,13 @@ psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, * \param[in,out] operation Initialized MAC operation. * * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_BAD_STATE - * \p operation is not an active MAC operation. * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_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_mac_abort(psa_mac_operation_t *operation); @@ -1285,6 +1621,100 @@ psa_status_t psa_mac_abort(psa_mac_operation_t *operation); * @{ */ +/** Encrypt a message using a symmetric cipher. + * + * This function encrypts a message with a random IV (initialization + * vector). Use the multipart operation interface with a + * #psa_cipher_operation_t object to provide other forms of IV. + * + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * The output contains the IV followed by + * the ciphertext proper. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_cipher_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Decrypt a message using a symmetric cipher. + * + * This function decrypts a message encrypted with a symmetric cipher. + * + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to decrypt. + * This consists of the IV followed by the + * ciphertext proper. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the plaintext is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_cipher_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + /** The type of the state data structure for multipart cipher operations. * * Before calling any function on a cipher operation object, the application @@ -1339,10 +1769,8 @@ static psa_cipher_operation_t psa_cipher_operation_init(void); * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_cipher_operation_t, e.g. - * PSA_CIPHER_OPERATION_INIT. + * #PSA_CIPHER_OPERATION_INIT. * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key. - * The key remains associated with the operation even if the content - * of the key slot changes. * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to * generate or set the IV (initialization vector). You should use * psa_cipher_generate_iv() unless the protocol you are implementing @@ -1351,20 +1779,23 @@ static psa_cipher_operation_t psa_cipher_operation_init(void); * of the message each time. * -# Call psa_cipher_finish(). * - * The application may call psa_cipher_abort() at any time after the operation + * If an error occurs at any step after a call to psa_cipher_encrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation * has been initialized. * * After a successful call to psa_cipher_encrypt_setup(), the application must * eventually terminate the operation. The following events terminate an * operation: - * - A failed call to psa_cipher_generate_iv(), psa_cipher_set_iv() - * or psa_cipher_update(). - * - A call to psa_cipher_finish() or psa_cipher_abort(). + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_cipher_operation_t and not yet in use. * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. * \param alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). @@ -1372,19 +1803,18 @@ static psa_cipher_operation_t psa_cipher_operation_init(void); * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p key is not compatible with \p alg. + * \p handle is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a cipher algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (already set up and not - * subsequently completed). + * The operation state is not valid (it must be inactive). * \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 @@ -1402,11 +1832,9 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_cipher_operation_t, e.g. - * PSA_CIPHER_OPERATION_INIT. + * #PSA_CIPHER_OPERATION_INIT. * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key. - * The key remains associated with the operation even if the content - * of the key slot changes. - * -# Call psa_cipher_update() with the IV (initialization vector) for the + * -# Call psa_cipher_set_iv() with the IV (initialization vector) for the * decryption. If the IV is prepended to the ciphertext, you can call * psa_cipher_update() on a buffer containing the IV followed by the * beginning of the message. @@ -1414,19 +1842,23 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, * of the message each time. * -# Call psa_cipher_finish(). * - * The application may call psa_cipher_abort() at any time after the operation + * If an error occurs at any step after a call to psa_cipher_decrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation * has been initialized. * * After a successful call to psa_cipher_decrypt_setup(), the application must * eventually terminate the operation. The following events terminate an * operation: - * - A failed call to psa_cipher_update(). - * - A call to psa_cipher_finish() or psa_cipher_abort(). + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_cipher_operation_t and not yet in use. * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. * \param alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). @@ -1434,19 +1866,18 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p key is not compatible with \p alg. + * \p handle is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a cipher algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (already set up and not - * subsequently completed). + * The operation state is not valid (it must be inactive). * \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 @@ -1465,7 +1896,8 @@ psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, * The application must call psa_cipher_encrypt_setup() before * calling this function. * - * If this function returns an error status, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). * * \param[in,out] operation Active cipher operation. * \param[out] iv Buffer where the generated IV is to be written. @@ -1476,28 +1908,34 @@ psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not set up, or IV already set). + * The operation state is not valid (it must be active, with no IV set). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p iv buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_cipher_generate_iv(psa_cipher_operation_t *operation, - unsigned char *iv, + uint8_t *iv, size_t iv_size, size_t *iv_length); /** Set the IV for a symmetric encryption or decryption operation. * - * This function sets the random IV (initialization vector), nonce + * This function sets the IV (initialization vector), nonce * or initial counter value for the encryption or decryption operation. * * The application must call psa_cipher_encrypt_setup() before * calling this function. * - * If this function returns an error status, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). * * \note When encrypting, applications should use psa_cipher_generate_iv() * instead of this function, unless implementing a protocol that requires @@ -1510,17 +1948,23 @@ psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not set up, or IV already set). + * The operation state is not valid (it must be an active cipher + * encrypt operation, with no IV set). * \retval #PSA_ERROR_INVALID_ARGUMENT * The size of \p iv is not acceptable for the chosen algorithm, * or the chosen algorithm does not use an IV. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_cipher_set_iv(psa_cipher_operation_t *operation, - const unsigned char *iv, + const uint8_t *iv, size_t iv_length); /** Encrypt or decrypt a message fragment in an active cipher operation. @@ -1532,7 +1976,8 @@ psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, * 2. If the algorithm requires an IV, call psa_cipher_generate_iv() * (recommended when encrypting) or psa_cipher_set_iv(). * - * If this function returns an error status, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). * * \param[in,out] operation Active cipher operation. * \param[in] input Buffer containing the message fragment to @@ -1546,19 +1991,24 @@ psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not set up, IV required but - * not set, or already completed). + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_cipher_update(psa_cipher_operation_t *operation, const uint8_t *input, size_t input_length, - unsigned char *output, + uint8_t *output, size_t output_size, size_t *output_length); @@ -1573,7 +2023,9 @@ psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, * formed by concatenating the inputs passed to preceding calls to * psa_cipher_update(). * - * When this function returns, the operation becomes inactive. + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). * * \param[in,out] operation Active cipher operation. * \param[out] output Buffer where the output is to be written. @@ -1583,15 +2035,28 @@ psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input size passed to this operation is not valid for + * this particular algorithm. For example, the algorithm is a based + * on block cipher and requires a whole number of blocks, but the + * total input size is not a multiple of the block size. + * \retval #PSA_ERROR_INVALID_PADDING + * This is a decryption operation for an algorithm that includes + * padding, and the ciphertext does not contain valid padding. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not set up, IV required but - * not set, or already completed). + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_cipher_finish(psa_cipher_operation_t *operation, uint8_t *output, @@ -1606,12 +2071,7 @@ psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again. * * You may call this function any time after the operation object has - * been initialized by any of the following methods: - * - A call to psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup(), - * whether it succeeds or not. - * - Initializing the \c struct to all-bits-zero. - * - Initializing the \c struct to logical zeros, e.g. - * `psa_cipher_operation_t operation = {0}`. + * been initialized as described in #psa_cipher_operation_t. * * In particular, calling psa_cipher_abort() after the operation has been * terminated by a call to psa_cipher_abort() or psa_cipher_finish() @@ -1620,11 +2080,13 @@ psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, * \param[in,out] operation Initialized cipher operation. * * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_BAD_STATE - * \p operation is not an active cipher operation. * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_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_cipher_abort(psa_cipher_operation_t *operation); @@ -1660,21 +2122,23 @@ psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\p alg, * \p plaintext_length). * \param[out] ciphertext_length On success, the size of the output - * in the \b ciphertext buffer. + * in the \p ciphertext buffer. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p key is not compatible with \p alg. + * \p handle is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not an AEAD algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p ciphertext_size is too small * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE * \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 @@ -1716,23 +2180,25 @@ psa_status_t psa_aead_encrypt(psa_key_handle_t handle, * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\p alg, * \p ciphertext_length). * \param[out] plaintext_length On success, the size of the output - * in the \b plaintext buffer. + * in the \p plaintext buffer. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_INVALID_SIGNATURE * The ciphertext is not authentic. * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p key is not compatible with \p alg. + * \p handle is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not an AEAD algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p plaintext_size or \p nonce_length is too small * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE * \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 @@ -1750,6 +2216,627 @@ psa_status_t psa_aead_decrypt(psa_key_handle_t handle, size_t plaintext_size, size_t *plaintext_length); +/** The type of the state data structure for multipart AEAD operations. + * + * Before calling any function on an AEAD operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_aead_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_aead_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_AEAD_OPERATION_INIT, + * for example: + * \code + * psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_aead_operation_init() + * to the structure, for example: + * \code + * psa_aead_operation_t operation; + * operation = psa_aead_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_aead_operation_s psa_aead_operation_t; + +/** \def PSA_AEAD_OPERATION_INIT + * + * This macro returns a suitable initializer for an AEAD operation object of + * type #psa_aead_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_AEAD_OPERATION_INIT {0} +#endif + +/** Return an initial value for an AEAD operation object. + */ +static psa_aead_operation_t psa_aead_operation_init(void); + +/** Set the key for a multipart authenticated encryption operation. + * + * The sequence of operations to encrypt a message with authentication + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_aead_operation_t, e.g. + * #PSA_AEAD_OPERATION_INIT. + * -# Call psa_aead_encrypt_setup() to specify the algorithm and key. + * -# If needed, call psa_aead_set_lengths() to specify the length of the + * inputs to the subsequent calls to psa_aead_update_ad() and + * psa_aead_update(). See the documentation of psa_aead_set_lengths() + * for details. + * -# Call either psa_aead_generate_nonce() or psa_aead_set_nonce() to + * generate or set the nonce. You should use + * psa_aead_generate_nonce() unless the protocol you are implementing + * requires a specific nonce value. + * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment + * of the non-encrypted additional authenticated data each time. + * -# Call psa_aead_update() zero, one or more times, passing a fragment + * of the message to encrypt each time. + * -# Call psa_aead_finish(). + * + * If an error occurs at any step after a call to psa_aead_encrypt_setup(), + * the operation will need to be reset by a call to psa_aead_abort(). The + * application may call psa_aead_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_aead_encrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_aead_finish(). + * - A call to psa_aead_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_aead_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_encrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Set the key for a multipart authenticated decryption operation. + * + * The sequence of operations to decrypt a message with authentication + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_aead_operation_t, e.g. + * #PSA_AEAD_OPERATION_INIT. + * -# Call psa_aead_decrypt_setup() to specify the algorithm and key. + * -# If needed, call psa_aead_set_lengths() to specify the length of the + * inputs to the subsequent calls to psa_aead_update_ad() and + * psa_aead_update(). See the documentation of psa_aead_set_lengths() + * for details. + * -# Call psa_aead_set_nonce() with the nonce for the decryption. + * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment + * of the non-encrypted additional authenticated data each time. + * -# Call psa_aead_update() zero, one or more times, passing a fragment + * of the ciphertext to decrypt each time. + * -# Call psa_aead_verify(). + * + * If an error occurs at any step after a call to psa_aead_decrypt_setup(), + * the operation will need to be reset by a call to psa_aead_abort(). The + * application may call psa_aead_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_aead_decrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_aead_verify(). + * - A call to psa_aead_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_aead_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_decrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Generate a random nonce for an authenticated encryption operation. + * + * This function generates a random nonce for the authenticated encryption + * operation with an appropriate size for the chosen algorithm, key type + * and key size. + * + * The application must call psa_aead_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[out] nonce Buffer where the generated nonce is to be + * written. + * \param nonce_size Size of the \p nonce buffer in bytes. + * \param[out] nonce_length On success, the number of bytes of the + * generated nonce. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active aead encrypt + operation, with no nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p nonce buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_generate_nonce(psa_aead_operation_t *operation, + uint8_t *nonce, + size_t nonce_size, + size_t *nonce_length); + +/** Set the nonce for an authenticated encryption or decryption operation. + * + * This function sets the nonce for the authenticated + * encryption or decryption operation. + * + * The application must call psa_aead_encrypt_setup() or + * psa_aead_decrypt_setup() before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \note When encrypting, applications should use psa_aead_generate_nonce() + * instead of this function, unless implementing a protocol that requires + * a non-random IV. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] nonce Buffer containing the nonce to use. + * \param nonce_length Size of the nonce in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with no nonce + * set). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p nonce is not acceptable for the chosen algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_set_nonce(psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length); + +/** Declare the lengths of the message and additional data for AEAD. + * + * The application must call this function before calling + * psa_aead_update_ad() or psa_aead_update() if the algorithm for + * the operation requires it. If the algorithm does not require it, + * calling this function is optional, but if this function is called + * then the implementation must enforce the lengths. + * + * You may call this function before or after setting the nonce with + * psa_aead_set_nonce() or psa_aead_generate_nonce(). + * + * - For #PSA_ALG_CCM, calling this function is required. + * - For the other AEAD algorithms defined in this specification, calling + * this function is not required. + * - For vendor-defined algorithm, refer to the vendor documentation. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param ad_length Size of the non-encrypted additional + * authenticated data in bytes. + * \param plaintext_length Size of the plaintext to encrypt in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, and + * psa_aead_update_ad() and psa_aead_update() must not have been + * called yet). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * At least one of the lengths is not acceptable for the chosen + * algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_aead_set_lengths(psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length); + +/** Pass additional data to an active AEAD operation. + * + * Additional data is authenticated, but not encrypted. + * + * You may call this function multiple times to pass successive fragments + * of the additional data. You may not call this function after passing + * data to encrypt or decrypt with psa_aead_update(). + * + * Before calling this function, you must: + * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). + * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, + * there is no guarantee that the input is valid. Therefore, until + * you have called psa_aead_verify() and it has returned #PSA_SUCCESS, + * treat the input as untrusted and prepare to undo any action that + * depends on the input if psa_aead_verify() returns an error status. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the fragment of + * additional data. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, have a nonce + * set, have lengths set if required by the algorithm, and + * psa_aead_update() must not have been called yet). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input length overflows the additional data length that + * was previously specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_update_ad(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Encrypt or decrypt a message fragment in an active AEAD operation. + * + * Before calling this function, you must: + * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). + * The choice of setup function determines whether this function + * encrypts or decrypts its input. + * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). + * 3. Call psa_aead_update_ad() to pass all the additional data. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, + * there is no guarantee that the input is valid. Therefore, until + * you have called psa_aead_verify() and it has returned #PSA_SUCCESS: + * - Do not use the output in any way other than storing it in a + * confidential location. If you take any action that depends + * on the tentative decrypted data, this action will need to be + * undone if the input turns out not to be valid. Furthermore, + * if an adversary can observe that this action took place + * (for example through timing), they may be able to use this + * fact as an oracle to decrypt any message encrypted with the + * same key. + * - In particular, do not copy the output anywhere but to a + * memory or storage space that you have exclusive access to. + * + * This function does not require the input to be aligned to any + * particular block boundary. If the implementation can only process + * a whole block at a time, it must consume all the input provided, but + * it may delay the end of the corresponding output until a subsequent + * call to psa_aead_update(), psa_aead_finish() or psa_aead_verify() + * provides sufficient input. The amount of data that can be delayed + * in this way is bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * This must be at least + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, + * \p input_length) where \c alg is the + * algorithm that is being calculated. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, have a nonce + * set, and have lengths set if required by the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * You can determine a sufficient buffer size by calling + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, \p input_length) + * where \c alg is the algorithm that is being calculated. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input length overflows the plaintext length that + * was previously specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_update(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Finish encrypting a message in an AEAD operation. + * + * The operation must have been set up with psa_aead_encrypt_setup(). + * + * This function finishes the authentication of the additional data + * formed by concatenating the inputs passed to preceding calls to + * psa_aead_update_ad() with the plaintext formed by concatenating the + * inputs passed to preceding calls to psa_aead_update(). + * + * This function has two output buffers: + * - \p ciphertext contains trailing ciphertext that was buffered from + * preceding calls to psa_aead_update(). + * - \p tag contains the authentication tag. Its length is always + * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is the AEAD algorithm + * that the operation performs. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[out] ciphertext Buffer where the last part of the ciphertext + * is to be written. + * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be at least + * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) where + * \c alg is the algorithm that is being + * calculated. + * \param[out] ciphertext_length On success, the number of bytes of + * returned ciphertext. + * \param[out] tag Buffer where the authentication tag is + * to be written. + * \param tag_size Size of the \p tag buffer in bytes. + * This must be at least + * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is + * the algorithm that is being calculated. + * \param[out] tag_length On success, the number of bytes + * that make up the returned tag. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active encryption + * operation with a nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p ciphertext or \p tag buffer is too small. + * You can determine a sufficient buffer size for \p ciphertext by + * calling #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) + * where \c alg is the algorithm that is being calculated. + * You can determine a sufficient buffer size for \p tag by + * calling #PSA_AEAD_TAG_LENGTH(\c alg). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update() so far is + * less than the plaintext length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_finish(psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length); + +/** Finish authenticating and decrypting a message in an AEAD operation. + * + * The operation must have been set up with psa_aead_decrypt_setup(). + * + * This function finishes the authenticated decryption of the message + * components: + * + * - The additional data consisting of the concatenation of the inputs + * passed to preceding calls to psa_aead_update_ad(). + * - The ciphertext consisting of the concatenation of the inputs passed to + * preceding calls to psa_aead_update(). + * - The tag passed to this function call. + * + * If the authentication tag is correct, this function outputs any remaining + * plaintext and reports success. If the authentication tag is not correct, + * this function returns #PSA_ERROR_INVALID_SIGNATURE. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual tag and the expected tag is performed + * in constant time. + * + * \param[in,out] operation Active AEAD operation. + * \param[out] plaintext Buffer where the last part of the plaintext + * is to be written. This is the remaining data + * from previous calls to psa_aead_update() + * that could not be processed until the end + * of the input. + * \param plaintext_size Size of the \p plaintext buffer in bytes. + * This must be at least + * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) where + * \c alg is the algorithm that is being + * calculated. + * \param[out] plaintext_length On success, the number of bytes of + * returned plaintext. + * \param[in] tag Buffer containing the authentication tag. + * \param tag_length Size of the \p tag buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculations were successful, but the authentication tag is + * not correct. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active decryption + * operation with a nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p plaintext buffer is too small. + * You can determine a sufficient buffer size for \p plaintext by + * calling #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) + * where \c alg is the algorithm that is being calculated. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update() so far is + * less than the plaintext length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_verify(psa_aead_operation_t *operation, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag, + size_t tag_length); + +/** Abort an AEAD operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_aead_encrypt_setup() or psa_aead_decrypt_setup() again. + * + * You may call this function any time after the operation object has + * been initialized as described in #psa_aead_operation_t. + * + * In particular, calling psa_aead_abort() after the operation has been + * terminated by a call to psa_aead_abort(), psa_aead_finish() or + * psa_aead_verify() is safe and has no effect. + * + * \param[in,out] operation Initialized AEAD operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_aead_abort(psa_aead_operation_t *operation); + /**@}*/ /** \defgroup asymmetric Asymmetric cryptography @@ -1768,7 +2855,7 @@ psa_status_t psa_aead_decrypt(psa_key_handle_t handle, * \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. + * the type of \p handle. * \param[in] hash The hash or message to sign. * \param hash_length Size of the \p hash buffer in bytes. * \param[out] signature Buffer where the signature is to be written. @@ -1777,31 +2864,34 @@ psa_status_t psa_aead_decrypt(psa_key_handle_t handle, * that make up the returned signature value. * * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p signature buffer is too small. You can * determine a sufficient buffer size by calling - * #PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size - * respectively of \p key. + * respectively of \p handle. * \retval #PSA_ERROR_NOT_SUPPORTED * \retval #PSA_ERROR_INVALID_ARGUMENT * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY * \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_asymmetric_sign(psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *hash, - size_t hash_length, - uint8_t *signature, - size_t signature_size, - size_t *signature_length); +psa_status_t psa_sign_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length); /** * \brief Verify the signature a hash or short message using a public key. @@ -1815,7 +2905,7 @@ psa_status_t psa_asymmetric_sign(psa_key_handle_t handle, * \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. + * the type of \p handle. * \param[in] hash The hash or message whose signature is to be * verified. * \param hash_length Size of the \p hash buffer in bytes. @@ -1824,6 +2914,8 @@ psa_status_t psa_asymmetric_sign(psa_key_handle_t handle, * * \retval #PSA_SUCCESS * The signature is valid. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculation was perfomed successfully, but the passed * signature is not a valid signature. @@ -1832,18 +2924,19 @@ psa_status_t psa_asymmetric_sign(psa_key_handle_t handle, * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE * \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_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); +psa_status_t psa_verify_hash(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); /** * \brief Encrypt a short message with a public key. @@ -1852,7 +2945,7 @@ psa_status_t psa_asymmetric_verify(psa_key_handle_t handle, * 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. + * compatible with the type of \p handle. * \param[in] input The message to encrypt. * \param input_length Size of the \p input buffer in bytes. * \param[in] salt A salt or label, if supported by the @@ -1874,18 +2967,21 @@ psa_status_t psa_asymmetric_verify(psa_key_handle_t handle, * that make up the returned output. * * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size - * respectively of \p key. + * respectively of \p handle. * \retval #PSA_ERROR_NOT_SUPPORTED * \retval #PSA_ERROR_INVALID_ARGUMENT * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). @@ -1908,7 +3004,7 @@ psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle, * \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. + * compatible with the type of \p handle. * \param[in] input The message to decrypt. * \param input_length Size of the \p input buffer in bytes. * \param[in] salt A salt or label, if supported by the @@ -1930,18 +3026,21 @@ psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle, * that make up the returned output. * * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size - * respectively of \p key. + * respectively of \p handle. * \retval #PSA_ERROR_NOT_SUPPORTED * \retval #PSA_ERROR_INVALID_ARGUMENT * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY * \retval #PSA_ERROR_INVALID_PADDING * \retval #PSA_ERROR_BAD_STATE @@ -1961,284 +3060,327 @@ psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle, /**@}*/ -/** \defgroup generators Generators +/** \defgroup key_derivation Key derivation and pseudorandom generation * @{ */ -/** The type of the state data structure for generators. +/** The type of the state data structure for key derivation operations. * - * Before calling any function on a generator, the application must - * initialize it by any of the following means: + * Before calling any function on a key derivation operation object, the + * application must initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code - * psa_crypto_generator_t generator; - * memset(&generator, 0, sizeof(generator)); + * psa_key_derivation_operation_t operation; + * memset(&operation, 0, sizeof(operation)); * \endcode * - Initialize the structure to logical zero values, for example: * \code - * psa_crypto_generator_t generator = {0}; + * psa_key_derivation_operation_t operation = {0}; * \endcode - * - Initialize the structure to the initializer #PSA_CRYPTO_GENERATOR_INIT, + * - Initialize the structure to the initializer #PSA_KEY_DERIVATION_OPERATION_INIT, * for example: * \code - * psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; + * psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; * \endcode - * - Assign the result of the function psa_crypto_generator_init() + * - Assign the result of the function psa_key_derivation_operation_init() * to the structure, for example: * \code - * psa_crypto_generator_t generator; - * generator = psa_crypto_generator_init(); + * psa_key_derivation_operation_t operation; + * operation = psa_key_derivation_operation_init(); * \endcode * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure except * as directed by the documentation of a specific implementation. */ -typedef struct psa_crypto_generator_s psa_crypto_generator_t; +typedef struct psa_key_derivation_s psa_key_derivation_operation_t; -/** \def PSA_CRYPTO_GENERATOR_INIT +/** \def PSA_KEY_DERIVATION_OPERATION_INIT * - * This macro returns a suitable initializer for a generator object - * of type #psa_crypto_generator_t. + * This macro returns a suitable initializer for a key derivation operation + * object of type #psa_key_derivation_operation_t. */ #ifdef __DOXYGEN_ONLY__ /* This is an example definition for documentation purposes. * Implementations should define a suitable value in `crypto_struct.h`. */ -#define PSA_CRYPTO_GENERATOR_INIT {0} +#define PSA_KEY_DERIVATION_OPERATION_INIT {0} #endif -/** Return an initial value for a generator object. - */ -static psa_crypto_generator_t psa_crypto_generator_init(void); - -/** Retrieve the current capacity of a generator. - * - * The capacity of a generator is the maximum number of bytes that it can - * return. Reading *N* bytes from a generator reduces its capacity by *N*. - * - * \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 +/** Return an initial value for a key derivation operation object. */ -psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator, - size_t *capacity); +static psa_key_derivation_operation_t psa_key_derivation_operation_init(void); -/** Read some data from a generator. - * - * This function reads and returns a sequence of bytes from a generator. - * The data that is read is discarded from the generator. The generator's - * capacity is decreased by the number of bytes read. +/** Set up a key derivation operation. * - * \param[in,out] generator The generator object to read from. - * \param[out] output Buffer where the generator output will be - * written. - * \param output_length Number of bytes to output. + * A key derivation algorithm takes some inputs and uses them to generate + * a byte stream in a deterministic way. + * This byte stream can be used to produce keys and other + * cryptographic material. + * + * To derive a key: + * -# Start with an initialized object of type #psa_key_derivation_operation_t. + * -# Call psa_key_derivation_setup() to select the algorithm. + * -# Provide the inputs for the key derivation by calling + * psa_key_derivation_input_bytes() or psa_key_derivation_input_key() + * as appropriate. Which inputs are needed, in what order, and whether + * they may be keys and if so of what type depends on the algorithm. + * -# Optionally set the operation's maximum capacity with + * psa_key_derivation_set_capacity(). You may do this before, in the middle + * of or after providing inputs. For some algorithms, this step is mandatory + * because the output depends on the maximum capacity. + * -# To derive a key, call psa_key_derivation_output_key(). + * To derive a byte string for a different purpose, call + * psa_key_derivation_output_bytes(). + * Successive calls to these functions use successive output bytes + * calculated by the key derivation algorithm. + * -# Clean up the key derivation operation object with + * psa_key_derivation_abort(). + * + * If this function returns an error, the key derivation operation object is + * not changed. + * + * If an error occurs at any step after a call to psa_key_derivation_setup(), + * the operation will need to be reset by a call to psa_key_derivation_abort(). + * + * Implementations must reject an attempt to derive a key of size 0. + * + * \param[in,out] operation The key derivation operation object + * to set up. It must + * have been initialized but not set up yet. + * \param alg The key derivation algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true). * * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INSUFFICIENT_DATA - * 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 + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c alg is not a key derivation algorithm. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \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_read(psa_crypto_generator_t *generator, - uint8_t *output, - size_t output_length); +psa_status_t psa_key_derivation_setup( + psa_key_derivation_operation_t *operation, + psa_algorithm_t alg); -/** Create a symmetric key from data read from a generator. +/** Retrieve the current capacity of a key derivation operation. * - * This function reads a sequence of bytes from a generator and imports - * these bytes as a key. - * The data that is read is discarded from the generator. The generator's - * capacity is decreased by the number of bytes read. + * The capacity of a key derivation is the maximum number of bytes that it can + * return. When you get *N* bytes of output from a key derivation operation, + * this reduces its capacity by *N*. * - * This function is equivalent to calling #psa_generator_read and - * passing the resulting output to #psa_import_key, but - * if the implementation provides an isolation boundary then - * the key material is not exposed outside the isolation boundary. - * - * \param handle Handle to the slot where the key will be stored. - * It must have been obtained by calling - * psa_allocate_key() or psa_create_key() and must - * not contain 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. + * \param[in] operation The operation to query. + * \param[out] capacity On success, the capacity of the operation. * * \retval #PSA_SUCCESS - * Success. - * If the key is persistent, the key material and the key's metadata - * have been saved to persistent storage. - * \retval #PSA_ERROR_INSUFFICIENT_DATA - * 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 - * 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_HANDLE - * \retval #PSA_ERROR_ALREADY_EXISTS - * 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_BAD_STATE + * The operation state is not valid (it must be active). * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_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_handle_t handle, - psa_key_type_t type, - size_t bits, - psa_crypto_generator_t *generator); +psa_status_t psa_key_derivation_get_capacity( + const psa_key_derivation_operation_t *operation, + size_t *capacity); -/** Abort a generator. - * - * Once a generator has been aborted, its capacity is zero. - * Aborting a generator frees all associated resources except for the - * \c generator structure itself. +/** Set the maximum capacity of a key derivation operation. * - * This function may be called at any time as long as the generator - * object has been initialized to #PSA_CRYPTO_GENERATOR_INIT, to - * psa_crypto_generator_init() or a zero value. In particular, it is valid - * to call psa_generator_abort() twice, or to call psa_generator_abort() - * on a generator that has not been set up. + * The capacity of a key derivation operation is the maximum number of bytes + * that the key derivation operation can return from this point onwards. * - * Once aborted, the generator object may be called. - * - * \param[in,out] generator The generator to abort. + * \param[in,out] operation The key derivation operation object to modify. + * \param capacity The new capacity of the operation. + * It must be less or equal to the operation's + * current capacity. * * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p capacity is larger than the operation's current capacity. + * In this case, the operation object remains valid and its capacity + * remains unchanged. * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_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_abort(psa_crypto_generator_t *generator); +psa_status_t psa_key_derivation_set_capacity( + psa_key_derivation_operation_t *operation, + size_t capacity); -/** Use the maximum possible capacity for a generator. +/** Use the maximum possible capacity for a key derivation operation. * - * Use this value as the capacity argument when setting up a generator - * to indicate that the generator should have the maximum possible capacity. - * The value of the maximum possible capacity depends on the generator + * Use this value as the capacity argument when setting up a key derivation + * to indicate that the operation should have the maximum possible capacity. + * The value of the maximum possible capacity depends on the key derivation * algorithm. */ -#define PSA_GENERATOR_UNBRIDLED_CAPACITY ((size_t)(-1)) +#define PSA_KEY_DERIVATION_UNLIMITED_CAPACITY ((size_t)(-1)) -/**@}*/ - -/** \defgroup derivation Key derivation - * @{ - */ - -/** Set up a key derivation operation. +/** Provide an input for key derivation or key agreement. * - * A key derivation algorithm takes three inputs: a secret input \p key and - * two non-secret inputs \p label and p salt. - * The result of this function is a byte generator which can - * be used to produce keys and other cryptographic material. + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. * - * The role of \p label and \p salt is as follows: - * - For HKDF (#PSA_ALG_HKDF), \p salt is the salt used in the "extract" step - * and \p label is the info string used in the "expand" step. + * This function passes direct inputs, which is usually correct for + * non-secret inputs. To pass a secret input, which should be in a key + * object, call psa_key_derivation_input_key() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. * - * \param[in,out] generator The generator object to set up. It must have - * been initialized as per the documentation for - * #psa_crypto_generator_t and not yet in 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). - * \param[in] salt Salt to use. - * \param salt_length Size of the \p salt buffer in bytes. - * \param[in] label Label to use. - * \param label_length Size of the \p label buffer in bytes. - * \param capacity The maximum number of bytes that the - * generator will be able to provide. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param[in] data Input data to use. + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow direct inputs. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step. + * \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_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length); + +/** Provide an input for key derivation in the form of a key. + * + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function obtains input from a key object, which is usually correct for + * secret inputs or for non-secret personalization strings kept in the key + * store. To pass a non-secret parameter which is not in the key store, + * call psa_key_derivation_input_bytes() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param handle Handle to the key. It must have an + * appropriate type for \p step and must + * allow the usage #PSA_KEY_USAGE_DERIVE. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT - * \c key is not compatible with \c alg, - * or \p capacity is too large for the specified algorithm and key. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \c alg is not supported or is not a key derivation algorithm. + * \c step is not compatible with the operation's algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow key inputs of the given type + * or does not allow key inputs at all. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step. * \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_key_derivation(psa_crypto_generator_t *generator, - psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *salt, - size_t salt_length, - const uint8_t *label, - size_t label_length, - size_t capacity); +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t handle); -/** Set up a key agreement operation. +/** Perform a key agreement and use the shared secret as input to a key + * derivation. * * A key agreement algorithm takes two inputs: a private key \p private_key * a public key \p peer_key. - * The result of this function is a byte generator which can - * be used to produce keys and other cryptographic material. - * - * The resulting generator always has the maximum capacity permitted by - * the algorithm. - * - * \param[in,out] generator The generator object to set up. It must have been - * initialized as per the documentation for - * #psa_crypto_generator_t and not yet in use. - * \param private_key Handle to the private key to use. + * The result of this function is passed as input to a key derivation. + * The output of this key derivation can be extracted by reading from the + * resulting operation to produce keys and other cryptographic material. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() with a + * key agreement and derivation algorithm + * \c alg (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_AGREEMENT(\c alg) is true + * and #PSA_ALG_IS_RAW_KEY_AGREEMENT(\c alg) + * is false). + * The operation must be ready for an + * input of the type given by \p step. + * \param step Which step the input data is for. + * \param private_key Handle to the private key to use. * \param[in] peer_key Public key of the peer. The peer key must be in the * same format that psa_import_key() accepts for the * public key type corresponding to the type of - * \p private_key. That is, this function performs the + * private_key. That is, this function performs the * equivalent of - * `psa_import_key(internal_public_key_handle, - * PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(private_key_type), - * peer_key, peer_key_length)` where - * `private_key_type` is the type of \p private_key. - * For example, for EC keys, this means that \p - * peer_key is interpreted as a point on the curve - * that the private key is associated with. The - * standard formats for public keys are documented in - * the documentation of psa_export_public_key(). - * \param peer_key_length Size of \p peer_key in bytes. - * \param alg The key agreement algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_KEY_AGREEMENT(\p alg) is true). + * #psa_import_key(..., + * `peer_key`, `peer_key_length`) where + * with key attributes indicating the public key + * type corresponding to the type of `private_key`. + * For example, for EC keys, this means that peer_key + * is interpreted as a point on the curve that the + * private key is on. The standard formats for public + * keys are documented in the documentation of + * psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this key agreement \p step. * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT * \c private_key is not compatible with \c alg, @@ -2246,16 +3388,290 @@ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator, * \c private_key. * \retval #PSA_ERROR_NOT_SUPPORTED * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow an input resulting from a key agreement. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_key_derivation_key_agreement( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length); + +/** Read some data from a key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm and + * return those bytes. + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads the requested number of bytes from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] output Buffer where the output will be written. + * \param output_length Number of bytes to output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The operation's capacity was less than + * \p output_length bytes. Note that in this case, + * no output is written to the output buffer. + * The operation'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 + * The operation state is not valid (it must be active and completed + * all required input steps). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, + size_t output_length); + +/** Derive a key from an ongoing key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm + * and uses those bytes to generate a key deterministically. + * The key's location, usage policy, type and size are taken from + * \p attributes. + * + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads as many bytes as required from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * How much output is produced and consumed from the operation, and how + * the key is derived, depends on the key type: + * + * - For key types for which the key is an arbitrary sequence of bytes + * of a given size, this function is functionally equivalent to + * calling #psa_key_derivation_output_bytes + * and passing the resulting output to #psa_import_key. + * However, this function has a security benefit: + * if the implementation provides an isolation boundary then + * the key material is not exposed outside the isolation boundary. + * As a consequence, for these key types, this function always consumes + * exactly (\p bits / 8) bytes from the operation. + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_AES; + * - #PSA_KEY_TYPE_ARC4; + * - #PSA_KEY_TYPE_CAMELLIA; + * - #PSA_KEY_TYPE_DERIVE; + * - #PSA_KEY_TYPE_HMAC. + * + * - For ECC keys on a Montgomery elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Montgomery curve), this function always draws a byte string whose + * length is determined by the curve, and sets the mandatory bits + * accordingly. That is: + * + * - #PSA_ECC_CURVE_CURVE25519: draw a 32-byte string + * and process it as specified in RFC 7748 §5. + * - #PSA_ECC_CURVE_CURVE448: draw a 56-byte string + * and process it as specified in RFC 7748 §5. + * + * - For key types for which the key is represented by a single sequence of + * \p bits bits with constraints as to which bit sequences are acceptable, + * this function draws a byte string of length (\p bits / 8) bytes rounded + * up to the nearest whole number of bytes. If the resulting byte string + * is acceptable, it becomes the key, otherwise the drawn bytes are discarded. + * This process is repeated until an acceptable byte string is drawn. + * The byte string drawn from the operation is interpreted as specified + * for the output produced by psa_export_key(). + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_DES. + * Force-set the parity bits, but discard forbidden weak keys. + * For 2-key and 3-key triple-DES, the three keys are generated + * successively (for example, for 3-key triple-DES, + * if the first 8 bytes specify a weak key and the next 8 bytes do not, + * discard the first 8 bytes, use the next 8 bytes as the first key, + * and continue reading output from the operation to derive the other + * two keys). + * - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEY_PAIR(\c group) + * where \c group designates any Diffie-Hellman group) and + * ECC keys on a Weierstrass elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Weierstrass curve). + * For these key types, interpret the byte string as integer + * in big-endian order. Discard it if it is not in the range + * [0, *N* - 2] where *N* is the boundary of the private key domain + * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, + * or the order of the curve's base point for ECC). + * Add 1 to the resulting integer and use this as the private key *x*. + * This method allows compliance to NIST standards, specifically + * the methods titled "key-pair generation by testing candidates" + * in NIST SP 800-56A §5.6.1.1.4 for Diffie-Hellman, + * in FIPS 186-4 §B.1.2 for DSA, and + * in NIST SP 800-56A §5.6.1.2.2 or + * FIPS 186-4 §B.4.2 for elliptic curve keys. + * + * - For other key types, including #PSA_KEY_TYPE_RSA_KEY_PAIR, + * the way in which the operation output is consumed is + * implementation-defined. + * + * In all cases, the data that is read is discarded from the operation. + * The operation's capacity is decreased by the number of bytes read. + * + * For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET, + * the input to that step must be provided with psa_key_derivation_input_key(). + * Future versions of this specification may include additional restrictions + * on the derived key based on the attributes and strength of the secret key. + * + * \param[in] attributes The attributes for the new key. + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. + * + * \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_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * There was not enough data to create the desired key. + * Note that in this case, no output is written to the output buffer. + * The operation'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 + * The key type or key size is not supported, either by the + * implementation in general or in this particular location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The provided key attributes are not valid for the operation. + * \retval #PSA_ERROR_NOT_PERMITTED + * The #PSA_KEY_DERIVATION_INPUT_SECRET input was not provided through + * a key. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + psa_key_handle_t *handle); + +/** Abort a key derivation operation. + * + * Aborting an operation frees all associated resources except for the \c + * operation structure itself. Once aborted, the operation object can be reused + * for another operation by calling psa_key_derivation_setup() again. + * + * This function may be called at any time after the operation + * object has been initialized as described in #psa_key_derivation_operation_t. + * + * In particular, it is valid to call psa_key_derivation_abort() twice, or to + * call psa_key_derivation_abort() on an operation that has not been set up. + * + * \param[in,out] operation The operation to abort. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_key_derivation_abort( + psa_key_derivation_operation_t *operation); + +/** Perform a key agreement and return the raw shared secret. + * + * \warning The raw result of a key agreement algorithm such as finite-field + * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should + * not be used directly as key material. It should instead be passed as + * input to a key derivation algorithm. To chain a key agreement with + * a key derivation, use psa_key_derivation_key_agreement() and other + * functions from the key derivation interface. + * + * \param alg The key agreement algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_RAW_KEY_AGREEMENT(\p alg) + * is true). + * \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 + * keys are documented in the documentation + * of psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a key agreement algorithm + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p private_key is not compatible with \p alg, + * or \p peer_key is not valid for \p alg or not compatible with + * \p private_key. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p output_size is too small + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported key agreement algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_key_agreement(psa_crypto_generator_t *generator, - psa_key_handle_t private_key, - const uint8_t *peer_key, - size_t peer_key_length, - psa_algorithm_t alg); +psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length); /**@}*/ @@ -2278,9 +3694,10 @@ psa_status_t psa_key_agreement(psa_crypto_generator_t *generator, * \retval #PSA_SUCCESS * \retval #PSA_ERROR_NOT_SUPPORTED * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_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 @@ -2289,73 +3706,48 @@ psa_status_t psa_key_agreement(psa_crypto_generator_t *generator, psa_status_t psa_generate_random(uint8_t *output, size_t output_size); -/** Extra parameters for RSA key generation. - * - * You may pass a pointer to a structure of this type as the \c extra - * parameter to psa_generate_key(). - */ -typedef struct { - uint32_t e; /**< Public exponent value. Default: 65537. */ -} psa_generate_key_extra_rsa; - /** * \brief Generate a key or key pair. * - * \param handle Handle to the slot where the key will be stored. - * It must have been obtained by calling - * psa_allocate_key() or psa_create_key() and must - * not contain 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 - * interpretation of this parameter depends on - * \p type. All types support \c NULL to use - * default parameters. Implementation that support - * the generation of vendor-specific key types - * that allow extra parameters shall document - * the format of these extra parameters and - * the default values. For standard parameters, - * the meaning of \p extra is as follows: - * - For a symmetric key type (a type such - * that #PSA_KEY_TYPE_IS_ASYMMETRIC(\p type) is - * false), \p extra must be \c NULL. - * - For an elliptic curve key type (a type - * such that #PSA_KEY_TYPE_IS_ECC(\p type) is - * false), \p extra must be \c NULL. - * - For an RSA key (\p type is - * #PSA_KEY_TYPE_RSA_KEYPAIR), \p extra is an - * optional #psa_generate_key_extra_rsa structure - * specifying the public exponent. The - * default public exponent used when \p extra - * is \c NULL is 65537. - * \param extra_size Size of the buffer that \p extra - * points to, in bytes. Note that if \p extra is - * \c NULL then \p extra_size must be zero. + * The key is generated randomly. + * Its location, usage policy, type and size are taken from \p attributes. + * + * Implementations must reject an attempt to generate a key of size 0. + * + * The following type-specific considerations apply: + * - For RSA keys (#PSA_KEY_TYPE_RSA_KEY_PAIR), + * the public exponent is 65537. + * The modulus is a product of two probabilistic primes + * between 2^{n-1} and 2^n where n is the bit size specified in the + * attributes. + * + * \param[in] attributes The attributes for the new key. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. * * \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_ALREADY_EXISTS - * There is already a key in the specified slot. + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. * \retval #PSA_ERROR_NOT_SUPPORTED * \retval #PSA_ERROR_INVALID_ARGUMENT * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_STORAGE_FAILURE * \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_generate_key(psa_key_handle_t handle, - psa_key_type_t type, - size_t bits, - const void *extra, - size_t extra_size); +psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, + psa_key_handle_t *handle); /**@}*/ diff --git a/interface/include/psa/crypto_compat.h b/interface/include/psa/crypto_compat.h new file mode 100644 index 0000000000..86fea2d3b0 --- /dev/null +++ b/interface/include/psa/crypto_compat.h @@ -0,0 +1,93 @@ +/** + * \file psa/crypto_compat.h + * + * \brief PSA cryptography module: Backward compatibility aliases + * + * This header declares alternative names for macro and functions. + * New application code should not use these names. + * These names may be removed in a future version of Mbed Crypto. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + */ +/* + * Copyright (C) 2019-2020, 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_COMPAT_H +#define PSA_CRYPTO_COMPAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +/* + * Mechanism for declaring deprecated values + */ +#if defined(MBEDTLS_DEPRECATED_WARNING) && !defined(MBEDTLS_PSA_DEPRECATED) +#define MBEDTLS_PSA_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_PSA_DEPRECATED +#endif + +typedef MBEDTLS_PSA_DEPRECATED size_t mbedtls_deprecated_size_t; +typedef MBEDTLS_PSA_DEPRECATED psa_status_t mbedtls_deprecated_psa_status_t; +typedef MBEDTLS_PSA_DEPRECATED psa_key_usage_t mbedtls_deprecated_psa_key_usage_t; + +#define MBEDTLS_DEPRECATED_CONSTANT( type, value ) \ + ( (mbedtls_deprecated_##type) ( value ) ) + +/* + * Deprecated PSA Crypto error code definitions (PSA Crypto API <= 1.0 beta2) + */ +#define PSA_ERROR_UNKNOWN_ERROR \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_GENERIC_ERROR ) +#define PSA_ERROR_OCCUPIED_SLOT \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_ALREADY_EXISTS ) +#define PSA_ERROR_EMPTY_SLOT \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_DOES_NOT_EXIST ) +#define PSA_ERROR_INSUFFICIENT_CAPACITY \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_INSUFFICIENT_DATA ) +#define PSA_ERROR_TAMPERING_DETECTED \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_CORRUPTION_DETECTED ) + +/* + * Deprecated PSA Crypto numerical encodings (PSA Crypto API <= 1.0 beta3) + */ +#define PSA_KEY_USAGE_SIGN \ + MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_SIGN_HASH ) +#define PSA_KEY_USAGE_VERIFY \ + MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_VERIFY_HASH ) + +/* + * Deprecated PSA Crypto size calculation macros (PSA Crypto API <= 1.0 beta3) + */ +#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \ + MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGNATURE_MAX_SIZE ) +#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) \ + MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) ) + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_COMPAT_H */ diff --git a/interface/include/psa/crypto_extra.h b/interface/include/psa/crypto_extra.h index 3f08fa77b7..356362f707 100644 --- a/interface/include/psa/crypto_extra.h +++ b/interface/include/psa/crypto_extra.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -15,15 +15,11 @@ * This file is reserved for vendor-specific definitions. */ -/** - * \note This implementation currently doesn't provide support to any - * vendor-specific extension or definition, so this header file - * is empty. - */ - #ifndef PSA_CRYPTO_EXTRA_H #define PSA_CRYPTO_EXTRA_H +#include "psa/crypto_compat.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/interface/include/psa/crypto_platform.h b/interface/include/psa/crypto_platform.h index c5def6fb78..c3120e485b 100644 --- a/interface/include/psa/crypto_platform.h +++ b/interface/include/psa/crypto_platform.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -7,7 +7,7 @@ /** * \file psa/crypto_platform.h * - * \brief PSA cryptography module: platform definitions + * \brief PSA cryptography module: Mbed TLS platform definitions * * \note This file may not be included directly. Applications must * include psa/crypto.h. @@ -29,4 +29,23 @@ /* Integral type representing a key handle. */ typedef uint16_t psa_key_handle_t; +/* This implementation distinguishes *application key identifiers*, which + * are the key identifiers specified by the application, from + * *key file identifiers*, which are the key identifiers that the library + * sees internally. The two types can be different if there is a remote + * call layer between the application and the library which supports + * multiple client applications that do not have access to each others' + * keys. The point of having different types is that the key file + * identifier may encode not only the key identifier specified by the + * application, but also the the identity of the application. + * + * Note that this is an internal concept of the library and the remote + * call layer. The application itself never sees anything other than + * #psa_app_key_id_t with its standard definition. + */ + +/* The application key identifier is always what the application sees as + * #psa_key_id_t. */ +typedef uint32_t psa_app_key_id_t; + #endif /* PSA_CRYPTO_PLATFORM_H */ diff --git a/interface/include/psa/crypto_sizes.h b/interface/include/psa/crypto_sizes.h index 4c622394ab..4f67501b56 100644 --- a/interface/include/psa/crypto_sizes.h +++ b/interface/include/psa/crypto_sizes.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -7,7 +7,7 @@ /** * \file psa/crypto_sizes.h * - * \brief PSA cryptography module: buffer size macros + * \brief PSA cryptography module: Mbed TLS buffer size macros * * \note This file may not be included directly. Applications must * include psa/crypto.h. @@ -33,6 +33,9 @@ #define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8) #define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8) +#define PSA_ROUND_UP_TO_MULTIPLE(block_size, length) \ + (((length) + (block_size) - 1) / (block_size) * (block_size)) + /** The size of the output of psa_hash_finish(), in bytes. * * This is also the hash size that psa_hash_verify() expects. @@ -134,6 +137,47 @@ * This is a vendor-specific macro. */ #define PSA_VENDOR_ECC_MAX_CURVE_BITS 521 +/** Bit size associated with an elliptic curve. + * + * \param curve An elliptic curve (value of type #psa_ecc_curve_t). + * + * \return The size associated with \p curve, in bits. + * This may be 0 if the implementation does not support + * the specified curve. + */ +#define PSA_ECC_CURVE_BITS(curve) \ + ((curve) == PSA_ECC_CURVE_SECT163K1 ? 163 : \ + (curve) == PSA_ECC_CURVE_SECT163R1 ? 163 : \ + (curve) == PSA_ECC_CURVE_SECT163R2 ? 163 : \ + (curve) == PSA_ECC_CURVE_SECT193R1 ? 193 : \ + (curve) == PSA_ECC_CURVE_SECT193R2 ? 193 : \ + (curve) == PSA_ECC_CURVE_SECT233K1 ? 233 : \ + (curve) == PSA_ECC_CURVE_SECT233R1 ? 233 : \ + (curve) == PSA_ECC_CURVE_SECT239K1 ? 239 : \ + (curve) == PSA_ECC_CURVE_SECT283K1 ? 283 : \ + (curve) == PSA_ECC_CURVE_SECT283R1 ? 283 : \ + (curve) == PSA_ECC_CURVE_SECT409K1 ? 409 : \ + (curve) == PSA_ECC_CURVE_SECT409R1 ? 409 : \ + (curve) == PSA_ECC_CURVE_SECT571K1 ? 571 : \ + (curve) == PSA_ECC_CURVE_SECT571R1 ? 571 : \ + (curve) == PSA_ECC_CURVE_SECP160K1 ? 160 : \ + (curve) == PSA_ECC_CURVE_SECP160R1 ? 160 : \ + (curve) == PSA_ECC_CURVE_SECP160R2 ? 160 : \ + (curve) == PSA_ECC_CURVE_SECP192K1 ? 192 : \ + (curve) == PSA_ECC_CURVE_SECP192R1 ? 192 : \ + (curve) == PSA_ECC_CURVE_SECP224K1 ? 224 : \ + (curve) == PSA_ECC_CURVE_SECP224R1 ? 224 : \ + (curve) == PSA_ECC_CURVE_SECP256K1 ? 256 : \ + (curve) == PSA_ECC_CURVE_SECP256R1 ? 256 : \ + (curve) == PSA_ECC_CURVE_SECP384R1 ? 384 : \ + (curve) == PSA_ECC_CURVE_SECP521R1 ? 521 : \ + (curve) == PSA_ECC_CURVE_BRAINPOOL_P256R1 ? 256 : \ + (curve) == PSA_ECC_CURVE_BRAINPOOL_P384R1 ? 384 : \ + (curve) == PSA_ECC_CURVE_BRAINPOOL_P512R1 ? 512 : \ + (curve) == PSA_ECC_CURVE_CURVE25519 ? 255 : \ + (curve) == PSA_ECC_CURVE_CURVE448 ? 448 : \ + 0) + /** \def PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN * * This macro returns the maximum length of the PSK supported @@ -150,21 +194,6 @@ */ #define PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN 128 -/** \def PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE - * - * Maximum size of an asymmetric signature. - * - * This macro must expand to a compile-time constant integer. This value - * should be the maximum size of a MAC supported by the implementation, - * in bytes, and must be no smaller than this maximum. - */ -#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \ - PSA_BITS_TO_BYTES( \ - PSA_VENDOR_RSA_MAX_KEY_BITS > PSA_VENDOR_ECC_MAX_CURVE_BITS ? \ - PSA_VENDOR_RSA_MAX_KEY_BITS : \ - PSA_VENDOR_ECC_MAX_CURVE_BITS \ - ) - /** The maximum size of a block cipher supported by the implementation. */ #define PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE 16 @@ -175,7 +204,7 @@ * \param key_type The type of the MAC key. * \param key_bits The size of the MAC key in bits. * \param alg A MAC algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_MAC(alg) is true). + * #PSA_ALG_IS_MAC(\p alg) is true). * * \return The MAC size for the specified algorithm with * the specified key parameters. @@ -200,7 +229,7 @@ * * \param alg An AEAD algorithm * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(alg) is true). + * #PSA_ALG_IS_AEAD(\p alg) is true). * \param plaintext_length Size of the plaintext in bytes. * * \return The AEAD ciphertext size for the specified @@ -224,7 +253,7 @@ * * \param alg An AEAD algorithm * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(alg) is true). + * #PSA_ALG_IS_AEAD(\p alg) is true). * \param ciphertext_length Size of the plaintext in bytes. * * \return The AEAD ciphertext size for the specified @@ -236,7 +265,81 @@ */ #define PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length) \ (PSA_AEAD_TAG_LENGTH(alg) != 0 ? \ - (plaintext_length) - PSA_AEAD_TAG_LENGTH(alg) : \ + (ciphertext_length) - PSA_AEAD_TAG_LENGTH(alg) : \ + 0) + +/** A sufficient output buffer size for psa_aead_update(). + * + * If the size of the output buffer is at least this large, it is + * guaranteed that psa_aead_update() will not fail due to an + * insufficient buffer size. The actual size of the output may be smaller + * in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param input_length Size of the input in bytes. + * + * \return A sufficient output buffer size for the specified + * algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +/* For all the AEAD modes defined in this specification, it is possible + * to emit output without delay. However, hardware may not always be + * capable of this. So for modes based on a block cipher, allow the + * implementation to delay the output until it has a full block. */ +#define PSA_AEAD_UPDATE_OUTPUT_SIZE(alg, input_length) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_ROUND_UP_TO_MULTIPLE(PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE, (input_length)) : \ + (input_length)) + +/** A sufficient ciphertext buffer size for psa_aead_finish(). + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_aead_finish() will not fail due to an + * insufficient ciphertext buffer size. The actual size of the output may + * be smaller in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return A sufficient ciphertext buffer size for the + * specified algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_FINISH_OUTPUT_SIZE(alg) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ + 0) + +/** A sufficient plaintext buffer size for psa_aead_verify(). + * + * If the size of the plaintext buffer is at least this large, it is + * guaranteed that psa_aead_verify() will not fail due to an + * insufficient plaintext buffer size. The actual size of the output may + * be smaller in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return A sufficient plaintext buffer size for the + * specified algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_VERIFY_OUTPUT_SIZE(alg) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ 0) #define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ @@ -255,9 +358,9 @@ #define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ (PSA_BITS_TO_BYTES(curve_bits) * 2) -/** Safe signature buffer size for psa_asymmetric_sign(). +/** Sufficient signature buffer size for psa_sign_hash(). * - * This macro returns a safe buffer size for a signature using a key + * This macro returns a sufficient buffer size for a signature using a key * of the specified type and size, with the specified algorithm. * Note that the actual size of the signature may be smaller * (some algorithms produce a variable-size signature). @@ -273,22 +376,38 @@ * * \return If the parameters are valid and supported, return * a buffer size in bytes that guarantees that - * psa_asymmetric_sign() will not fail with + * psa_sign_hash() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not supported - * by the implementation, this macro either shall return either a + * by the implementation, this macro shall return either a * sensible size or 0. * If the parameters are not valid, the * return value is unspecified. */ -#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ +#define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \ ((void)alg, 0)) -/** Safe output buffer size for psa_asymmetric_encrypt(). +#define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE \ + PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) + +/** \def PSA_SIGNATURE_MAX_SIZE + * + * Maximum size of an asymmetric signature. + * + * This macro must expand to a compile-time constant integer. This value + * should be the maximum size of a signature supported by the implementation, + * in bytes, and must be no smaller than this maximum. + */ +#define PSA_SIGNATURE_MAX_SIZE \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE ? \ + PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ + PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE) + +/** Sufficient output buffer size for psa_asymmetric_encrypt(). * - * This macro returns a safe buffer size for a ciphertext produced using + * This macro returns a sufficient buffer size for a ciphertext produced using * a key of the specified type and size, with the specified algorithm. * Note that the actual size of the ciphertext may be smaller, depending * on the algorithm. @@ -307,7 +426,7 @@ * psa_asymmetric_encrypt() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not supported - * by the implementation, this macro either shall return either a + * by the implementation, this macro shall return either a * sensible size or 0. * If the parameters are not valid, the * return value is unspecified. @@ -317,9 +436,9 @@ ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ 0) -/** Safe output buffer size for psa_asymmetric_decrypt(). +/** Sufficient output buffer size for psa_asymmetric_decrypt(). * - * This macro returns a safe buffer size for a ciphertext produced using + * This macro returns a sufficient buffer size for a ciphertext produced using * a key of the specified type and size, with the specified algorithm. * Note that the actual size of the ciphertext may be smaller, depending * on the algorithm. @@ -338,7 +457,7 @@ * psa_asymmetric_decrypt() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not supported - * by the implementation, this macro either shall return either a + * by the implementation, this macro shall return either a * sensible size or 0. * If the parameters are not valid, the * return value is unspecified. @@ -397,7 +516,7 @@ * overapproximated as 9 half-size INTEGERS; * - 7 bytes for the public exponent. */ -#define PSA_KEY_EXPORT_RSA_KEYPAIR_MAX_SIZE(key_bits) \ +#define PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) \ (9 * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2 + 1) + 14) /* Maximum size of the export encoding of a DSA public key. @@ -435,7 +554,7 @@ * - 3 full-size INTEGERs (p, g, y); * - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits). */ -#define PSA_KEY_EXPORT_DSA_KEYPAIR_MAX_SIZE(key_bits) \ +#define PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) \ (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 75) /* Maximum size of the export encoding of an ECC public key. @@ -455,10 +574,10 @@ * * An ECC key pair is represented by the secret value. */ -#define PSA_KEY_EXPORT_ECC_KEYPAIR_MAX_SIZE(key_bits) \ +#define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) \ (PSA_BITS_TO_BYTES(key_bits)) -/** Safe output buffer size for psa_export_key() or psa_export_public_key(). +/** Sufficient output buffer size for psa_export_key() or psa_export_public_key(). * * This macro returns a compile-time constant if its arguments are * compile-time constants. @@ -470,32 +589,36 @@ * The following code illustrates how to allocate enough memory to export * a key by querying the key type and size at runtime. * \code{c} - * psa_key_type_t key_type; - * size_t key_bits; + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; * psa_status_t status; - * status = psa_get_key_information(key, &key_type, &key_bits); + * status = psa_get_key_attributes(key, &attributes); * if (status != PSA_SUCCESS) handle_error(...); + * psa_key_type_t key_type = psa_get_key_type(&attributes); + * size_t key_bits = psa_get_key_bits(&attributes); * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits); - * unsigned char *buffer = malloc(buffer_size); - * if (buffer != NULL) handle_error(...); + * psa_reset_key_attributes(&attributes); + * uint8_t *buffer = malloc(buffer_size); + * if (buffer == NULL) handle_error(...); * size_t buffer_length; * status = psa_export_key(key, buffer, buffer_size, &buffer_length); * if (status != PSA_SUCCESS) handle_error(...); * \endcode * * For psa_export_public_key(), calculate the buffer size from the - * public key type. You can use the macro #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR + * public key type. You can use the macro #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR * to convert a key pair type to the corresponding public key type. * \code{c} - * psa_key_type_t key_type; - * size_t key_bits; + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; * psa_status_t status; - * status = psa_get_key_information(key, &key_type, &key_bits); + * status = psa_get_key_attributes(key, &attributes); * if (status != PSA_SUCCESS) handle_error(...); - * psa_key_type_t public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(key_type); + * psa_key_type_t key_type = psa_get_key_type(&attributes); + * psa_key_type_t public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type); + * size_t key_bits = psa_get_key_bits(&attributes); * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(public_key_type, key_bits); - * unsigned char *buffer = malloc(buffer_size); - * if (buffer != NULL) handle_error(...); + * psa_reset_key_attributes(&attributes); + * uint8_t *buffer = malloc(buffer_size); + * if (buffer == NULL) handle_error(...); * size_t buffer_length; * status = psa_export_public_key(key, buffer, buffer_size, &buffer_length); * if (status != PSA_SUCCESS) handle_error(...); @@ -506,21 +629,21 @@ * * \return If the parameters are valid and supported, return * a buffer size in bytes that guarantees that - * psa_asymmetric_sign() will not fail with + * psa_sign_hash() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not supported - * by the implementation, this macro either shall return either a + * by the implementation, this macro shall return either a * sensible size or 0. * If the parameters are not valid, the * return value is unspecified. */ #define PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits) \ (PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ - (key_type) == PSA_KEY_TYPE_RSA_KEYPAIR ? PSA_KEY_EXPORT_RSA_KEYPAIR_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_RSA_KEY_PAIR ? PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) : \ (key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ - (key_type) == PSA_KEY_TYPE_DSA_KEYPAIR ? PSA_KEY_EXPORT_DSA_KEYPAIR_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_DSA_KEY_PAIR ? PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) : \ (key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ - PSA_KEY_TYPE_IS_ECC_KEYPAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEYPAIR_MAX_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) : \ PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ 0) diff --git a/interface/include/psa/crypto_struct.h b/interface/include/psa/crypto_struct.h index 12d1fc8d11..403a734000 100644 --- a/interface/include/psa/crypto_struct.h +++ b/interface/include/psa/crypto_struct.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -23,6 +23,27 @@ #ifndef PSA_CRYPTO_STRUCT_H #define PSA_CRYPTO_STRUCT_H +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Note that the below structures are different from the decalrations in + * mbed-crypto. This is because TF-M maintains 'front-end' and 'back-end' + * versions of this header. In the front-end version, exported to NS + * clients in interface/include/psa, a crypto operation is defined as an + * opaque handle to a context in the Crypto service. The back-end + * version, directly included from the mbed-crypto repo by the Crypto + * service, contains the full definition of the operation structs. + * + * One of the functions of the Crypto service is to allocate the back-end + * operation contexts in its own partition memory (in crypto_alloc.c), + * and then do the mapping between front-end operation handles passed by + * NS clients and the corresponding back-end operation contexts. The + * advantage of doing it this way is that internal mbed-crypto state is never + * exposed to the NS client. + */ + struct psa_hash_operation_s { uint32_t handle; @@ -59,15 +80,27 @@ static inline struct psa_cipher_operation_s psa_cipher_operation_init( void ) return( v ); } -struct psa_crypto_generator_s +struct psa_aead_operation_s +{ + uint32_t handle; +}; + +#define PSA_AEAD_OPERATION_INIT {0} +static inline struct psa_aead_operation_s psa_aead_operation_init( void ) +{ + const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT; + return( v ); +} + +struct psa_key_derivation_s { uint32_t handle; }; -#define PSA_CRYPTO_GENERATOR_INIT {0} -static inline struct psa_crypto_generator_s psa_crypto_generator_init( void ) +#define PSA_KEY_DERIVATION_OPERATION_INIT {0} +static inline struct psa_key_derivation_s psa_key_derivation_operation_init( void ) { - const struct psa_crypto_generator_s v = PSA_CRYPTO_GENERATOR_INIT; + const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT; return( v ); } @@ -77,6 +110,7 @@ struct psa_key_policy_s psa_algorithm_t alg; psa_algorithm_t alg2; }; +typedef struct psa_key_policy_s psa_key_policy_t; #define PSA_KEY_POLICY_INIT {0, 0, 0} static inline struct psa_key_policy_s psa_key_policy_init( void ) @@ -85,4 +119,183 @@ static inline struct psa_key_policy_s psa_key_policy_init( void ) return( v ); } +/* The type used internally for key sizes. + * Public interfaces use size_t, but internally we use a smaller type. */ +typedef uint16_t psa_key_bits_t; +/* The maximum value of the type used to represent bit-sizes. + * This is used to mark an invalid key size. */ +#define PSA_KEY_BITS_TOO_LARGE ( (psa_key_bits_t) ( -1 ) ) +/* The maximum size of a key in bits. + * Currently defined as the maximum that can be represented, rounded down + * to a whole number of bytes. + * This is an uncast value so that it can be used in preprocessor + * conditionals. */ +#define PSA_MAX_KEY_BITS 0xfff8 + +/** A mask of flags that can be stored in key attributes. + * + * This type is also used internally to store flags in slots. Internal + * flags are defined in library/psa_crypto_core.h. Internal flags may have + * the same value as external flags if they are properly handled during + * key creation and in psa_get_key_attributes. + */ +typedef uint16_t psa_key_attributes_flag_t; + +#define MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER \ + ( (psa_key_attributes_flag_t) 0x0001 ) + +/* A mask of key attribute flags used externally only. + * Only meant for internal checks inside the library. */ +#define MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY ( \ + MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER | \ + 0 ) + +/* A mask of key attribute flags used both internally and externally. + * Currently there aren't any. */ +#define MBEDTLS_PSA_KA_MASK_DUAL_USE ( \ + 0 ) + +typedef struct +{ + psa_key_type_t type; + psa_key_lifetime_t lifetime; + psa_key_id_t id; + psa_key_policy_t policy; + psa_key_bits_t bits; + psa_key_attributes_flag_t flags; +} psa_core_key_attributes_t; + +#define PSA_CORE_KEY_ATTRIBUTES_INIT {0, 0, PSA_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0, 0} + +struct psa_key_attributes_s +{ + psa_core_key_attributes_t core; +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + psa_key_slot_number_t slot_number; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + void *domain_parameters; + size_t domain_parameters_size; +}; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0} +#else +#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0} +#endif + +static inline struct psa_key_attributes_s psa_key_attributes_init( void ) +{ + const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT; + return( v ); +} + +static inline void psa_set_key_id(psa_key_attributes_t *attributes, + psa_key_id_t id) +{ + attributes->core.id = id; + if( attributes->core.lifetime == PSA_KEY_LIFETIME_VOLATILE ) + attributes->core.lifetime = PSA_KEY_LIFETIME_PERSISTENT; +} + +static inline psa_key_id_t psa_get_key_id( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.id ); +} + +static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime) +{ + attributes->core.lifetime = lifetime; + if( lifetime == PSA_KEY_LIFETIME_VOLATILE ) + { +#ifdef MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER + attributes->core.id.key_id = 0; + attributes->core.id.owner = 0; +#else + attributes->core.id = 0; +#endif + } +} + +static inline psa_key_lifetime_t psa_get_key_lifetime( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.lifetime ); +} + +static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes, + psa_key_usage_t usage_flags) +{ + attributes->core.policy.usage = usage_flags; +} + +static inline psa_key_usage_t psa_get_key_usage_flags( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.policy.usage ); +} + +static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes, + psa_algorithm_t alg) +{ + attributes->core.policy.alg = alg; +} + +static inline psa_algorithm_t psa_get_key_algorithm( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.policy.alg ); +} + +/* This function is declared in crypto_extra.h, which comes after this + * header file, but we need the function here, so repeat the declaration. */ +psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length); + +static inline void psa_set_key_type(psa_key_attributes_t *attributes, + psa_key_type_t type) +{ + if( attributes->domain_parameters == NULL ) + { + /* Common case: quick path */ + attributes->core.type = type; + } + else + { + /* Call the bigger function to free the old domain paramteres. + * Ignore any errors which may arise due to type requiring + * non-default domain parameters, since this function can't + * report errors. */ + (void) psa_set_key_domain_parameters( attributes, type, NULL, 0 ); + } +} + +static inline psa_key_type_t psa_get_key_type( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.type ); +} + +static inline void psa_set_key_bits(psa_key_attributes_t *attributes, + size_t bits) +{ + if( bits > PSA_MAX_KEY_BITS ) + attributes->core.bits = PSA_KEY_BITS_TOO_LARGE; + else + attributes->core.bits = (psa_key_bits_t) bits; +} + +static inline size_t psa_get_key_bits( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.bits ); +} + +#ifdef __cplusplus +} +#endif + #endif /* PSA_CRYPTO_STRUCT_H */ diff --git a/interface/include/psa/crypto_types.h b/interface/include/psa/crypto_types.h index bf5b82471d..690999f79c 100644 --- a/interface/include/psa/crypto_types.h +++ b/interface/include/psa/crypto_types.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -33,9 +33,9 @@ * \brief Function return status. * * This is either #PSA_SUCCESS (which is zero), indicating success, - * or a nonzero value indicating that an error occurred. Errors are - * encoded as one of the \c PSA_ERROR_xxx values defined here. - * If #PSA_SUCCESS is already defined, it means that #psa_status_t + * or a small negative value indicating that an error occurred. Errors are + * encoded as one of the \c PSA_ERROR_xxx values defined here. */ +/* If #PSA_SUCCESS is already defined, it means that #psa_status_t * is also defined in an external header, so prevent its multiple * definition. */ @@ -53,9 +53,84 @@ typedef int32_t psa_status_t; */ typedef uint32_t psa_key_type_t; -/** The type of PSA elliptic curve identifiers. */ +/** The type of PSA elliptic curve identifiers. + * + * The curve identifier is required to create an ECC key using the + * PSA_KEY_TYPE_ECC_KEY_PAIR() or PSA_KEY_TYPE_ECC_PUBLIC_KEY() + * macros. + * + * The encoding of curve identifiers is taken from the + * TLS Supported Groups Registry (formerly known as the + * TLS EC Named Curve Registry) + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * + * This specification defines identifiers for some of the curves in the IANA + * registry. Implementations that support other curves that are in the IANA + * registry should use the IANA value and a implementation-specific identifier. + * Implemenations that support non-IANA curves should use one of the following + * approaches for allocating a key type: + * + * 1. Select a ::psa_ecc_curve_t value in the range #PSA_ECC_CURVE_VENDOR_MIN to + * #PSA_ECC_CURVE_VENDOR_MAX, which is a subset of the IANA private use + * range. + * 2. Use a ::psa_key_type_t value that is vendor-defined. + * + * The first option is recommended. + */ typedef uint16_t psa_ecc_curve_t; +/** The type of PSA Diffie-Hellman group identifiers. + * + * The group identifier is required to create an Diffie-Hellman key using the + * PSA_KEY_TYPE_DH_KEY_PAIR() or PSA_KEY_TYPE_DH_PUBLIC_KEY() + * macros. + * + * The encoding of group identifiers is taken from the + * TLS Supported Groups Registry (formerly known as the + * TLS EC Named Curve Registry) + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * + * This specification defines identifiers for some of the groups in the IANA + * registry. Implementations that support other groups that are in the IANA + * registry should use the IANA value and a implementation-specific identifier. + * Implemenations that support non-IANA groups should use one of the following + * approaches for allocating a key type: + * + * 1. Select a ::psa_dh_group_t value in the range #PSA_DH_GROUP_VENDOR_MIN to + * #PSA_DH_GROUP_VENDOR_MAX, which is a subset of the IANA private use + * range. + * 2. Select a ::psa_dh_group_t value from the named groups allocated for + * GREASE in the IETF draft specification. The GREASE specification and + * values are listed below. + * 3. Use a ::psa_key_type_t value that is vendor-defined. + * + * Option 1 or 2 are recommended. + * + * The current draft of the GREASE specification is + * https://datatracker.ietf.org/doc/draft-ietf-tls-grease + * + * The following GREASE values are allocated for named groups: + * \code + * 0x0A0A + * 0x1A1A + * 0x2A2A + * 0x3A3A + * 0x4A4A + * 0x5A5A + * 0x6A6A + * 0x7A7A + * 0x8A8A + * 0x9A9A + * 0xAAAA + * 0xBABA + * 0xCACA + * 0xDADA + * 0xEAEA + * 0xFAFA + * \endcode + */ +typedef uint16_t psa_dh_group_t; + /** \brief Encoding of a cryptographic algorithm. * * For algorithms that can be applied to multiple key types, this type @@ -73,12 +148,33 @@ typedef uint32_t psa_algorithm_t; */ /** Encoding of key lifetimes. + * + * The lifetime of a key indicates where it is stored and what system actions + * may create and destroy it. + * + * Keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE are automatically + * destroyed when the application terminates or on a power reset. + * + * Keys with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE are said + * to be _persistent_. + * Persistent keys are preserved if the application or the system restarts. + * Persistent keys have a key identifier of type #psa_key_id_t. + * The application can call psa_open_key() to open a persistent key that + * it created previously. */ typedef uint32_t psa_key_lifetime_t; /** Encoding of identifiers of persistent keys. + * + * - Applications may freely choose key identifiers in the range + * #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX. + * - Implementations may define additional key identifiers in the range + * #PSA_KEY_ID_VENDOR_MIN to #PSA_KEY_ID_VENDOR_MAX. + * - 0 is reserved as an invalid key identifier. + * - Key identifiers outside these ranges are reserved for future use. */ typedef uint32_t psa_key_id_t; +#define PSA_KEY_ID_INIT 0 /**@}*/ @@ -91,4 +187,127 @@ typedef uint32_t psa_key_usage_t; /**@}*/ +/** \defgroup attributes Key attributes + * @{ + */ + +/** The type of a structure containing key attributes. + * + * This is an opaque structure that can represent the metadata of a key + * object. Metadata that can be stored in attributes includes: + * - The location of the key in storage, indicated by its key identifier + * and its lifetime. + * - The key's policy, comprising usage flags and a specification of + * the permitted algorithm(s). + * - Information about the key itself: the key type and its size. + * - Implementations may define additional attributes. + * + * The actual key material is not considered an attribute of a key. + * Key attributes do not contain information that is generally considered + * highly confidential. + * + * An attribute structure can be a simple data structure where each function + * `psa_set_key_xxx` sets a field and the corresponding function + * `psa_get_key_xxx` retrieves the value of the corresponding field. + * However, implementations may report values that are equivalent to the + * original one, but have a different encoding. For example, an + * implementation may use a more compact representation for types where + * many bit-patterns are invalid or not supported, and store all values + * that it does not support as a special marker value. In such an + * implementation, after setting an invalid value, the corresponding + * get function returns an invalid value which may not be the one that + * was originally stored. + * + * An attribute structure may contain references to auxiliary resources, + * for example pointers to allocated memory or indirect references to + * pre-calculated values. In order to free such resources, the application + * must call psa_reset_key_attributes(). As an exception, calling + * psa_reset_key_attributes() on an attribute structure is optional if + * the structure has only been modified by the following functions + * since it was initialized or last reset with psa_reset_key_attributes(): + * - psa_set_key_id() + * - psa_set_key_lifetime() + * - psa_set_key_type() + * - psa_set_key_bits() + * - psa_set_key_usage_flags() + * - psa_set_key_algorithm() + * + * Before calling any function on a key attribute structure, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_attributes_t attributes; + * memset(&attributes, 0, sizeof(attributes)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_attributes_t attributes = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_ATTRIBUTES_INIT, + * for example: + * \code + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * \endcode + * - Assign the result of the function psa_key_attributes_init() + * to the structure, for example: + * \code + * psa_key_attributes_t attributes; + * attributes = psa_key_attributes_init(); + * \endcode + * + * A freshly initialized attribute structure contains the following + * values: + * + * - lifetime: #PSA_KEY_LIFETIME_VOLATILE. + * - key identifier: 0 (which is not a valid key identifier). + * - type: \c 0 (meaning that the type is unspecified). + * - key size: \c 0 (meaning that the size is unspecified). + * - usage flags: \c 0 (which allows no usage except exporting a public key). + * - algorithm: \c 0 (which allows no cryptographic usage, but allows + * exporting). + * + * A typical sequence to create a key is as follows: + * -# Create and initialize an attribute structure. + * -# If the key is persistent, call psa_set_key_id(). + * Also call psa_set_key_lifetime() to place the key in a non-default + * location. + * -# Set the key policy with psa_set_key_usage_flags() and + * psa_set_key_algorithm(). + * -# Set the key type with psa_set_key_type(). + * Skip this step if copying an existing key with psa_copy_key(). + * -# When generating a random key with psa_generate_key() or deriving a key + * with psa_key_derivation_output_key(), set the desired key size with + * psa_set_key_bits(). + * -# Call a key creation function: psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). This function reads + * the attribute structure, creates a key with these attributes, and + * outputs a handle to the newly created key. + * -# The attribute structure is now no longer necessary. + * You may call psa_reset_key_attributes(), although this is optional + * with the workflow presented here because the attributes currently + * defined in this specification do not require any additional resources + * beyond the structure itself. + * + * A typical sequence to query a key's attributes is as follows: + * -# Call psa_get_key_attributes(). + * -# Call `psa_get_key_xxx` functions to retrieve the attribute(s) that + * you are interested in. + * -# Call psa_reset_key_attributes() to free any resources that may be + * used by the attribute structure. + * + * Once a key has been created, it is impossible to change its attributes. + */ +typedef struct psa_key_attributes_s psa_key_attributes_t; + +/**@}*/ + +/** \defgroup derivation Key derivation + * @{ + */ + +/** \brief Encoding of the step of a key derivation. */ +typedef uint16_t psa_key_derivation_step_t; + +/**@}*/ + #endif /* PSA_CRYPTO_TYPES_H */ diff --git a/interface/include/psa/crypto_values.h b/interface/include/psa/crypto_values.h index 315cd107d0..7fde07385f 100644 --- a/interface/include/psa/crypto_values.h +++ b/interface/include/psa/crypto_values.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -95,9 +95,13 @@ * descriptions for permitted sequencing of functions. * * 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_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST - * as applicable. */ + * that a key either exists or not, + * but shall instead return #PSA_ERROR_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST + * as applicable. + * + * Implementations 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_BAD_STATE ((psa_status_t)-137) /** The parameters passed to the function are invalid. @@ -105,12 +109,7 @@ * Implementations may return this error any time a parameter or * combination of parameters are recognized as invalid. * - * 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_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST - * as applicable. - * - * Implementation shall not return this error code to indicate that a + * Implementations shall not return this error code to indicate that a * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE * instead. */ @@ -140,7 +139,7 @@ * * \warning If a function returns this error, it is undetermined * whether the requested action has completed or not. Implementations - * should return #PSA_SUCCESS on successful completion whenver + * should return #PSA_SUCCESS on successful completion whenever * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE * if the requested action was completed successfully in an external * cryptoprocessor but there was a breakdown of communication before @@ -152,7 +151,7 @@ * * This error indicates that some persistent storage is corrupted. * It should not be used for a corruption of volatile memory - * (use #PSA_ERROR_TAMPERING_DETECTED), for a communication error + * (use #PSA_ERROR_CORRUPTION_DETECTED), for a communication error * between the cryptoprocessor and its external storage (use * #PSA_ERROR_COMMUNICATION_FAILURE), or when the storage is * in a valid state but is full (use #PSA_ERROR_INSUFFICIENT_STORAGE). @@ -165,7 +164,7 @@ * the global integrity of the keystore. Depending on the global * integrity guarantees offered by the implementation, access to other * data may or may not fail even if the data is still readable but - * its integrity canont be guaranteed. + * its integrity cannot be guaranteed. * * Implementations should only use this error code to report a * permanent storage corruption. However application writers should @@ -208,7 +207,7 @@ * This error indicates an attack against the application. Implementations * shall not return this error code as a consequence of the behavior of * the application itself. */ -#define PSA_ERROR_TAMPERING_DETECTED ((psa_status_t)-151) +#define PSA_ERROR_CORRUPTION_DETECTED ((psa_status_t)-151) /** There is not enough entropy to generate random data needed * for the requested action. @@ -259,7 +258,7 @@ * to read from a resource. */ #define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) -/** The key handle is not valid. +/** The key handle is not valid. See also :ref:\`key-handles\`. */ #define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) @@ -275,7 +274,7 @@ */ #define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x00000000) -/** Vendor-defined flag +/** Vendor-defined key type flag. * * Key types defined by this standard will never have the * #PSA_KEY_TYPE_VENDOR_FLAG bit set. Vendors who define additional key types @@ -292,7 +291,10 @@ #define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t)0x10000000) -/** Whether a key type is vendor-defined. */ +/** Whether a key type is vendor-defined. + * + * See also #PSA_KEY_TYPE_VENDOR_FLAG. + */ #define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \ (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0) @@ -314,7 +316,7 @@ (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) /** Whether a key type is a key pair containing a private part and a public * part. */ -#define PSA_KEY_TYPE_IS_KEYPAIR(type) \ +#define PSA_KEY_TYPE_IS_KEY_PAIR(type) \ (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_KEY_PAIR) /** The key pair type corresponding to a public key type. * @@ -326,7 +328,7 @@ * If \p type is not a public key or a key pair, * the return value is undefined. */ -#define PSA_KEY_TYPE_KEYPAIR_OF_PUBLIC_KEY(type) \ +#define PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type) \ ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) /** The public key type corresponding to a key pair type. * @@ -338,7 +340,7 @@ * If \p type is not a public key or a key pair, * the return value is undefined. */ -#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) \ +#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) \ ((type) & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) /** Raw data. @@ -364,7 +366,7 @@ */ #define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x52000000) -/** Key for an cipher, AEAD or MAC algorithm based on the AES block cipher. +/** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher. * * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or * 32 bytes (AES-256). @@ -382,7 +384,7 @@ */ #define PSA_KEY_TYPE_DES ((psa_key_type_t)0x40000002) -/** Key for an cipher, AEAD or MAC algorithm based on the +/** Key for a cipher, AEAD or MAC algorithm based on the * Camellia block cipher. */ #define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x40000003) @@ -392,40 +394,49 @@ * legacy protocols. */ #define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x40000004) +/** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm. + * + * ChaCha20 and the ChaCha20_Poly1305 construction are defined in RFC 7539. + * + * Implementations must support 12-byte nonces, may support 8-byte nonces, + * and should reject other sizes. + */ +#define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t)0x40000005) + /** RSA public key. */ #define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x60010000) /** RSA key pair (private and public key). */ -#define PSA_KEY_TYPE_RSA_KEYPAIR ((psa_key_type_t)0x70010000) +#define PSA_KEY_TYPE_RSA_KEY_PAIR ((psa_key_type_t)0x70010000) /** Whether a key type is an RSA key (pair or public-only). */ #define PSA_KEY_TYPE_IS_RSA(type) \ - (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) - -/** DSA public key. */ -#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x60020000) -/** DSA key pair (private and public key). */ -#define PSA_KEY_TYPE_DSA_KEYPAIR ((psa_key_type_t)0x70020000) -/** Whether a key type is an DSA key (pair or public-only). */ -#define PSA_KEY_TYPE_IS_DSA(type) \ - (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY) + (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) #define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x60030000) -#define PSA_KEY_TYPE_ECC_KEYPAIR_BASE ((psa_key_type_t)0x70030000) +#define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE ((psa_key_type_t)0x70030000) #define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x0000ffff) -/** Elliptic curve key pair. */ -#define PSA_KEY_TYPE_ECC_KEYPAIR(curve) \ - (PSA_KEY_TYPE_ECC_KEYPAIR_BASE | (curve)) -/** Elliptic curve public key. */ +/** Elliptic curve key pair. + * + * \param curve A value of type ::psa_ecc_curve_t that identifies the + * ECC curve to be used. + */ +#define PSA_KEY_TYPE_ECC_KEY_PAIR(curve) \ + (PSA_KEY_TYPE_ECC_KEY_PAIR_BASE | (curve)) +/** Elliptic curve public key. + * + * \param curve A value of type ::psa_ecc_curve_t that identifies the + * ECC curve to be used. + */ #define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve) \ (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve)) /** Whether a key type is an elliptic curve key (pair or public-only). */ #define PSA_KEY_TYPE_IS_ECC(type) \ - ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) & \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) /** Whether a key type is an elliptic curve key pair. */ -#define PSA_KEY_TYPE_IS_ECC_KEYPAIR(type) \ +#define PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type) \ (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ - PSA_KEY_TYPE_ECC_KEYPAIR_BASE) + PSA_KEY_TYPE_ECC_KEY_PAIR_BASE) /** Whether a key type is an elliptic curve public key. */ #define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type) \ (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ @@ -470,9 +481,95 @@ #define PSA_ECC_CURVE_BRAINPOOL_P256R1 ((psa_ecc_curve_t) 0x001a) #define PSA_ECC_CURVE_BRAINPOOL_P384R1 ((psa_ecc_curve_t) 0x001b) #define PSA_ECC_CURVE_BRAINPOOL_P512R1 ((psa_ecc_curve_t) 0x001c) +/** Curve25519. + * + * This is the curve defined in Bernstein et al., + * _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006. + * The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve. + */ #define PSA_ECC_CURVE_CURVE25519 ((psa_ecc_curve_t) 0x001d) +/** Curve448 + * + * This is the curve defined in Hamburg, + * _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. + * The algorithm #PSA_ALG_ECDH performs X448 when used with this curve. + */ #define PSA_ECC_CURVE_CURVE448 ((psa_ecc_curve_t) 0x001e) +/** Minimum value for a vendor-defined ECC curve identifier + * + * The range for vendor-defined curve identifiers is a subset of the IANA + * registry private use range, `0xfe00` - `0xfeff`. + */ +#define PSA_ECC_CURVE_VENDOR_MIN ((psa_ecc_curve_t) 0xfe00) +/** Maximum value for a vendor-defined ECC curve identifier + * + * The range for vendor-defined curve identifiers is a subset of the IANA + * registry private use range, `0xfe00` - `0xfeff`. + */ +#define PSA_ECC_CURVE_VENDOR_MAX ((psa_ecc_curve_t) 0xfe7f) + +#define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t)0x60040000) +#define PSA_KEY_TYPE_DH_KEY_PAIR_BASE ((psa_key_type_t)0x70040000) +#define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t)0x0000ffff) +/** Diffie-Hellman key pair. + * + * \param group A value of type ::psa_dh_group_t that identifies the + * Diffie-Hellman group to be used. + */ +#define PSA_KEY_TYPE_DH_KEY_PAIR(group) \ + (PSA_KEY_TYPE_DH_KEY_PAIR_BASE | (group)) +/** Diffie-Hellman public key. + * + * \param group A value of type ::psa_dh_group_t that identifies the + * Diffie-Hellman group to be used. + */ +#define PSA_KEY_TYPE_DH_PUBLIC_KEY(group) \ + (PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE | (group)) + +/** Whether a key type is a Diffie-Hellman key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_DH(type) \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ + ~PSA_KEY_TYPE_DH_GROUP_MASK) == PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) +/** Whether a key type is a Diffie-Hellman key pair. */ +#define PSA_KEY_TYPE_IS_DH_KEY_PAIR(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_KEY_PAIR_BASE) +/** Whether a key type is a Diffie-Hellman public key. */ +#define PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) + +/** Extract the group from a Diffie-Hellman key type. */ +#define PSA_KEY_TYPE_GET_GROUP(type) \ + ((psa_dh_group_t) (PSA_KEY_TYPE_IS_DH(type) ? \ + ((type) & PSA_KEY_TYPE_DH_GROUP_MASK) : \ + 0)) + +/* The encoding of group identifiers is currently aligned with the + * TLS Supported Groups Registry (formerly known as the + * TLS EC Named Curve Registry) + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * The values are defined by RFC 7919. */ +#define PSA_DH_GROUP_FFDHE2048 ((psa_dh_group_t) 0x0100) +#define PSA_DH_GROUP_FFDHE3072 ((psa_dh_group_t) 0x0101) +#define PSA_DH_GROUP_FFDHE4096 ((psa_dh_group_t) 0x0102) +#define PSA_DH_GROUP_FFDHE6144 ((psa_dh_group_t) 0x0103) +#define PSA_DH_GROUP_FFDHE8192 ((psa_dh_group_t) 0x0104) + +/** Minimum value for a vendor-defined Diffie Hellman group identifier + * + * The range for vendor-defined group identifiers is a subset of the IANA + * registry private use range, `0x01fc` - `0x01ff`. + */ +#define PSA_DH_GROUP_VENDOR_MIN ((psa_dh_group_t) 0x01fc) +/** Maximum value for a vendor-defined Diffie Hellman group identifier + * + * The range for vendor-defined group identifiers is a subset of the IANA + * registry private use range, `0x01fc` - `0x01ff`. + */ +#define PSA_DH_GROUP_VENDOR_MAX ((psa_dh_group_t) 0x01fd) + /** The block size of a block cipher. * * \param type A cipher key type (value of type #psa_key_type_t). @@ -497,9 +594,18 @@ (type) == PSA_KEY_TYPE_DES ? 8 : \ (type) == PSA_KEY_TYPE_CAMELLIA ? 16 : \ (type) == PSA_KEY_TYPE_ARC4 ? 1 : \ + (type) == PSA_KEY_TYPE_CHACHA20 ? 1 : \ 0) +/** Vendor-defined algorithm flag. + * + * Algorithms defined by this standard will never have the #PSA_ALG_VENDOR_FLAG + * bit set. Vendors who define additional algorithms must use an encoding with + * the #PSA_ALG_VENDOR_FLAG bit set and should respect the bitwise structure + * used by standard encodings whenever practical. + */ #define PSA_ALG_VENDOR_FLAG ((psa_algorithm_t)0x80000000) + #define PSA_ALG_CATEGORY_MASK ((psa_algorithm_t)0x7f000000) #define PSA_ALG_CATEGORY_HASH ((psa_algorithm_t)0x01000000) #define PSA_ALG_CATEGORY_MAC ((psa_algorithm_t)0x02000000) @@ -507,10 +613,13 @@ #define PSA_ALG_CATEGORY_AEAD ((psa_algorithm_t)0x06000000) #define PSA_ALG_CATEGORY_SIGN ((psa_algorithm_t)0x10000000) #define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x12000000) -#define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x22000000) -#define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x30000000) -#define PSA_ALG_CATEGORY_KEY_SELECTION ((psa_algorithm_t)0x31000000) +#define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x20000000) +#define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x30000000) +/** Whether an algorithm is vendor-defined. + * + * See also #PSA_ALG_VENDOR_FLAG. + */ #define PSA_ALG_IS_VENDOR_DEFINED(alg) \ (((alg) & PSA_ALG_VENDOR_FLAG) != 0) @@ -581,7 +690,6 @@ #define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION) -#define PSA_ALG_KEY_SELECTION_FLAG ((psa_algorithm_t)0x01000000) /** Whether the specified algorithm is a key agreement algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). @@ -591,8 +699,7 @@ * algorithm identifier. */ #define PSA_ALG_IS_KEY_AGREEMENT(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK & ~PSA_ALG_KEY_SELECTION_FLAG) == \ - PSA_ALG_CATEGORY_KEY_AGREEMENT) + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT) /** Whether the specified algorithm is a key derivation algorithm. * @@ -605,23 +712,16 @@ #define PSA_ALG_IS_KEY_DERIVATION(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) -/** Whether the specified algorithm is a key selection algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a key selection algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_KEY_SELECTION(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_SELECTION) - #define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) - +/** MD2 */ #define PSA_ALG_MD2 ((psa_algorithm_t)0x01000001) +/** MD4 */ #define PSA_ALG_MD4 ((psa_algorithm_t)0x01000002) +/** MD5 */ #define PSA_ALG_MD5 ((psa_algorithm_t)0x01000003) +/** PSA_ALG_RIPEMD160 */ #define PSA_ALG_RIPEMD160 ((psa_algorithm_t)0x01000004) +/** SHA1 */ #define PSA_ALG_SHA_1 ((psa_algorithm_t)0x01000005) /** SHA2-224 */ #define PSA_ALG_SHA_224 ((psa_algorithm_t)0x01000008) @@ -653,29 +753,26 @@ * * That is, suppose that `PSA_xxx_SIGNATURE` is one of the following macros: * - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS, - * - #PSA_ALG_DSA, #PSA_ALG_DETERMINISTIC_DSA, * - #PSA_ALG_ECDSA, #PSA_ALG_DETERMINISTIC_ECDSA. * Then you may create and use a key as follows: * - Set the key usage field using #PSA_ALG_ANY_HASH, for example: * ``` - * psa_key_policy_set_usage(&policy, - * PSA_KEY_USAGE_SIGN, //or PSA_KEY_USAGE_VERIFY - * PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH)); - * psa_set_key_policy(handle, &policy); + * psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); // or VERIFY + * psa_set_key_algorithm(&attributes, PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH)); * ``` * - Import or generate key material. - * - Call psa_asymmetric_sign() or psa_asymmetric_verify(), passing + * - Call psa_sign_hash() or psa_verify_hash(), passing * an algorithm built from `PSA_xxx_SIGNATURE` and a specific hash. Each * call to sign or verify a message may use a different hash. * ``` - * psa_asymmetric_sign(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...); - * psa_asymmetric_sign(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...); - * psa_asymmetric_sign(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...); + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...); + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...); + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...); * ``` * * This value may not be used to build other algorithms that are * parametrized over a hash. For any valid use of this macro to build - * an algorithm `\p alg`, #PSA_ALG_IS_HASH_AND_SIGN(\p alg) is true. + * an algorithm \c alg, #PSA_ALG_IS_HASH_AND_SIGN(\c alg) is true. * * This value may not be used to build an algorithm specification to * perform an operation. It is only valid to build policies. @@ -692,7 +789,7 @@ * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding HMAC algorithm. - * \return Unspecified if \p alg is not a supported + * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_HMAC(hash_alg) \ @@ -792,9 +889,14 @@ (((mac_alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET) #define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t)0x02c00000) +/** The CBC-MAC construction over a block cipher + * + * \warning CBC-MAC is insecure in many cases. + * A more secure mode, such as #PSA_ALG_CMAC, is recommended. + */ #define PSA_ALG_CBC_MAC ((psa_algorithm_t)0x02c00001) +/** The CMAC construction over a block cipher */ #define PSA_ALG_CMAC ((psa_algorithm_t)0x02c00002) -#define PSA_ALG_GMAC ((psa_algorithm_t)0x02c00003) /** Whether the specified algorithm is a MAC algorithm based on a block cipher. * @@ -831,6 +933,18 @@ */ #define PSA_ALG_ARC4 ((psa_algorithm_t)0x04800001) +/** The ChaCha20 stream cipher. + * + * ChaCha20 is defined in RFC 7539. + * + * The nonce size for psa_cipher_set_iv() or psa_cipher_generate_iv() + * must be 12. + * + * The initial block counter is always 0. + * + */ +#define PSA_ALG_CHACHA20 ((psa_algorithm_t)0x04800005) + /** The CTR stream cipher mode. * * CTR is a stream cipher which is built from a block cipher. @@ -840,8 +954,16 @@ */ #define PSA_ALG_CTR ((psa_algorithm_t)0x04c00001) +/** The CFB stream cipher mode. + * + * The underlying block cipher is determined by the key type. + */ #define PSA_ALG_CFB ((psa_algorithm_t)0x04c00002) +/** The OFB stream cipher mode. + * + * The underlying block cipher is determined by the key type. + */ #define PSA_ALG_OFB ((psa_algorithm_t)0x04c00003) /** The XTS cipher mode. @@ -869,8 +991,43 @@ */ #define PSA_ALG_CBC_PKCS7 ((psa_algorithm_t)0x04600101) -#define PSA_ALG_CCM ((psa_algorithm_t)0x06001001) -#define PSA_ALG_GCM ((psa_algorithm_t)0x06001002) +#define PSA_ALG_AEAD_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) + +/** Whether the specified algorithm is an AEAD mode on a block cipher. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an AEAD algorithm which is an AEAD mode based on + * a block cipher, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) == \ + (PSA_ALG_CATEGORY_AEAD | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) + +/** The CCM authenticated encryption algorithm. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_CCM ((psa_algorithm_t)0x06401001) + +/** The GCM authenticated encryption algorithm. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_GCM ((psa_algorithm_t)0x06401002) + +/** The Chacha20-Poly1305 AEAD algorithm. + * + * The ChaCha20_Poly1305 construction is defined in RFC 7539. + * + * Implementations must support 12-byte nonces, may support 8-byte nonces, + * and should reject other sizes. + * + * Implementations must support 16-byte tags and should reject other sizes. + */ +#define PSA_ALG_CHACHA20_POLY1305 ((psa_algorithm_t)0x06001005) /* In the encoding of a AEAD algorithm, the bits corresponding to * PSA_ALG_AEAD_TAG_LENGTH_MASK encode the length of the AEAD tag. @@ -910,14 +1067,15 @@ * \return The corresponding AEAD algorithm with the default * tag length for that algorithm. */ -#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(aead_alg) \ - ( \ - PSA__ALG_AEAD_WITH_DEFAULT_TAG_LENGTH__CASE(aead_alg, PSA_ALG_CCM) \ - PSA__ALG_AEAD_WITH_DEFAULT_TAG_LENGTH__CASE(aead_alg, PSA_ALG_GCM) \ +#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(aead_alg) \ + ( \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CCM) \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_GCM) \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CHACHA20_POLY1305) \ 0) -#define PSA__ALG_AEAD_WITH_DEFAULT_TAG_LENGTH__CASE(aead_alg, ref) \ - PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, 0) == \ - PSA_ALG_AEAD_WITH_TAG_LENGTH(ref, 0) ? \ +#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, ref) \ + PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, 0) == \ + PSA_ALG_AEAD_WITH_TAG_LENGTH(ref, 0) ? \ ref : #define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t)0x10020000) @@ -933,7 +1091,7 @@ * when specifying the algorithm in a usage policy. * * \return The corresponding RSA PKCS#1 v1.5 signature algorithm. - * \return Unspecified if \p alg is not a supported + * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg) \ @@ -964,7 +1122,7 @@ * when specifying the algorithm in a usage policy. * * \return The corresponding RSA PSS signature algorithm. - * \return Unspecified if \p alg is not a supported + * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_RSA_PSS(hash_alg) \ @@ -972,37 +1130,6 @@ #define PSA_ALG_IS_RSA_PSS(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE) -#define PSA_ALG_DSA_BASE ((psa_algorithm_t)0x10040000) -/** DSA signature with hashing. - * - * This is the signature scheme defined by FIPS 186-4, - * with a random per-message secret number (*k*). - * - * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_HASH(\p hash_alg) is true). - * This includes #PSA_ALG_ANY_HASH - * when specifying the algorithm in a usage policy. - * - * \return The corresponding DSA signature algorithm. - * \return Unspecified if \p alg is not a supported - * hash algorithm. - */ -#define PSA_ALG_DSA(hash_alg) \ - (PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_DETERMINISTIC_DSA_BASE ((psa_algorithm_t)0x10050000) -#define PSA_ALG_DSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000) -#define PSA_ALG_DETERMINISTIC_DSA(hash_alg) \ - (PSA_ALG_DETERMINISTIC_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_IS_DSA(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \ - PSA_ALG_DSA_BASE) -#define PSA_ALG_DSA_IS_DETERMINISTIC(alg) \ - (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0) -#define PSA_ALG_IS_DETERMINISTIC_DSA(alg) \ - (PSA_ALG_IS_DSA(alg) && PSA_ALG_DSA_IS_DETERMINISTIC(alg)) -#define PSA_ALG_IS_RANDOMIZED_DSA(alg) \ - (PSA_ALG_IS_DSA(alg) && !PSA_ALG_DSA_IS_DETERMINISTIC(alg)) - #define PSA_ALG_ECDSA_BASE ((psa_algorithm_t)0x10060000) /** ECDSA signature with hashing. * @@ -1021,7 +1148,7 @@ * when specifying the algorithm in a usage policy. * * \return The corresponding ECDSA signature algorithm. - * \return Unspecified if \p alg is not a supported + * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_ECDSA(hash_alg) \ @@ -1056,16 +1183,17 @@ * * \return The corresponding deterministic ECDSA signature * algorithm. - * \return Unspecified if \p alg is not a supported + * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \ (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_ECDSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000) #define PSA_ALG_IS_ECDSA(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \ + (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_ECDSA_DETERMINISTIC_FLAG) == \ PSA_ALG_ECDSA_BASE) #define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \ - (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0) + (((alg) & PSA_ALG_ECDSA_DETERMINISTIC_FLAG) != 0) #define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \ (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) #define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \ @@ -1086,7 +1214,7 @@ */ #define PSA_ALG_IS_HASH_AND_SIGN(alg) \ (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ - PSA_ALG_IS_DSA(alg) || PSA_ALG_IS_ECDSA(alg)) + PSA_ALG_IS_ECDSA(alg)) /** Get the hash used by a hash-and-sign signature algorithm. * @@ -1128,7 +1256,7 @@ * for MGF1. * * \return The corresponding RSA OAEP signature algorithm. - * \return Unspecified if \p alg is not a supported + * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_RSA_OAEP(hash_alg) \ @@ -1140,16 +1268,25 @@ ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ 0) -#define PSA_ALG_HKDF_BASE ((psa_algorithm_t)0x30000100) +#define PSA_ALG_HKDF_BASE ((psa_algorithm_t)0x20000100) /** Macro to build an HKDF algorithm. * * For example, `PSA_ALG_HKDF(PSA_ALG_SHA256)` is HKDF using HMAC-SHA-256. * + * This key derivation algorithm uses the following inputs: + * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt used in the "extract" step. + * It is optional; if omitted, the derivation uses an empty salt. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key used in the "extract" step. + * - #PSA_KEY_DERIVATION_INPUT_INFO is the info string used in the "expand" step. + * You must pass #PSA_KEY_DERIVATION_INPUT_SALT before #PSA_KEY_DERIVATION_INPUT_SECRET. + * You may pass #PSA_KEY_DERIVATION_INPUT_INFO at any time after steup and before + * starting to generate output. + * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding HKDF algorithm. - * \return Unspecified if \p alg is not a supported + * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_HKDF(hash_alg) \ @@ -1170,18 +1307,22 @@ #define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \ (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_TLS12_PRF_BASE ((psa_algorithm_t)0x30000200) +#define PSA_ALG_TLS12_PRF_BASE ((psa_algorithm_t)0x20000200) /** Macro to build a TLS-1.2 PRF algorithm. * * TLS 1.2 uses a custom pseudorandom function (PRF) for key schedule, * specified in Section 5 of RFC 5246. It is based on HMAC and can be * used with either SHA-256 or SHA-384. * - * For the application to TLS-1.2, the salt and label arguments passed - * to psa_key_derivation() are what's called 'seed' and 'label' in RFC 5246, - * respectively. For example, for TLS key expansion, the salt is the + * This key derivation algorithm uses the following inputs, which must be + * passed in the order given here: + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * + * For the application to TLS-1.2 key expansion, the seed is the * concatenation of ServerHello.Random + ClientHello.Random, - * while the label is "key expansion". + * and the label is "key expansion". * * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA256)` represents the * TLS 1.2 PRF using HMAC-SHA-256. @@ -1190,7 +1331,7 @@ * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding TLS-1.2 PRF algorithm. - * \return Unspecified if \p alg is not a supported + * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_TLS12_PRF(hash_alg) \ @@ -1209,7 +1350,7 @@ #define PSA_ALG_TLS12_PRF_GET_HASH(hkdf_alg) \ (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_TLS12_PSK_TO_MS_BASE ((psa_algorithm_t)0x30000300) +#define PSA_ALG_TLS12_PSK_TO_MS_BASE ((psa_algorithm_t)0x20000300) /** Macro to build a TLS-1.2 PSK-to-MasterSecret algorithm. * * In a pure-PSK handshake in TLS 1.2, the master secret is derived @@ -1218,10 +1359,16 @@ * The latter is based on HMAC and can be used with either SHA-256 * or SHA-384. * - * For the application to TLS-1.2, the salt passed to psa_key_derivation() - * (and forwarded to the TLS-1.2 PRF) is the concatenation of the - * ClientHello.Random + ServerHello.Random, while the label is "master secret" - * or "extended master secret". + * This key derivation algorithm uses the following inputs, which must be + * passed in the order given here: + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * + * For the application to TLS-1.2, the seed (which is + * forwarded to the TLS-1.2 PRF) is the concatenation of the + * ClientHello.Random + ServerHello.Random, + * and the label is "master secret" or "extended master secret". * * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA256)` represents the * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256. @@ -1230,7 +1377,7 @@ * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding TLS-1.2 PSK to MS algorithm. - * \return Unspecified if \p alg is not a supported + * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_TLS12_PSK_TO_MS(hash_alg) \ @@ -1249,55 +1396,67 @@ #define PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(hkdf_alg) \ (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) -#define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t)0x010fffff) +#define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t)0x0803ffff) +#define PSA_ALG_KEY_AGREEMENT_MASK ((psa_algorithm_t)0x10fc0000) -/** Use a shared secret as is. +/** Macro to build a combined algorithm that chains a key agreement with + * a key derivation. * - * Specify this algorithm as the selection component of a key agreement - * to use the raw result of the key agreement as key material. + * \param ka_alg A key agreement algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_AGREEMENT(\p ka_alg) is true). + * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_DERIVATION(\p kdf_alg) is true). * - * \warning The raw result of a key agreement algorithm such as finite-field - * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should - * not be used directly as key material. It can however be used as the secret - * input in a key derivation algorithm. + * \return The corresponding key agreement and derivation + * algorithm. + * \return Unspecified if \p ka_alg is not a supported + * key agreement algorithm or \p kdf_alg is not a + * supported key derivation algorithm. */ -#define PSA_ALG_SELECT_RAW ((psa_algorithm_t)0x31000001) +#define PSA_ALG_KEY_AGREEMENT(ka_alg, kdf_alg) \ + ((ka_alg) | (kdf_alg)) #define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) \ (((alg) & PSA_ALG_KEY_DERIVATION_MASK) | PSA_ALG_CATEGORY_KEY_DERIVATION) -#define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ - ((alg) & ~PSA_ALG_KEY_DERIVATION_MASK) +#define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ + (((alg) & PSA_ALG_KEY_AGREEMENT_MASK) | PSA_ALG_CATEGORY_KEY_AGREEMENT) -#define PSA_ALG_FFDH_BASE ((psa_algorithm_t)0x22100000) -/** The Diffie-Hellman key agreement algorithm. +/** Whether the specified algorithm is a raw key agreement algorithm. + * + * A raw key agreement algorithm is one that does not specify + * a key derivation function. + * Usually, raw key agreement algorithms are constructed directly with + * a \c PSA_ALG_xxx macro while non-raw key agreement algorithms are + * constructed with PSA_ALG_KEY_AGREEMENT(). + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). * - * This algorithm combines the finite-field Diffie-Hellman (DH) key - * agreement, also known as Diffie-Hellman-Merkle (DHM) key agreement, - * to produce a shared secret from a private key and the peer's - * public key, with a key selection or key derivation algorithm to produce - * one or more shared keys and other shared cryptographic material. + * \return 1 if \p alg is a raw key agreement algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) \ + (PSA_ALG_IS_KEY_AGREEMENT(alg) && \ + PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) == PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_IS_KEY_DERIVATION_OR_AGREEMENT(alg) \ + ((PSA_ALG_IS_KEY_DERIVATION(alg) || PSA_ALG_IS_KEY_AGREEMENT(alg))) + +/** The finite-field Diffie-Hellman (DH) key agreement algorithm. * - * The shared secret produced by key agreement and passed as input to the - * derivation or selection algorithm \p kdf_alg is the shared secret + * The shared secret produced by key agreement is * `g^{ab}` in big-endian format. * It is `ceiling(m / 8)` bytes long where `m` is the size of the prime `p` * in bits. - * - * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such - * that #PSA_ALG_IS_KEY_DERIVATION(\p hash_alg) is true) - * or a key selection algorithm (\c PSA_ALG_XXX value such - * that #PSA_ALG_IS_KEY_SELECTION(\p hash_alg) is true). - * - * \return The Diffie-Hellman algorithm with the specified - * selection or derivation algorithm. */ -#define PSA_ALG_FFDH(kdf_alg) \ - (PSA_ALG_FFDH_BASE | ((kdf_alg) & PSA_ALG_KEY_DERIVATION_MASK)) +#define PSA_ALG_FFDH ((psa_algorithm_t)0x30100000) + /** Whether the specified algorithm is a finite field Diffie-Hellman algorithm. * - * This includes every supported key selection or key agreement algorithm - * for the output of the Diffie-Hellman calculation. + * This includes the raw finite field Diffie-Hellman algorithm as well as + * finite-field Diffie-Hellman followed by any supporter key derivation + * algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * @@ -1306,18 +1465,11 @@ * key agreement algorithm identifier. */ #define PSA_ALG_IS_FFDH(alg) \ - (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_FFDH_BASE) + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_FFDH) -#define PSA_ALG_ECDH_BASE ((psa_algorithm_t)0x22200000) /** The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. * - * This algorithm combines the elliptic curve Diffie-Hellman key - * agreement to produce a shared secret from a private key and the peer's - * public key, with a key selection or key derivation algorithm to produce - * one or more shared keys and other shared cryptographic material. - * - * The shared secret produced by key agreement and passed as input to the - * derivation or selection algorithm \p kdf_alg is the x-coordinate of + * The shared secret produced by key agreement is the x-coordinate of * the shared secret point. It is always `ceiling(m / 8)` bytes long where * `m` is the bit size associated with the curve, i.e. the bit size of the * order of the curve's coordinate field. When `m` is not a multiple of 8, @@ -1339,22 +1491,15 @@ * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` * in big-endian byte order. * The bit size is `m` for the field `F_{2^m}`. - * - * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such - * that #PSA_ALG_IS_KEY_DERIVATION(\p hash_alg) is true) - * or a selection algorithm (\c PSA_ALG_XXX value such - * that #PSA_ALG_IS_KEY_SELECTION(\p hash_alg) is true). - * - * \return The Diffie-Hellman algorithm with the specified - * selection or derivation algorithm. */ -#define PSA_ALG_ECDH(kdf_alg) \ - (PSA_ALG_ECDH_BASE | ((kdf_alg) & PSA_ALG_KEY_DERIVATION_MASK)) +#define PSA_ALG_ECDH ((psa_algorithm_t)0x30200000) + /** Whether the specified algorithm is an elliptic curve Diffie-Hellman * algorithm. * - * This includes every supported key selection or key agreement algorithm - * for the output of the Diffie-Hellman calculation. + * This includes the raw elliptic curve Diffie-Hellman algorithm as well as + * elliptic curve Diffie-Hellman followed by any supporter key derivation + * algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * @@ -1364,7 +1509,7 @@ * key agreement algorithm identifier. */ #define PSA_ALG_IS_ECDH(alg) \ - (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH_BASE) + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH) /** Whether the specified algorithm encoding is a wildcard. * @@ -1409,6 +1554,19 @@ */ #define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001) +/** The minimum value for a key identifier chosen by the application. + */ +#define PSA_KEY_ID_USER_MIN ((psa_app_key_id_t)0x00000001) +/** The maximum value for a key identifier chosen by the application. + */ +#define PSA_KEY_ID_USER_MAX ((psa_app_key_id_t)0x3fffffff) +/** The minimum value for a key identifier chosen by the implementation. + */ +#define PSA_KEY_ID_VENDOR_MIN ((psa_app_key_id_t)0x40000000) +/** The maximum value for a key identifier chosen by the implementation. + */ +#define PSA_KEY_ID_VENDOR_MAX ((psa_app_key_id_t)0x7fffffff) + /**@}*/ /** \defgroup policy Key policies @@ -1428,6 +1586,22 @@ */ #define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t)0x00000001) +/** Whether the key may be copied. + * + * This flag allows the use of psa_copy_key() to make a copy of the key + * with the same policy or a more restrictive policy. + * + * For lifetimes for which the key is located in a secure element which + * enforce the non-exportability of keys, copying a key outside the secure + * element also requires the usage flag #PSA_KEY_USAGE_EXPORT. + * Copying the key inside the secure element is permitted with just + * #PSA_KEY_USAGE_COPY if the secure element supports it. + * For keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE or + * #PSA_KEY_LIFETIME_PERSISTENT, the usage flag #PSA_KEY_USAGE_COPY + * is sufficient to permit the copy. + */ +#define PSA_KEY_USAGE_COPY ((psa_key_usage_t)0x00000002) + /** Whether the key may be used to encrypt a message. * * This flag allows the key to be used for a symmetric encryption operation, @@ -1458,7 +1632,7 @@ * * For a key pair, this concerns the private key. */ -#define PSA_KEY_USAGE_SIGN ((psa_key_usage_t)0x00000400) +#define PSA_KEY_USAGE_SIGN_HASH ((psa_key_usage_t)0x00000400) /** Whether the key may be used to verify a message signature. * @@ -1468,7 +1642,7 @@ * * For a key pair, this concerns the public key. */ -#define PSA_KEY_USAGE_VERIFY ((psa_key_usage_t)0x00000800) +#define PSA_KEY_USAGE_VERIFY_HASH ((psa_key_usage_t)0x00000800) /** Whether the key may be used to derive other keys. */ @@ -1476,4 +1650,52 @@ /**@}*/ +/** \defgroup derivation Key derivation + * @{ + */ + +/** A secret input for key derivation. + * + * This should be a key of type #PSA_KEY_TYPE_DERIVE + * (passed to psa_key_derivation_input_key()) + * or the shared secret resulting from a key agreement + * (obtained via psa_key_derivation_key_agreement()). + * + * The secret can also be a direct input (passed to + * key_derivation_input_bytes()). In this case, the derivation operation + * may not be used to derive keys: the operation will only allow + * psa_key_derivation_output_bytes(), not psa_key_derivation_output_key(). + */ +#define PSA_KEY_DERIVATION_INPUT_SECRET ((psa_key_derivation_step_t)0x0101) + +/** A label for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_LABEL ((psa_key_derivation_step_t)0x0201) + +/** A salt for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_SALT ((psa_key_derivation_step_t)0x0202) + +/** An information string for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_INFO ((psa_key_derivation_step_t)0x0203) + +/** A seed for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_SEED ((psa_key_derivation_step_t)0x0204) + +/**@}*/ + #endif /* PSA_CRYPTO_VALUES_H */ diff --git a/interface/include/tfm_crypto_defs.h b/interface/include/tfm_crypto_defs.h index 5a380c6449..53c03ce022 100644 --- a/interface/include/tfm_crypto_defs.h +++ b/interface/include/tfm_crypto_defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -37,15 +37,13 @@ struct tfm_crypto_pack_iovec { uint32_t sfn_id; /*!< Secure function ID used to dispatch the * request */ + uint16_t step; /*!< Key derivation step */ psa_key_handle_t key_handle; /*!< Key handle */ - psa_key_type_t type; /*!< Key type */ - psa_key_usage_t usage; /*!< Usage policy for a key */ psa_algorithm_t alg; /*!< Algorithm */ - psa_key_lifetime_t lifetime; /*!< Lifetime policy for a key */ uint32_t op_handle; /*!< Frontend context handle associated to a * multipart operation */ - size_t capacity; /*!< Generator capacity */ + size_t capacity; /*!< Key derivation capacity */ struct tfm_crypto_aead_pack_input aead_in; /*!< FixMe: Temporarily used for * AEAD until the API is @@ -58,51 +56,70 @@ struct tfm_crypto_pack_iovec { * when dispatching the requests to the service */ enum { - TFM_CRYPTO_ALLOCATE_KEY_SID = (0u), + TFM_CRYPTO_GET_KEY_ATTRIBUTES_SID = (0u), + TFM_CRYPTO_RESET_KEY_ATTRIBUTES_SID, TFM_CRYPTO_OPEN_KEY_SID, TFM_CRYPTO_CLOSE_KEY_SID, TFM_CRYPTO_IMPORT_KEY_SID, TFM_CRYPTO_DESTROY_KEY_SID, - TFM_CRYPTO_GET_KEY_INFORMATION_SID, TFM_CRYPTO_EXPORT_KEY_SID, TFM_CRYPTO_EXPORT_PUBLIC_KEY_SID, TFM_CRYPTO_COPY_KEY_SID, - TFM_CRYPTO_SET_KEY_POLICY_SID, - TFM_CRYPTO_GET_KEY_POLICY_SID, - TFM_CRYPTO_GET_KEY_LIFETIME_SID, - TFM_CRYPTO_CIPHER_GENERATE_IV_SID, - TFM_CRYPTO_CIPHER_SET_IV_SID, - TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID, - TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID, - TFM_CRYPTO_CIPHER_UPDATE_SID, - TFM_CRYPTO_CIPHER_ABORT_SID, - TFM_CRYPTO_CIPHER_FINISH_SID, + TFM_CRYPTO_HASH_COMPUTE_SID, + TFM_CRYPTO_HASH_COMPARE_SID, TFM_CRYPTO_HASH_SETUP_SID, TFM_CRYPTO_HASH_UPDATE_SID, TFM_CRYPTO_HASH_FINISH_SID, TFM_CRYPTO_HASH_VERIFY_SID, TFM_CRYPTO_HASH_ABORT_SID, TFM_CRYPTO_HASH_CLONE_SID, + TFM_CRYPTO_MAC_COMPUTE_SID, + TFM_CRYPTO_MAC_VERIFY_SID, TFM_CRYPTO_MAC_SIGN_SETUP_SID, TFM_CRYPTO_MAC_VERIFY_SETUP_SID, TFM_CRYPTO_MAC_UPDATE_SID, TFM_CRYPTO_MAC_SIGN_FINISH_SID, TFM_CRYPTO_MAC_VERIFY_FINISH_SID, TFM_CRYPTO_MAC_ABORT_SID, + TFM_CRYPTO_CIPHER_ENCRYPT_SID, + TFM_CRYPTO_CIPHER_DECRYPT_SID, + TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID, + TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID, + TFM_CRYPTO_CIPHER_GENERATE_IV_SID, + TFM_CRYPTO_CIPHER_SET_IV_SID, + TFM_CRYPTO_CIPHER_UPDATE_SID, + TFM_CRYPTO_CIPHER_FINISH_SID, + TFM_CRYPTO_CIPHER_ABORT_SID, TFM_CRYPTO_AEAD_ENCRYPT_SID, TFM_CRYPTO_AEAD_DECRYPT_SID, - TFM_CRYPTO_ASYMMETRIC_SIGN_SID, - TFM_CRYPTO_ASYMMETRIC_VERIFY_SID, + TFM_CRYPTO_AEAD_ENCRYPT_SETUP_SID, + TFM_CRYPTO_AEAD_DECRYPT_SETUP_SID, + TFM_CRYPTO_AEAD_GENERATE_NONCE_SID, + TFM_CRYPTO_AEAD_SET_NONCE_SID, + TFM_CRYPTO_AEAD_SET_LENGTHS_SID, + TFM_CRYPTO_AEAD_UPDATE_AD_SID, + TFM_CRYPTO_AEAD_UPDATE_SID, + TFM_CRYPTO_AEAD_FINISH_SID, + TFM_CRYPTO_AEAD_VERIFY_SID, + TFM_CRYPTO_AEAD_ABORT_SID, + TFM_CRYPTO_SIGN_HASH_SID, + TFM_CRYPTO_VERIFY_HASH_SID, TFM_CRYPTO_ASYMMETRIC_ENCRYPT_SID, TFM_CRYPTO_ASYMMETRIC_DECRYPT_SID, - TFM_CRYPTO_GET_GENERATOR_CAPACITY_SID, - TFM_CRYPTO_GENERATOR_READ_SID, - TFM_CRYPTO_GENERATOR_IMPORT_KEY_SID, - TFM_CRYPTO_GENERATOR_ABORT_SID, - TFM_CRYPTO_KEY_DERIVATION_SID, - TFM_CRYPTO_KEY_AGREEMENT_SID, + TFM_CRYPTO_KEY_DERIVATION_SETUP_SID, + TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID, + TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID, + TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID, + TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID, + TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID, + TFM_CRYPTO_KEY_DERIVATION_ABORT_SID, + TFM_CRYPTO_RAW_KEY_AGREEMENT_SID, TFM_CRYPTO_GENERATE_RANDOM_SID, TFM_CRYPTO_GENERATE_KEY_SID, + TFM_CRYPTO_SET_KEY_DOMAIN_PARAMETERS_SID, + TFM_CRYPTO_GET_KEY_DOMAIN_PARAMETERS_SID, TFM_CRYPTO_SID_MAX, }; diff --git a/interface/include/tfm_veneers.h b/interface/include/tfm_veneers.h index f4f182c690..5f9c5b62c5 100644 --- a/interface/include/tfm_veneers.h +++ b/interface/include/tfm_veneers.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -44,49 +44,66 @@ psa_status_t tfm_audit_core_delete_record_veneer(psa_invec *in_vec, size_t in_le #ifdef TFM_PARTITION_CRYPTO /******** TFM_SP_CRYPTO ********/ -psa_status_t tfm_tfm_crypto_allocate_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_get_key_attributes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_open_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_close_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_reset_key_attributes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_import_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_destroy_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_get_key_information_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_export_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_export_public_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_copy_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_set_key_policy_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_get_key_policy_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_get_key_lifetime_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_generate_iv_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_set_iv_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_encrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_decrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_cipher_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_compute_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_compare_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_hash_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_hash_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_hash_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_hash_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_hash_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_hash_clone_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_compute_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_mac_sign_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_mac_verify_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_mac_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_mac_sign_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_mac_verify_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_mac_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_encrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_decrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_generate_iv_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_set_iv_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_aead_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_aead_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_asymmetric_sign_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_asymmetric_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_encrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_decrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_generate_nonce_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_set_nonce_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_set_lengths_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_update_ad_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_sign_hash_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_verify_hash_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_asymmetric_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_asymmetric_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_get_generator_capacity_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_generator_read_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_generator_import_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_generator_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_derivation_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); -psa_status_t tfm_tfm_crypto_key_agreement_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_get_capacity_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_set_capacity_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_input_bytes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_input_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_key_agreement_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_output_bytes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_output_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_raw_key_agreement_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_generate_random_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); psa_status_t tfm_tfm_crypto_generate_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); #endif /* TFM_PARTITION_CRYPTO */ diff --git a/interface/include/tfm_veneers.h.template b/interface/include/tfm_veneers.h.template index 3613b01ab4..83012f7ae3 100644 --- a/interface/include/tfm_veneers.h.template +++ b/interface/include/tfm_veneers.h.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * diff --git a/interface/src/tfm_crypto_func_api.c b/interface/src/tfm_crypto_func_api.c index 87c1a64631..c1b1d9060d 100644 --- a/interface/src/tfm_crypto_func_api.c +++ b/interface/src/tfm_crypto_func_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -30,32 +30,11 @@ psa_status_t psa_crypto_init(void) return PSA_SUCCESS; } -psa_status_t psa_allocate_key(psa_key_handle_t *handle) -{ - psa_status_t status; - const struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_ALLOCATE_KEY_SID, - }; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = handle, .len = sizeof(psa_key_handle_t)}, - }; - - status = API_DISPATCH(tfm_crypto_allocate_key, - TFM_CRYPTO_ALLOCATE_KEY); - - return status; -} - -psa_status_t psa_open_key(psa_key_lifetime_t lifetime, - psa_key_id_t id, +psa_status_t psa_open_key(psa_key_id_t id, psa_key_handle_t *handle) { const struct tfm_crypto_pack_iovec iov = { .sfn_id = TFM_CRYPTO_OPEN_KEY_SID, - .lifetime = lifetime, }; psa_invec in_vec[] = { {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, @@ -69,18 +48,6 @@ psa_status_t psa_open_key(psa_key_lifetime_t lifetime, TFM_CRYPTO_OPEN_KEY); } -psa_status_t psa_create_key(psa_key_lifetime_t lifetime, - psa_key_id_t id, - psa_key_handle_t *handle) -{ - (void)lifetime; - (void)id; - (void)handle; - - /* TODO: Persistent key APIs are not supported yet */ - return PSA_ERROR_NOT_SUPPORTED; -} - psa_status_t psa_close_key(psa_key_handle_t handle) { const struct tfm_crypto_pack_iovec iov = { @@ -95,24 +62,26 @@ psa_status_t psa_close_key(psa_key_handle_t handle) TFM_CRYPTO_CLOSE_KEY); } -psa_status_t psa_import_key(psa_key_handle_t handle, - psa_key_type_t type, +psa_status_t psa_import_key(const psa_key_attributes_t *attributes, const uint8_t *data, - size_t data_length) + size_t data_length, + psa_key_handle_t *handle) { psa_status_t status; struct tfm_crypto_pack_iovec iov = { .sfn_id = TFM_CRYPTO_IMPORT_KEY_SID, - .key_handle = handle, - .type = type, }; psa_invec in_vec[] = { {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, {.base = data, .len = data_length} }; + psa_outvec out_vec[] = { + {.base = handle, .len = sizeof(psa_key_handle_t)} + }; - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_import_key, - TFM_CRYPTO_IMPORT_KEY); + status = API_DISPATCH(tfm_crypto_import_key, + TFM_CRYPTO_IMPORT_KEY); return status; } @@ -134,29 +103,43 @@ psa_status_t psa_destroy_key(psa_key_handle_t handle) return status; } -psa_status_t psa_get_key_information(psa_key_handle_t handle, - psa_key_type_t *type, - size_t *bits) +psa_status_t psa_get_key_attributes(psa_key_handle_t handle, + psa_key_attributes_t *attributes) { psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GET_KEY_INFORMATION_SID, + .sfn_id = TFM_CRYPTO_GET_KEY_ATTRIBUTES_SID, .key_handle = handle, }; psa_invec in_vec[] = { {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, }; psa_outvec out_vec[] = { - {.base = type, .len = sizeof(psa_key_type_t)}, - {.base = bits, .len = sizeof(size_t)} + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, }; - status = API_DISPATCH(tfm_crypto_get_key_information, - TFM_CRYPTO_GET_KEY_INFORMATION); - + status = API_DISPATCH(tfm_crypto_get_key_attributes, + TFM_CRYPTO_GET_KEY_ATTRIBUTES); return status; } +void psa_reset_key_attributes(psa_key_attributes_t *attributes) +{ + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_RESET_KEY_ATTRIBUTES_SID, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + }; + + (void)API_DISPATCH(tfm_crypto_reset_key_attributes, + TFM_CRYPTO_RESET_KEY_ATTRIBUTES); + return; +} + psa_status_t psa_export_key(psa_key_handle_t handle, uint8_t *data, size_t data_size, @@ -179,7 +162,6 @@ psa_status_t psa_export_key(psa_key_handle_t handle, *data_length = out_vec[0].len; - return status; } @@ -210,8 +192,8 @@ psa_status_t psa_export_public_key(psa_key_handle_t handle, } psa_status_t psa_copy_key(psa_key_handle_t source_handle, - psa_key_handle_t target_handle, - const psa_key_policy_t *constraint) + const psa_key_attributes_t *attributes, + psa_key_handle_t *target_handle) { psa_status_t status; struct tfm_crypto_pack_iovec iov = { @@ -221,94 +203,15 @@ psa_status_t psa_copy_key(psa_key_handle_t source_handle, psa_invec in_vec[] = { {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = &target_handle, .len = sizeof(psa_key_handle_t)}, - {.base = constraint, .len = sizeof(psa_key_policy_t)}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, }; - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_copy_key, - TFM_CRYPTO_COPY_KEY); - - return status; -} - -void psa_key_policy_set_usage(psa_key_policy_t *policy, - psa_key_usage_t usage, - psa_algorithm_t alg) -{ - policy->usage = usage; - policy->alg = alg; -} - -psa_key_usage_t psa_key_policy_get_usage(const psa_key_policy_t *policy) -{ - return policy->usage; -} - -psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy) -{ - return policy->alg; -} - -psa_status_t psa_set_key_policy(psa_key_handle_t handle, - const psa_key_policy_t *policy) -{ - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_SET_KEY_POLICY_SID, - .key_handle = handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = policy, .len = sizeof(psa_key_policy_t)}, - }; - - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_set_key_policy, - TFM_CRYPTO_SET_KEY_POLICY); - - return status; -} - -psa_status_t psa_get_key_policy(psa_key_handle_t handle, - psa_key_policy_t *policy) -{ - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GET_KEY_POLICY_SID, - .key_handle = handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; psa_outvec out_vec[] = { - {.base = policy, .len = sizeof(psa_key_policy_t)}, + {.base = target_handle, .len = sizeof(psa_key_handle_t)}, }; - status = API_DISPATCH(tfm_crypto_get_key_policy, - TFM_CRYPTO_GET_KEY_POLICY); - - return status; -} - -psa_status_t psa_get_key_lifetime(psa_key_handle_t handle, - psa_key_lifetime_t *lifetime) -{ - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GET_KEY_LIFETIME_SID, - .key_handle = handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = lifetime, .len = sizeof(psa_key_lifetime_t)}, - }; - - status = API_DISPATCH(tfm_crypto_get_key_lifetime, - TFM_CRYPTO_GET_KEY_LIFETIME); + status = API_DISPATCH(tfm_crypto_copy_key, + TFM_CRYPTO_COPY_KEY); return status; } @@ -627,6 +530,10 @@ psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, {.base = target_operation, .len = sizeof(psa_hash_operation_t)}, }; + if (target_operation && (target_operation->handle != 0)) { + return PSA_ERROR_BAD_STATE; + } + status = API_DISPATCH(tfm_crypto_hash_clone, TFM_CRYPTO_HASH_CLONE); @@ -893,9 +800,21 @@ psa_status_t psa_asymmetric_sign(psa_key_handle_t handle, size_t signature_size, size_t *signature_length) { + return psa_sign_hash(handle, alg, hash, hash_length, signature, + signature_size, signature_length); +} + +psa_status_t psa_sign_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length) +{ psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_ASYMMETRIC_SIGN_SID, + .sfn_id = TFM_CRYPTO_SIGN_HASH_SID, .key_handle = handle, .alg = alg, }; @@ -908,8 +827,8 @@ psa_status_t psa_asymmetric_sign(psa_key_handle_t handle, {.base = signature, .len = signature_size}, }; - status = API_DISPATCH(tfm_crypto_asymmetric_sign, - TFM_CRYPTO_ASYMMETRIC_SIGN); + status = API_DISPATCH(tfm_crypto_sign_hash, + TFM_CRYPTO_SIGN_HASH); *signature_length = out_vec[0].len; @@ -923,9 +842,20 @@ psa_status_t psa_asymmetric_verify(psa_key_handle_t handle, const uint8_t *signature, size_t signature_length) { + return psa_verify_hash(handle, alg, hash, hash_length, + signature, signature_length); +} + +psa_status_t psa_verify_hash(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) +{ psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_ASYMMETRIC_VERIFY_SID, + .sfn_id = TFM_CRYPTO_VERIFY_HASH_SID, .key_handle = handle, .alg = alg }; @@ -936,8 +866,8 @@ psa_status_t psa_asymmetric_verify(psa_key_handle_t handle, {.base = signature, .len = signature_length} }; - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_asymmetric_verify, - TFM_CRYPTO_ASYMMETRIC_VERIFY); + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_verify_hash, + TFM_CRYPTO_VERIFY_HASH); return status; } @@ -1022,13 +952,14 @@ psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle, return status; } -psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator, - size_t *capacity) +psa_status_t psa_key_derivation_get_capacity( + const psa_key_derivation_operation_t *operation, + size_t *capacity) { psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GET_GENERATOR_CAPACITY_SID, - .op_handle = generator->handle, + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID, + .op_handle = operation->handle, }; psa_invec in_vec[] = { @@ -1039,20 +970,21 @@ psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator, {.base = capacity, .len = sizeof(size_t)}, }; - status = API_DISPATCH(tfm_crypto_get_generator_capacity, - TFM_CRYPTO_GET_GENERATOR_CAPACITY); + status = API_DISPATCH(tfm_crypto_key_derivation_get_capacity, + TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY); return status; } -psa_status_t psa_generator_read(psa_crypto_generator_t *generator, - uint8_t *output, - size_t output_length) +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, + size_t output_length) { psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GENERATOR_READ_SID, - .op_handle = generator->handle, + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID, + .op_handle = operation->handle, }; psa_invec in_vec[] = { @@ -1063,42 +995,41 @@ psa_status_t psa_generator_read(psa_crypto_generator_t *generator, {.base = output, .len = output_length}, }; - status = API_DISPATCH(tfm_crypto_generator_read, - TFM_CRYPTO_GENERATOR_READ); + status = API_DISPATCH(tfm_crypto_key_derivation_output_bytes, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES); return status; } -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) +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t handle) { psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GENERATOR_IMPORT_KEY_SID, + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID, .key_handle = handle, - .type = type, - .op_handle = generator->handle, + .step = step, + .op_handle = operation->handle, }; psa_invec in_vec[] = { {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = &bits, .len = sizeof(size_t)}, }; - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_generator_import_key, - TFM_CRYPTO_GENERATOR_IMPORT_KEY); + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_input_key, + TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY); return status; } -psa_status_t psa_generator_abort(psa_crypto_generator_t *generator) +psa_status_t psa_key_derivation_abort(psa_key_derivation_operation_t *operation) { psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GENERATOR_ABORT_SID, - .op_handle = generator->handle, + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_ABORT_SID, + .op_handle = operation->handle, }; psa_invec in_vec[] = { @@ -1106,70 +1037,249 @@ psa_status_t psa_generator_abort(psa_crypto_generator_t *generator) }; psa_outvec out_vec[] = { - {.base = &(generator->handle), .len = sizeof(uint32_t)}, + {.base = &(operation->handle), .len = sizeof(uint32_t)}, }; - status = API_DISPATCH(tfm_crypto_generator_abort, - TFM_CRYPTO_GENERATOR_ABORT); + status = API_DISPATCH(tfm_crypto_key_derivation_abort, + TFM_CRYPTO_KEY_DERIVATION_ABORT); return status; } -psa_status_t psa_key_derivation(psa_crypto_generator_t *generator, - psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *salt, - size_t salt_length, - const uint8_t *label, - size_t label_length, - size_t capacity) +psa_status_t psa_key_derivation_key_agreement( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length) { psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_SID, - .key_handle = handle, - .alg = alg, - .op_handle = generator->handle, - .capacity = capacity, + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID, + .key_handle = private_key, + .step = step, + .op_handle = operation->handle, }; - /* Sanitize the optional input */ - if ((salt == NULL) && (salt_length != 0)) { - return PSA_ERROR_INVALID_ARGUMENT; - } + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = peer_key, .len = peer_key_length}, + }; - if ((label == NULL) && (label_length != 0)) { - return PSA_ERROR_INVALID_ARGUMENT; + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_key_agreement, + TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT); + + return status; +} + +psa_status_t psa_generate_random(uint8_t *output, + size_t output_size) +{ + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_GENERATE_RANDOM_SID, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + psa_outvec out_vec[] = { + {.base = output, .len = output_size}, + }; + + if (output_size == 0) { + return PSA_SUCCESS; } + status = API_DISPATCH(tfm_crypto_generate_random, + TFM_CRYPTO_GENERATE_RANDOM); + + return status; +} + +psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, + psa_key_handle_t *handle) +{ + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_GENERATE_KEY_SID, + }; + psa_invec in_vec[] = { {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = salt, .len = salt_length}, - {.base = label, .len = label_length}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, }; psa_outvec out_vec[] = { - {.base = &(generator->handle), .len = sizeof(uint32_t)}, + {.base = handle, .len = sizeof(psa_key_handle_t)}, }; - status = API_DISPATCH(tfm_crypto_key_derivation, - TFM_CRYPTO_KEY_DERIVATION); + status = API_DISPATCH(tfm_crypto_generate_key, + TFM_CRYPTO_GENERATE_KEY); + + return status; +} + +psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_get_key_domain_parameters( + const psa_key_attributes_t *attributes, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; return status; } -psa_status_t psa_key_agreement(psa_crypto_generator_t *generator, - psa_key_handle_t private_key, - const uint8_t *peer_key, - size_t peer_key_length, - psa_algorithm_t alg) +psa_status_t psa_hash_compare(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *hash, + const size_t hash_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_finish(psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_verify(psa_aead_operation_t *operation, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag, + size_t tag_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_abort(psa_aead_operation_t *operation) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_mac_compute(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_mac_verify(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *mac, + const size_t mac_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_cipher_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_cipher_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length) { psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_AGREEMENT_SID, - .key_handle = private_key, + .sfn_id = TFM_CRYPTO_RAW_KEY_AGREEMENT_SID, .alg = alg, - .op_handle = generator->handle, + .key_handle = private_key }; psa_invec in_vec[] = { @@ -1178,67 +1288,187 @@ psa_status_t psa_key_agreement(psa_crypto_generator_t *generator, }; psa_outvec out_vec[] = { - {.base = &(generator->handle), .len = sizeof(uint32_t)}, + {.base = output, .len = output_size}, }; - status = API_DISPATCH(tfm_crypto_key_agreement, - TFM_CRYPTO_KEY_AGREEMENT); + status = API_DISPATCH(tfm_crypto_raw_key_agreement, + TFM_CRYPTO_RAW_KEY_AGREEMENT); + + *output_length = out_vec[0].len; return status; } -psa_status_t psa_generate_random(uint8_t *output, - size_t output_size) +psa_status_t psa_key_derivation_setup(psa_key_derivation_operation_t *operation, + psa_algorithm_t alg) { psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GENERATE_RANDOM_SID, + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_SETUP_SID, + .alg = alg, + .op_handle = operation->handle, }; psa_invec in_vec[] = { {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, }; - psa_outvec out_vec[] = { - {.base = output, .len = output_size}, + {.base = &(operation->handle), .len = sizeof(uint32_t)}, }; - if (output_size == 0) { - return PSA_SUCCESS; - } + status = API_DISPATCH(tfm_crypto_key_derivation_setup, + TFM_CRYPTO_KEY_DERIVATION_SETUP); + return status; +} - status = API_DISPATCH(tfm_crypto_generate_random, - TFM_CRYPTO_GENERATE_RANDOM); +psa_status_t psa_key_derivation_set_capacity( + psa_key_derivation_operation_t *operation, + size_t capacity) +{ + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID, + .capacity = capacity, + .op_handle = operation->handle, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_set_capacity, + TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY); return status; } -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) +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length) { psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GENERATE_KEY_SID, - .key_handle = handle, - .type = type, + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID, + .step = step, + .op_handle = operation->handle, }; - /* Sanitize the optional input */ - if ((extra == NULL) && (extra_size != 0)) { - return PSA_ERROR_INVALID_ARGUMENT; - } + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = data, .len = data_length}, + }; + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_input_bytes, + TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES); + return status; +} + +psa_status_t psa_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + psa_key_handle_t *handle) +{ + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID, + .op_handle = operation->handle, + }; psa_invec in_vec[] = { {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = &bits, .len = sizeof(size_t)}, - {.base = extra, .len = extra_size}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, }; - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_generate_key, - TFM_CRYPTO_GENERATE_KEY); + psa_outvec out_vec[] = { + {.base = handle, .len = sizeof(psa_key_handle_t)} + }; + + status = API_DISPATCH(tfm_crypto_key_derivation_output_key, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY); + return status; +} + +psa_status_t psa_hash_compute(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, + uint8_t *nonce, + size_t nonce_size, + size_t *nonce_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_update(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; return status; } diff --git a/interface/src/tfm_crypto_ipc_api.c b/interface/src/tfm_crypto_ipc_api.c index 3bc75976c1..9e27ade61b 100644 --- a/interface/src/tfm_crypto_ipc_api.c +++ b/interface/src/tfm_crypto_ipc_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -41,35 +41,7 @@ psa_status_t psa_crypto_init(void) return PSA_SUCCESS; } -psa_status_t psa_allocate_key(psa_key_handle_t *handle) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - const struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_ALLOCATE_KEY_SID, - }; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = handle, .len = sizeof(psa_key_handle_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_allocate_key, - TFM_CRYPTO_ALLOCATE_KEY); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_open_key(psa_key_lifetime_t lifetime, - psa_key_id_t id, +psa_status_t psa_open_key(psa_key_id_t id, psa_key_handle_t *handle) { #ifdef TFM_CRYPTO_KEY_MODULE_DISABLED @@ -78,7 +50,6 @@ psa_status_t psa_open_key(psa_key_lifetime_t lifetime, psa_status_t status; const struct tfm_crypto_pack_iovec iov = { .sfn_id = TFM_CRYPTO_OPEN_KEY_SID, - .lifetime = lifetime, }; psa_invec in_vec[] = { {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, @@ -99,22 +70,6 @@ psa_status_t psa_open_key(psa_key_lifetime_t lifetime, #endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ } -psa_status_t psa_create_key(psa_key_lifetime_t lifetime, - psa_key_id_t id, - psa_key_handle_t *handle) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - (void)lifetime; - (void)id; - (void)handle; - - /* TODO: Persistent key APIs are not supported yet */ - return PSA_ERROR_NOT_SUPPORTED; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - psa_status_t psa_close_key(psa_key_handle_t handle) { #ifdef TFM_CRYPTO_KEY_MODULE_DISABLED @@ -140,10 +95,10 @@ psa_status_t psa_close_key(psa_key_handle_t handle) #endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ } -psa_status_t psa_import_key(psa_key_handle_t handle, - psa_key_type_t type, +psa_status_t psa_import_key(const psa_key_attributes_t *attributes, const uint8_t *data, - size_t data_length) + size_t data_length, + psa_key_handle_t *handle) { #ifdef TFM_CRYPTO_KEY_MODULE_DISABLED return PSA_ERROR_NOT_SUPPORTED; @@ -151,19 +106,20 @@ psa_status_t psa_import_key(psa_key_handle_t handle, psa_status_t status; struct tfm_crypto_pack_iovec iov = { .sfn_id = TFM_CRYPTO_IMPORT_KEY_SID, - .key_handle = handle, - .type = type, }; psa_invec in_vec[] = { {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, {.base = data, .len = data_length} }; + psa_outvec out_vec[] = { + {.base = handle, .len = sizeof(psa_key_handle_t)} + }; PSA_CONNECT(TFM_CRYPTO); - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_import_key, - TFM_CRYPTO_IMPORT_KEY); - + status = API_DISPATCH(tfm_crypto_import_key, + TFM_CRYPTO_IMPORT_KEY); PSA_CLOSE(); return status; @@ -188,44 +144,69 @@ psa_status_t psa_destroy_key(psa_key_handle_t handle) status = API_DISPATCH_NO_OUTVEC(tfm_crypto_destroy_key, TFM_CRYPTO_DESTROY_KEY); - PSA_CLOSE(); return status; #endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ } -psa_status_t psa_get_key_information(psa_key_handle_t handle, - psa_key_type_t *type, - size_t *bits) +psa_status_t psa_get_key_attributes(psa_key_handle_t handle, + psa_key_attributes_t *attributes) { #ifdef TFM_CRYPTO_KEY_MODULE_DISABLED return PSA_ERROR_NOT_SUPPORTED; #else psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GET_KEY_INFORMATION_SID, + .sfn_id = TFM_CRYPTO_GET_KEY_ATTRIBUTES_SID, .key_handle = handle, }; psa_invec in_vec[] = { {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, }; psa_outvec out_vec[] = { - {.base = type, .len = sizeof(psa_key_type_t)}, - {.base = bits, .len = sizeof(size_t)} + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, }; PSA_CONNECT(TFM_CRYPTO); - status = API_DISPATCH(tfm_crypto_get_key_information, - TFM_CRYPTO_GET_KEY_INFORMATION); - + status = API_DISPATCH(tfm_crypto_get_key_attributes, + TFM_CRYPTO_GET_KEY_ATTRIBUTES); PSA_CLOSE(); return status; #endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ } +void psa_reset_key_attributes(psa_key_attributes_t *attributes) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return; +#else + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_RESET_KEY_ATTRIBUTES_SID, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + }; + + psa_handle_t ipc_handle; + ipc_handle = psa_connect(TFM_CRYPTO_SID, TFM_CRYPTO_VERSION); + if (!PSA_HANDLE_IS_VALID(ipc_handle)) { + return; + } + + (void)API_DISPATCH(tfm_crypto_reset_key_attributes, + TFM_CRYPTO_RESET_KEY_ATTRIBUTES); + PSA_CLOSE(); + + return; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + psa_status_t psa_export_key(psa_key_handle_t handle, uint8_t *data, size_t data_size, @@ -294,8 +275,8 @@ psa_status_t psa_export_public_key(psa_key_handle_t handle, } psa_status_t psa_copy_key(psa_key_handle_t source_handle, - psa_key_handle_t target_handle, - const psa_key_policy_t *constraint) + const psa_key_attributes_t *attributes, + psa_key_handle_t *target_handle) { #ifdef TFM_CRYPTO_KEY_MODULE_DISABLED return PSA_ERROR_NOT_SUPPORTED; @@ -308,120 +289,18 @@ psa_status_t psa_copy_key(psa_key_handle_t source_handle, psa_invec in_vec[] = { {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = &target_handle, .len = sizeof(psa_key_handle_t)}, - {.base = constraint, .len = sizeof(psa_key_policy_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_copy_key, - TFM_CRYPTO_COPY_KEY); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -void psa_key_policy_set_usage(psa_key_policy_t *policy, - psa_key_usage_t usage, - psa_algorithm_t alg) -{ - policy->usage = usage; - policy->alg = alg; -} - -psa_key_usage_t psa_key_policy_get_usage(const psa_key_policy_t *policy) -{ - return policy->usage; -} - -psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy) -{ - return policy->alg; -} - -psa_status_t psa_set_key_policy(psa_key_handle_t handle, - const psa_key_policy_t *policy) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_SET_KEY_POLICY_SID, - .key_handle = handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = policy, .len = sizeof(psa_key_policy_t)}, - }; - - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_set_key_policy, - TFM_CRYPTO_SET_KEY_POLICY); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_get_key_policy(psa_key_handle_t handle, - psa_key_policy_t *policy) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GET_KEY_POLICY_SID, - .key_handle = handle, - }; - - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; - psa_outvec out_vec[] = { - {.base = policy, .len = sizeof(psa_key_policy_t)}, - }; + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, - PSA_CONNECT(TFM_CRYPTO); - - status = API_DISPATCH(tfm_crypto_get_key_policy, - TFM_CRYPTO_GET_KEY_POLICY); - - PSA_CLOSE(); - - return status; -#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ -} - -psa_status_t psa_get_key_lifetime(psa_key_handle_t handle, - psa_key_lifetime_t *lifetime) -{ -#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED - return PSA_ERROR_NOT_SUPPORTED; -#else - psa_status_t status; - struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GET_KEY_LIFETIME_SID, - .key_handle = handle, }; - psa_invec in_vec[] = { - {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - }; psa_outvec out_vec[] = { - {.base = lifetime, .len = sizeof(psa_key_lifetime_t)}, + {.base = target_handle, .len = sizeof(psa_key_handle_t)}, }; PSA_CONNECT(TFM_CRYPTO); - status = API_DISPATCH(tfm_crypto_get_key_lifetime, - TFM_CRYPTO_GET_KEY_LIFETIME); + status = API_DISPATCH(tfm_crypto_copy_key, + TFM_CRYPTO_COPY_KEY); PSA_CLOSE(); @@ -842,6 +721,10 @@ psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, {.base = target_operation, .len = sizeof(psa_hash_operation_t)}, }; + if (target_operation && (target_operation->handle != 0)) { + return PSA_ERROR_BAD_STATE; + } + PSA_CONNECT(TFM_CRYPTO); status = API_DISPATCH(tfm_crypto_hash_clone, @@ -1185,12 +1068,23 @@ psa_status_t psa_asymmetric_sign(psa_key_handle_t handle, size_t signature_size, size_t *signature_length) { + return psa_sign_hash(handle, alg, hash, hash_length, signature, signature_size, signature_length); +} + +psa_status_t psa_sign_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length) +{ #ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED return PSA_ERROR_NOT_SUPPORTED; #else psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_ASYMMETRIC_SIGN_SID, + .sfn_id = TFM_CRYPTO_SIGN_HASH_SID, .key_handle = handle, .alg = alg, }; @@ -1205,8 +1099,8 @@ psa_status_t psa_asymmetric_sign(psa_key_handle_t handle, PSA_CONNECT(TFM_CRYPTO); - status = API_DISPATCH(tfm_crypto_asymmetric_sign, - TFM_CRYPTO_ASYMMETRIC_SIGN); + status = API_DISPATCH(tfm_crypto_sign_hash, + TFM_CRYPTO_SIGN_HASH); *signature_length = out_vec[0].len; @@ -1223,12 +1117,22 @@ psa_status_t psa_asymmetric_verify(psa_key_handle_t handle, const uint8_t *signature, size_t signature_length) { + return psa_verify_hash(handle, alg, hash, hash_length, signature, signature_length); +} + +psa_status_t psa_verify_hash(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) +{ #ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED return PSA_ERROR_NOT_SUPPORTED; #else psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_ASYMMETRIC_VERIFY_SID, + .sfn_id = TFM_CRYPTO_VERIFY_HASH_SID, .key_handle = handle, .alg = alg }; @@ -1241,8 +1145,8 @@ psa_status_t psa_asymmetric_verify(psa_key_handle_t handle, PSA_CONNECT(TFM_CRYPTO); - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_asymmetric_verify, - TFM_CRYPTO_ASYMMETRIC_VERIFY); + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_verify_hash, + TFM_CRYPTO_VERIFY_HASH); PSA_CLOSE(); @@ -1354,16 +1258,17 @@ psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle, #endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ } -psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator, - size_t *capacity) +psa_status_t psa_key_derivation_get_capacity( + const psa_key_derivation_operation_t *operation, + size_t *capacity) { #ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED return PSA_ERROR_NOT_SUPPORTED; #else psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GET_GENERATOR_CAPACITY_SID, - .op_handle = generator->handle, + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID, + .op_handle = operation->handle, }; psa_invec in_vec[] = { @@ -1376,8 +1281,8 @@ psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator, PSA_CONNECT(TFM_CRYPTO); - status = API_DISPATCH(tfm_crypto_get_generator_capacity, - TFM_CRYPTO_GET_GENERATOR_CAPACITY); + status = API_DISPATCH(tfm_crypto_key_derivation_get_capacity, + TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY); PSA_CLOSE(); @@ -1385,17 +1290,18 @@ psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator, #endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ } -psa_status_t psa_generator_read(psa_crypto_generator_t *generator, - uint8_t *output, - size_t output_length) +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, + size_t output_length) { #ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED return PSA_ERROR_NOT_SUPPORTED; #else psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GENERATOR_READ_SID, - .op_handle = generator->handle, + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID, + .op_handle = operation->handle, }; psa_invec in_vec[] = { @@ -1408,8 +1314,8 @@ psa_status_t psa_generator_read(psa_crypto_generator_t *generator, PSA_CONNECT(TFM_CRYPTO); - status = API_DISPATCH(tfm_crypto_generator_read, - TFM_CRYPTO_GENERATOR_READ); + status = API_DISPATCH(tfm_crypto_key_derivation_output_bytes, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES); PSA_CLOSE(); @@ -1417,31 +1323,30 @@ psa_status_t psa_generator_read(psa_crypto_generator_t *generator, #endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ } -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) +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t handle) { #ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED return PSA_ERROR_NOT_SUPPORTED; #else psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GENERATOR_IMPORT_KEY_SID, + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID, .key_handle = handle, - .type = type, - .op_handle = generator->handle, + .step = step, + .op_handle = operation->handle, }; psa_invec in_vec[] = { {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = &bits, .len = sizeof(size_t)}, }; PSA_CONNECT(TFM_CRYPTO); - status = API_DISPATCH_NO_OUTVEC(tfm_crypto_generator_import_key, - TFM_CRYPTO_GENERATOR_IMPORT_KEY); + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_input_key, + TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY); PSA_CLOSE(); @@ -1449,15 +1354,16 @@ psa_status_t psa_generator_import_key(psa_key_handle_t handle, #endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ } -psa_status_t psa_generator_abort(psa_crypto_generator_t *generator) +psa_status_t psa_key_derivation_abort( + psa_key_derivation_operation_t *operation) { #ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED return PSA_ERROR_NOT_SUPPORTED; #else psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GENERATOR_ABORT_SID, - .op_handle = generator->handle, + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_ABORT_SID, + .op_handle = operation->handle, }; psa_invec in_vec[] = { @@ -1465,13 +1371,13 @@ psa_status_t psa_generator_abort(psa_crypto_generator_t *generator) }; psa_outvec out_vec[] = { - {.base = &(generator->handle), .len = sizeof(uint32_t)}, + {.base = &(operation->handle), .len = sizeof(uint32_t)}, }; PSA_CONNECT(TFM_CRYPTO); - status = API_DISPATCH(tfm_crypto_generator_abort, - TFM_CRYPTO_GENERATOR_ABORT); + status = API_DISPATCH(tfm_crypto_key_derivation_abort, + TFM_CRYPTO_KEY_DERIVATION_ABORT); PSA_CLOSE(); @@ -1479,57 +1385,67 @@ psa_status_t psa_generator_abort(psa_crypto_generator_t *generator) #endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ } -psa_status_t psa_key_derivation(psa_crypto_generator_t *generator, - psa_key_handle_t handle, - psa_algorithm_t alg, - const uint8_t *salt, - size_t salt_length, - const uint8_t *label, - size_t label_length, - size_t capacity) +psa_status_t psa_key_derivation_key_agreement( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length) { #ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED return PSA_ERROR_NOT_SUPPORTED; #else psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_DERIVATION_SID, - .key_handle = handle, - .alg = alg, - .op_handle = generator->handle, - .capacity = capacity, + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID, + .key_handle = private_key, + .step = step, + .op_handle = operation->handle, }; - /* Sanitize the optional input */ - if ((salt == NULL) && (salt_length != 0)) { - return PSA_ERROR_INVALID_ARGUMENT; - } + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = peer_key, .len = peer_key_length}, + }; - if ((label == NULL) && (label_length != 0)) { - return PSA_ERROR_INVALID_ARGUMENT; - } + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_key_agreement, + TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_generate_random(uint8_t *output, + size_t output_size) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_GENERATE_RANDOM_SID, + }; psa_invec in_vec[] = { {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = salt, .len = salt_length}, - {.base = label, .len = label_length}, }; psa_outvec out_vec[] = { - {.base = &(generator->handle), .len = sizeof(uint32_t)}, + {.base = output, .len = output_size}, }; + if (output_size == 0) { + return PSA_SUCCESS; + } + PSA_CONNECT(TFM_CRYPTO); - size_t in_len = ARRAY_SIZE(in_vec); - if (label == NULL) { - in_len--; - if (salt == NULL) { - in_len--; - } - } - status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, - out_vec, ARRAY_SIZE(out_vec)); + status = API_DISPATCH(tfm_crypto_generate_random, + TFM_CRYPTO_GENERATE_RANDOM); PSA_CLOSE(); @@ -1537,70 +1453,215 @@ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator, #endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ } -psa_status_t psa_key_agreement(psa_crypto_generator_t *generator, - psa_key_handle_t private_key, - const uint8_t *peer_key, - size_t peer_key_length, - psa_algorithm_t alg) +psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, + psa_key_handle_t *handle) { #ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED return PSA_ERROR_NOT_SUPPORTED; #else psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_KEY_AGREEMENT_SID, - .key_handle = private_key, - .alg = alg, - .op_handle = generator->handle, + .sfn_id = TFM_CRYPTO_GENERATE_KEY_SID, }; psa_invec in_vec[] = { {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = peer_key, .len = peer_key_length}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, }; psa_outvec out_vec[] = { - {.base = &(generator->handle), .len = sizeof(uint32_t)}, + {.base = handle, .len = sizeof(psa_key_handle_t)}, }; PSA_CONNECT(TFM_CRYPTO); - status = API_DISPATCH(tfm_crypto_key_agreement, - TFM_CRYPTO_KEY_AGREEMENT); - + status = API_DISPATCH(tfm_crypto_generate_key, + TFM_CRYPTO_GENERATE_KEY); PSA_CLOSE(); return status; #endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ } -psa_status_t psa_generate_random(uint8_t *output, - size_t output_size) +psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_get_key_domain_parameters( + const psa_key_attributes_t *attributes, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_hash_compare(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *hash, + const size_t hash_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_finish(psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_verify(psa_aead_operation_t *operation, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag, + size_t tag_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_abort(psa_aead_operation_t *operation) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_mac_compute(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_mac_verify(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *mac, + const size_t mac_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_cipher_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_cipher_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length) { #ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED return PSA_ERROR_NOT_SUPPORTED; #else psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GENERATE_RANDOM_SID, + .sfn_id = TFM_CRYPTO_RAW_KEY_AGREEMENT_SID, + .alg = alg, + .key_handle = private_key }; psa_invec in_vec[] = { {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = peer_key, .len = peer_key_length}, }; psa_outvec out_vec[] = { {.base = output, .len = output_size}, }; - if (output_size == 0) { - return PSA_SUCCESS; - } - PSA_CONNECT(TFM_CRYPTO); - status = API_DISPATCH(tfm_crypto_generate_random, - TFM_CRYPTO_GENERATE_RANDOM); + status = API_DISPATCH(tfm_crypto_raw_key_agreement, + TFM_CRYPTO_RAW_KEY_AGREEMENT); + + *output_length = out_vec[0].len; PSA_CLOSE(); @@ -1608,44 +1669,208 @@ psa_status_t psa_generate_random(uint8_t *output, #endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ } -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) +psa_status_t psa_key_derivation_setup(psa_key_derivation_operation_t *operation, + psa_algorithm_t alg) { #ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED return PSA_ERROR_NOT_SUPPORTED; #else psa_status_t status; struct tfm_crypto_pack_iovec iov = { - .sfn_id = TFM_CRYPTO_GENERATE_KEY_SID, - .key_handle = handle, - .type = type, + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_SETUP_SID, + .alg = alg, + .op_handle = operation->handle, }; - /* Sanitize the optional input */ - if ((extra == NULL) && (extra_size != 0)) { - return PSA_ERROR_INVALID_ARGUMENT; - } + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_key_derivation_setup, + TFM_CRYPTO_KEY_DERIVATION_SETUP); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_set_capacity( + psa_key_derivation_operation_t *operation, + size_t capacity) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID, + .capacity = capacity, + .op_handle = operation->handle, + }; psa_invec in_vec[] = { {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, - {.base = &bits, .len = sizeof(size_t)}, - {.base = extra, .len = extra_size}, }; PSA_CONNECT(TFM_CRYPTO); - size_t in_len = ARRAY_SIZE(in_vec); - if (extra == NULL) { - in_len--; - } + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_set_capacity, + TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID, + .step = step, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = data, .len = data_length}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_input_bytes, + TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + psa_key_handle_t *handle) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + }; + + psa_outvec out_vec[] = { + {.base = handle, .len = sizeof(psa_key_handle_t)} + }; - status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, NULL, 0); + PSA_CONNECT(TFM_CRYPTO); + status = API_DISPATCH(tfm_crypto_key_derivation_output_key, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY); PSA_CLOSE(); return status; #endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ } + +psa_status_t psa_hash_compute(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, + uint8_t *nonce, + size_t nonce_size, + size_t *nonce_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_update(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} |