From 03d62b1958419903c766850294dbec8270e6f309 Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Thu, 18 Jul 2024 19:31:57 +0100 Subject: [PATCH 01/17] Add psa_key_agreement_iop_t structs and docs Signed-off-by: Paul Elliott --- tf-psa-crypto/include/psa/crypto.h | 42 +++++++++++++++++++++++ tf-psa-crypto/include/psa/crypto_struct.h | 34 ++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/tf-psa-crypto/include/psa/crypto.h b/tf-psa-crypto/include/psa/crypto.h index 3525da221f..7a48e3eff0 100644 --- a/tf-psa-crypto/include/psa/crypto.h +++ b/tf-psa-crypto/include/psa/crypto.h @@ -4810,6 +4810,48 @@ psa_status_t psa_verify_hash_abort( psa_verify_hash_interruptible_operation_t *operation); +/**@}*/ + +/**@}*/ + +/** + * \defgroup interruptible_key_agreement Interruptible Key Agreement + * @{ + */ + +/** + * The type of the state data structure for interruptible key agreement + * operations. + * + * Before calling any function on an interruptible key agreement object, the + * application must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_agreement_iop_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_agreement_iop_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_AGREEMENT_IOP_INIT, + * for example: + * - \code + * psa_key_agreement_iop_t operation = PSA_KEY_AGREEMENT_IOP_INIT; + * \endcode + * - Assign the result of the function psa_key_agreement_iop_init() to the + * structure, for example: + * \code + * psa_key_agreement_iop_t operation; + * operation = psa_key_agreement_iop_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. + */ +typedef struct psa_key_agreement_iop_s psa_key_agreement_iop_t; + /**@}*/ #ifdef __cplusplus diff --git a/tf-psa-crypto/include/psa/crypto_struct.h b/tf-psa-crypto/include/psa/crypto_struct.h index 3913551aa8..4a6c9fe7bb 100644 --- a/tf-psa-crypto/include/psa/crypto_struct.h +++ b/tf-psa-crypto/include/psa/crypto_struct.h @@ -494,6 +494,40 @@ psa_verify_hash_interruptible_operation_init(void) return v; } +/** + * \brief The context for PSA interruptible key agreement. + */ +struct psa_key_agreement_iop_s { +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) + mbedtls_psa_client_handle_t handle; +#else + /** + * Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_crypto_driver_wrappers.h + * ID value zero means the context is not valid or not assigned to + * any driver (i.e. none of the driver contexts are active). + */ + unsigned int MBEDTLS_PRIVATE(id); + +#endif +}; + +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) +#define PSA_KEY_AGREEMENT_IOP_INIT { 0 } +#else +#define PSA_KEY_AGREEMENT_IOP_INIT { 0 } +#endif + +static inline struct psa_key_agreement_iop_s +psa_key_agreement_iop_init(void) +{ + const struct psa_key_agreement_iop_s v = PSA_KEY_AGREEMENT_IOP_INIT; + + return v; +} + #ifdef __cplusplus } #endif From d791062fee1da5171caaf9ca967e59a9555a1524 Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Thu, 18 Jul 2024 19:33:17 +0100 Subject: [PATCH 02/17] Add psa_key_agreement_iop_get_num_ops() docs Signed-off-by: Paul Elliott --- tf-psa-crypto/core/psa_crypto_ecp.c | 10 ++++++++++ tf-psa-crypto/include/psa/crypto.h | 25 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/tf-psa-crypto/core/psa_crypto_ecp.c b/tf-psa-crypto/core/psa_crypto_ecp.c index 95baff6a0f..9e98cc1296 100644 --- a/tf-psa-crypto/core/psa_crypto_ecp.c +++ b/tf-psa-crypto/core/psa_crypto_ecp.c @@ -592,5 +592,15 @@ exit: } #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */ +/****************************************************************/ +/* Interruptible ECC Key Agreement */ +/****************************************************************/ + +uint32_t psa_key_agreement_iop_get_num_ops( + psa_key_agreement_iop_t *operation) +{ + (void) operation; + return 0; +} #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/tf-psa-crypto/include/psa/crypto.h b/tf-psa-crypto/include/psa/crypto.h index 7a48e3eff0..75ea8fe7fe 100644 --- a/tf-psa-crypto/include/psa/crypto.h +++ b/tf-psa-crypto/include/psa/crypto.h @@ -4852,6 +4852,31 @@ psa_status_t psa_verify_hash_abort( */ typedef struct psa_key_agreement_iop_s psa_key_agreement_iop_t; +/** + * \brief Get the number of ops that a key agreement + * operation has taken so far. If the operation has + * completed, then this will represent the number of + * ops required for the entire operation. + * After initialization or calling \c + * psa_key_agreement_iop_abort() on the operation, + * a value of 0 will be returned. + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * This is a helper provided to help you tune the + * value passed to \c + * psa_interruptible_set_max_ops(). + * + * \param operation The \c psa_key_agreement_iop_t to use. This must + * be initialized first. + * + * \return Number of ops that the operation has taken so + * far. + */ +uint32_t psa_key_agreement_iop_get_num_ops(psa_key_agreement_iop_t *operation); + /**@}*/ #ifdef __cplusplus From 2dc58fe717f40c0a7f83fda3dfec0f965d79cde4 Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Thu, 18 Jul 2024 21:30:36 +0100 Subject: [PATCH 03/17] Add psa_key_agreement_iop_setup() documentation Signed-off-by: Paul Elliott --- tf-psa-crypto/core/psa_crypto_ecp.c | 18 ++++ tf-psa-crypto/include/psa/crypto.h | 158 ++++++++++++++++++++++++++++ 2 files changed, 176 insertions(+) diff --git a/tf-psa-crypto/core/psa_crypto_ecp.c b/tf-psa-crypto/core/psa_crypto_ecp.c index 9e98cc1296..ce119e258f 100644 --- a/tf-psa-crypto/core/psa_crypto_ecp.c +++ b/tf-psa-crypto/core/psa_crypto_ecp.c @@ -603,4 +603,22 @@ uint32_t psa_key_agreement_iop_get_num_ops( return 0; } +psa_status_t psa_key_agreement_iop_setup( + psa_key_agreement_iop_t *operation, + psa_key_id_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + psa_algorithm_t alg, + const psa_key_attributes_t *attributes) +{ + (void) operation; + (void) private_key; + (void) peer_key; + (void) peer_key_length; + (void) alg; + (void) attributes; + + return PSA_SUCCESS; +} + #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/tf-psa-crypto/include/psa/crypto.h b/tf-psa-crypto/include/psa/crypto.h index 75ea8fe7fe..c43f674c63 100644 --- a/tf-psa-crypto/include/psa/crypto.h +++ b/tf-psa-crypto/include/psa/crypto.h @@ -4877,6 +4877,164 @@ typedef struct psa_key_agreement_iop_s psa_key_agreement_iop_t; */ uint32_t psa_key_agreement_iop_get_num_ops(psa_key_agreement_iop_t *operation); +/** + * \brief Start a key agreement operation, in an + * interruptible manner. + * + * \see \c psa_key_agreement_iop_complete() + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function combined with \c + * psa_key_agreement_iop_complete() is equivalent + * to \c psa_key_agreement() but \c + * psa_key_agreement_iop_complete() can return + * early and resume according to the limit set with + * \c psa_interruptible_set_max_ops() to reduce the + * maximum time spent in a function. + * + * \note Users should call + * \c psa_key_agreement_iop_complete() repeatedly + * on the same operation object after a successful + * call to this function until \c + * psa_key_agreement_iop_complete() either returns + * 0 or an error. + * \c psa_key_agreement_iop_complete() will return + * #PSA_OPERATION_INCOMPLETE if there is more work + * to do. Alternatively users can call + * \c psa_key_agreement_iop_abort() at any point + * if they no longer want the result. + * + * \note If this function returns an error status, the + * operation enters an error state and must be + * aborted by calling \c + * psa_key_agreement_iop_abort(). + * + * \param[in, out] operation The \c psa_key_agreement_iop_t to use. This must + * be initialized as per the documentation for + * \c psa_key_agreement_iop_t, and be inactive. + + * \param private_key Identifier of the private key to use. It must + * allow the usage #PSA_KEY_USAGE_DERIVE. + * \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(). + * The peer key data is parsed with the type + * #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) where + * type is the type of \p private_key, and with the + * same bit-size as \p private_key. + * \param peer_key_length Size of \p peer_key in bytes. + * + * \param alg The key agreement algorithm to compute + * (a \c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_AGREEMENT(\p alg) is true). + * + * \param[in] attributes The attributes for the new key. + * This function uses the attributes as follows: + * * The key type must be one of + * `PSA_KEY_TYPE_DERIVE`,`PSA_KEY_TYPE_RAW_DATA`, + * `PSA_KEY_TYPE_HMAC`, or + * `PSA_KEY_TYPE_PASSWORD`. + * * Implementations must support the + * `PSA_KEY_TYPE_DERIVE` and + * `PSA_KEY_TYPE_RAW_DATA` key types. + * * The size of the returned key is always the + * bit-size of the shared secret, rounded up to a + * whole number of bytes. The key size in \p + * attributes can be zero; if it is nonzero, it + * must be equal to the output size of the key + * agreement, in bits. + * * The output size, in bits, of the key agreement + * is #PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(type, + * bits), where type and bits are the type and + * bit-size of \p private_key. + * * The key permitted-algorithm policy is required + * for keys that will be used for a cryptographic + * operation. The key usage flags define what + * operations are permitted with the key. The key + * lifetime and identifier are required for a + * persistent key. + * + * \note \p attributes is an input parameter, it is not + * updated with the final key attributes. The final + * attributes of the new key can be queried by + * calling `psa_get_key_attributes()` with + * the key's identifier. + * + * \retval #PSA_SUCCESS + * The operation started successfully - please call \c + * psa_key_agreement_iop_complete() with the same context to complete + * the operation. + * + * \retval #PSA_ERROR_BAD_STATE + * Another operation has already been started on this context, and is + * still in progress. + * + * \retval #PSA_ERROR_NOT_PERMITTED + * The following conditions can result in this error: + * * Either the \p private_key does not have the #PSA_KEY_USAGE_DERIVE` + * flag, or it does not permit the requested algorithm. + * * The implementation does not permit creating a key with the + * specified attributes due to some implementation-specific policy. + * + * \retval #PSA_ERROR_INVALID_HANDLE + * \p private_key is not a valid key identifier. + * + * \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_INVALID_ARGUMENT + * The following conditions can result in this error: + * * \p alg is not a key agreement algorithm. + * * \p private_key is not compatible with \p alg. + * * \p peer_key is not a valid public key corresponding to + * \p private_key. + * * The output key attributes in \p attributes are not valid: + * - The key type is not valid for key agreement output. + * - The key size is nonzero, and is not the size of the shared + * secret. + * - The key lifetime is invalid. + * - The key identifier is not valid for the key lifetime. + * - The key usage flags include invalid values. + * - The key's permitted-usage algorithm is invalid. + * - The key attributes, as a whole, are invalid. + * + * \retval #PSA_ERROR_NOT_SUPPORTED + * The following conditions can result in this error: + * * \p alg is not supported or is not a key agreement algorithm. + * * \p private_key is not supported for use with \p alg. The output + * key attributes, as a whole, are not supported, either by the + * implementation in general or in the specified storage location. + * + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The following conditions can result in this error: + * * The library has not been previously initialized by + * \c psa_crypto_init(). It is implementation-dependent whether a + * failure to initialize results in this error code. + * * The operation state is not valid: it must be inactive. + */ + +psa_status_t psa_key_agreement_iop_setup( + psa_key_agreement_iop_t *operation, + psa_key_id_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + psa_algorithm_t alg, + const psa_key_attributes_t *attributes); + /**@}*/ #ifdef __cplusplus From b06727e463a2af1f30c1dd2b37a87dba3d971d2d Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Thu, 18 Jul 2024 21:31:55 +0100 Subject: [PATCH 04/17] Add psa_key_agreement_iop_complete() documentation Signed-off-by: Paul Elliott --- tf-psa-crypto/core/psa_crypto_ecp.c | 10 ++++ tf-psa-crypto/include/psa/crypto.h | 82 +++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/tf-psa-crypto/core/psa_crypto_ecp.c b/tf-psa-crypto/core/psa_crypto_ecp.c index ce119e258f..948e14675b 100644 --- a/tf-psa-crypto/core/psa_crypto_ecp.c +++ b/tf-psa-crypto/core/psa_crypto_ecp.c @@ -621,4 +621,14 @@ psa_status_t psa_key_agreement_iop_setup( return PSA_SUCCESS; } +psa_status_t psa_key_agreement_iop_complete( + psa_key_agreement_iop_t *operation, + psa_key_id_t *key) +{ + (void) operation; + (void) key; + + return PSA_SUCCESS; +} + #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/tf-psa-crypto/include/psa/crypto.h b/tf-psa-crypto/include/psa/crypto.h index c43f674c63..7ec865a9ad 100644 --- a/tf-psa-crypto/include/psa/crypto.h +++ b/tf-psa-crypto/include/psa/crypto.h @@ -5035,6 +5035,88 @@ psa_status_t psa_key_agreement_iop_setup( psa_algorithm_t alg, const psa_key_attributes_t *attributes); +/** + * \brief Continue and eventually complete the action of + * key agreement, in an interruptible + * manner. + * + * \see \c psa_key_agreement_iop_setup() + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function combined with \c + * psa_key_agreement_iop_setup() is equivalent to + * \c psa_key_agreement() but this + * function can return early and resume according + * to the limit set with \c + * psa_interruptible_set_max_ops() to reduce the + * maximum time spent in a function call. + * + * \note Users should call this function on the same + * operation object repeatedly until it either + * returns 0 or an error. This function will return + * #PSA_OPERATION_INCOMPLETE if there is more work + * to do. Alternatively users can call + * \c psa_key_agreement_iop_abort() at any point if + * they no longer want the result. + * + * \note When this function returns successfully, the + * operation becomes inactive. If this function + * returns an error status, the operation enters an + * error state and must be aborted by calling + * \c psa_key_agreement_iop_abort(). + * + * \param[in, out] operation The \c psa_key_agreement_iop_t to use. This must + * be initialized first, and have had \c + * psa_key_agreement_iop_start() called with it + * first. + * + * \param[out] key On success, an identifier for the newly created + * key, on failure this will be set to + * #PSA_KEY_ID_NULL. + * + * \retval #PSA_SUCCESS + * The operation is complete and \p key contains the shared secret. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * + * \retval #PSA_OPERATION_INCOMPLETE + * Operation was interrupted due to the setting of \c + * psa_interruptible_set_max_ops(). There is still work to be done. + * Call this function again with the same operation object. + * + * \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_INVALID_SIGNATURE + * The calculation was performed successfully, but the passed + * signature is not a valid signature. + * \retval #PSA_ERROR_BAD_STATE + * An operation was not previously started on this context via + * \c psa_key_agreement_iop_start(). + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription + * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription + * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription + * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription + * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription + * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription + * \retval #PSA_ERROR_DATA_INVALID \emptydescription + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The following conditions can result in this error: + * * The library has not been previously initialized by + * \c psa_crypto_init(). It is implementation-dependent whether a + * failure to initialize results in this error code. + * * The operation state is not valid: it must be inactive. + */ +psa_status_t psa_key_agreement_iop_complete( + psa_key_agreement_iop_t *operation, + psa_key_id_t *key); + /**@}*/ #ifdef __cplusplus From 088fd7ec852b3a2db0de73b03de1a562cfa29f5d Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Thu, 18 Jul 2024 21:40:16 +0100 Subject: [PATCH 05/17] Add psa_key_agreement_iop_abort() documentation Signed-off-by: Paul Elliott --- tf-psa-crypto/core/psa_crypto_ecp.c | 7 +++++ tf-psa-crypto/include/psa/crypto.h | 41 +++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/tf-psa-crypto/core/psa_crypto_ecp.c b/tf-psa-crypto/core/psa_crypto_ecp.c index 948e14675b..096bc116b2 100644 --- a/tf-psa-crypto/core/psa_crypto_ecp.c +++ b/tf-psa-crypto/core/psa_crypto_ecp.c @@ -631,4 +631,11 @@ psa_status_t psa_key_agreement_iop_complete( return PSA_SUCCESS; } +psa_status_t psa_key_agreement_iop_abort( + psa_key_agreement_iop_t *operation) +{ + (void) operation; + + return PSA_SUCCESS; +} #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/tf-psa-crypto/include/psa/crypto.h b/tf-psa-crypto/include/psa/crypto.h index 7ec865a9ad..eaac3585c2 100644 --- a/tf-psa-crypto/include/psa/crypto.h +++ b/tf-psa-crypto/include/psa/crypto.h @@ -5117,6 +5117,47 @@ psa_status_t psa_key_agreement_iop_complete( psa_key_agreement_iop_t *operation, psa_key_id_t *key); +/** + * \brief Abort a key agreement operation. + * + * \warning This is a beta API, and thus subject to change + * at any point. It is not bound by the usual + * interface stability promises. + * + * \note This function is the only function that clears + * the number of ops completed as part of the + * operation. Please ensure you copy this value via + * \c psa_key_agreement_iop_get_num_ops() if + * required before calling. + * + * \note Aborting an operation frees all + * associated resources except for the operation + * structure itself. Once aborted, the operation + * object can be reused for another operation by + * calling \c psa_key_agreement_iop_setup() again. + * + * \note You may call this function any time after the + * operation object has been initialized. + * In particular, calling \c + * psa_key_agreement_iop_abort() after the + * operation has already been terminated by a call + * to \c psa_key_agreement_iop_abort() or + * psa_key_agreement_iop_complete() is safe. + * + * \param[in,out] operation The \c psa_key_agreement_iop_t to use + * + * \retval #PSA_SUCCESS + * The operation was aborted successfully. + * + * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by + * \c psa_crypto_init(). It is implementation-dependent whether a + * failure to initialize results in this error code. + */ +psa_status_t psa_key_agreement_iop_abort( + psa_key_agreement_iop_t *operation); + /**@}*/ #ifdef __cplusplus From c884b29b9598184f296bf3dded6dfd6730145fac Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Fri, 19 Jul 2024 17:32:42 +0100 Subject: [PATCH 06/17] Add generated files for new iop key agreement funcs Signed-off-by: Paul Elliott --- tests/include/test/psa_test_wrappers.h | 21 +++++++++++++++ tests/src/psa_test_wrappers.c | 36 ++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/tests/include/test/psa_test_wrappers.h b/tests/include/test/psa_test_wrappers.h index e6d712bd63..50744392e5 100644 --- a/tests/include/test/psa_test_wrappers.h +++ b/tests/include/test/psa_test_wrappers.h @@ -441,6 +441,27 @@ psa_status_t mbedtls_test_wrap_psa_import_key( #define psa_import_key(arg0_attributes, arg1_data, arg2_data_length, arg3_key) \ mbedtls_test_wrap_psa_import_key(arg0_attributes, arg1_data, arg2_data_length, arg3_key) +psa_status_t mbedtls_test_wrap_psa_key_agreement_iop_abort( + psa_key_agreement_iop_t *arg0_operation); +#define psa_key_agreement_iop_abort(arg0_operation) \ + mbedtls_test_wrap_psa_key_agreement_iop_abort(arg0_operation) + +psa_status_t mbedtls_test_wrap_psa_key_agreement_iop_complete( + psa_key_agreement_iop_t *arg0_operation, + psa_key_id_t *arg1_key); +#define psa_key_agreement_iop_complete(arg0_operation, arg1_key) \ + mbedtls_test_wrap_psa_key_agreement_iop_complete(arg0_operation, arg1_key) + +psa_status_t mbedtls_test_wrap_psa_key_agreement_iop_setup( + psa_key_agreement_iop_t *arg0_operation, + psa_key_id_t arg1_private_key, + const uint8_t *arg2_peer_key, + size_t arg3_peer_key_length, + psa_algorithm_t arg4_alg, + const psa_key_attributes_t *arg5_attributes); +#define psa_key_agreement_iop_setup(arg0_operation, arg1_private_key, arg2_peer_key, arg3_peer_key_length, arg4_alg, arg5_attributes) \ + mbedtls_test_wrap_psa_key_agreement_iop_setup(arg0_operation, arg1_private_key, arg2_peer_key, arg3_peer_key_length, arg4_alg, arg5_attributes) + psa_status_t mbedtls_test_wrap_psa_key_derivation_abort( psa_key_derivation_operation_t *arg0_operation); #define psa_key_derivation_abort(arg0_operation) \ diff --git a/tests/src/psa_test_wrappers.c b/tests/src/psa_test_wrappers.c index 24e05c8c6a..44f9868f82 100644 --- a/tests/src/psa_test_wrappers.c +++ b/tests/src/psa_test_wrappers.c @@ -773,6 +773,42 @@ psa_status_t mbedtls_test_wrap_psa_import_key( return status; } +/* Wrapper for psa_key_agreement_iop_abort */ +psa_status_t mbedtls_test_wrap_psa_key_agreement_iop_abort( + psa_key_agreement_iop_t *arg0_operation) +{ + psa_status_t status = (psa_key_agreement_iop_abort)(arg0_operation); + return status; +} + +/* Wrapper for psa_key_agreement_iop_complete */ +psa_status_t mbedtls_test_wrap_psa_key_agreement_iop_complete( + psa_key_agreement_iop_t *arg0_operation, + psa_key_id_t *arg1_key) +{ + psa_status_t status = (psa_key_agreement_iop_complete)(arg0_operation, arg1_key); + return status; +} + +/* Wrapper for psa_key_agreement_iop_setup */ +psa_status_t mbedtls_test_wrap_psa_key_agreement_iop_setup( + psa_key_agreement_iop_t *arg0_operation, + psa_key_id_t arg1_private_key, + const uint8_t *arg2_peer_key, + size_t arg3_peer_key_length, + psa_algorithm_t arg4_alg, + const psa_key_attributes_t *arg5_attributes) +{ +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_POISON(arg2_peer_key, arg3_peer_key_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + psa_status_t status = (psa_key_agreement_iop_setup)(arg0_operation, arg1_private_key, arg2_peer_key, arg3_peer_key_length, arg4_alg, arg5_attributes); +#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) + MBEDTLS_TEST_MEMORY_UNPOISON(arg2_peer_key, arg3_peer_key_length); +#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */ + return status; +} + /* Wrapper for psa_key_derivation_abort */ psa_status_t mbedtls_test_wrap_psa_key_derivation_abort( psa_key_derivation_operation_t *arg0_operation) From cae2bed689bd3d940f6e4f3ed9cdca251f17895d Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Wed, 31 Jul 2024 18:48:34 +0100 Subject: [PATCH 07/17] Remove unneccessary 'Implementation' references These were copied from the PSA docs when they should not have been. Signed-off-by: Paul Elliott --- tf-psa-crypto/include/psa/crypto.h | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/tf-psa-crypto/include/psa/crypto.h b/tf-psa-crypto/include/psa/crypto.h index eaac3585c2..f0b740eb64 100644 --- a/tf-psa-crypto/include/psa/crypto.h +++ b/tf-psa-crypto/include/psa/crypto.h @@ -4938,14 +4938,11 @@ uint32_t psa_key_agreement_iop_get_num_ops(psa_key_agreement_iop_t *operation); * `PSA_KEY_TYPE_DERIVE`,`PSA_KEY_TYPE_RAW_DATA`, * `PSA_KEY_TYPE_HMAC`, or * `PSA_KEY_TYPE_PASSWORD`. - * * Implementations must support the - * `PSA_KEY_TYPE_DERIVE` and - * `PSA_KEY_TYPE_RAW_DATA` key types. * * The size of the returned key is always the * bit-size of the shared secret, rounded up to a * whole number of bytes. The key size in \p - * attributes can be zero; if it is nonzero, it - * must be equal to the output size of the key + * attributes can be zero; if it is nonzero, + * it must be equal to the output size of the key * agreement, in bits. * * The output size, in bits, of the key agreement * is #PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(type, @@ -4977,8 +4974,6 @@ uint32_t psa_key_agreement_iop_get_num_ops(psa_key_agreement_iop_t *operation); * The following conditions can result in this error: * * Either the \p private_key does not have the #PSA_KEY_USAGE_DERIVE` * flag, or it does not permit the requested algorithm. - * * The implementation does not permit creating a key with the - * specified attributes due to some implementation-specific policy. * * \retval #PSA_ERROR_INVALID_HANDLE * \p private_key is not a valid key identifier. @@ -5022,8 +5017,7 @@ uint32_t psa_key_agreement_iop_get_num_ops(psa_key_agreement_iop_t *operation); * \retval #PSA_ERROR_BAD_STATE * The following conditions can result in this error: * * The library has not been previously initialized by - * \c psa_crypto_init(). It is implementation-dependent whether a - * failure to initialize results in this error code. + * \c psa_crypto_init(). * * The operation state is not valid: it must be inactive. */ @@ -5109,8 +5103,7 @@ psa_status_t psa_key_agreement_iop_setup( * \retval #PSA_ERROR_BAD_STATE * The following conditions can result in this error: * * The library has not been previously initialized by - * \c psa_crypto_init(). It is implementation-dependent whether a - * failure to initialize results in this error code. + * \c psa_crypto_init(). * * The operation state is not valid: it must be inactive. */ psa_status_t psa_key_agreement_iop_complete( @@ -5152,8 +5145,7 @@ psa_status_t psa_key_agreement_iop_complete( * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by - * \c psa_crypto_init(). It is implementation-dependent whether a - * failure to initialize results in this error code. + * \c psa_crypto_init(). */ psa_status_t psa_key_agreement_iop_abort( psa_key_agreement_iop_t *operation); From 867815d89daa042e385e642acac3cf6fea458d3a Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Wed, 31 Jul 2024 18:56:36 +0100 Subject: [PATCH 08/17] Minor formatting fixes Signed-off-by: Paul Elliott --- tf-psa-crypto/include/psa/crypto.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tf-psa-crypto/include/psa/crypto.h b/tf-psa-crypto/include/psa/crypto.h index f0b740eb64..06ec304b13 100644 --- a/tf-psa-crypto/include/psa/crypto.h +++ b/tf-psa-crypto/include/psa/crypto.h @@ -4923,9 +4923,9 @@ uint32_t psa_key_agreement_iop_get_num_ops(psa_key_agreement_iop_t *operation); * standard formats for public keys are documented * in the documentation of psa_export_public_key(). * The peer key data is parsed with the type - * #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) where - * type is the type of \p private_key, and with the - * same bit-size as \p private_key. + * #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type) + * where \c type is the type of \p private_key, + * and with the same bit-size as \p private_key. * \param peer_key_length Size of \p peer_key in bytes. * * \param alg The key agreement algorithm to compute @@ -4945,9 +4945,9 @@ uint32_t psa_key_agreement_iop_get_num_ops(psa_key_agreement_iop_t *operation); * it must be equal to the output size of the key * agreement, in bits. * * The output size, in bits, of the key agreement - * is #PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(type, - * bits), where type and bits are the type and - * bit-size of \p private_key. + * is #PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(\c type, + * \c bits), where \c type and \c bits are the + * type and bit-size of \p private_key. * * The key permitted-algorithm policy is required * for keys that will be used for a cryptographic * operation. The key usage flags define what @@ -5068,7 +5068,7 @@ psa_status_t psa_key_agreement_iop_setup( * first. * * \param[out] key On success, an identifier for the newly created - * key, on failure this will be set to + * key. On failure this will be set to * #PSA_KEY_ID_NULL. * * \retval #PSA_SUCCESS From 9bcfd8981e6a0b0922f0d2d14fe588615aa1aa19 Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Thu, 1 Aug 2024 10:29:24 +0100 Subject: [PATCH 09/17] improve return codes and logic description Signed-off-by: Paul Elliott --- tf-psa-crypto/include/psa/crypto.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tf-psa-crypto/include/psa/crypto.h b/tf-psa-crypto/include/psa/crypto.h index 06ec304b13..8d89204237 100644 --- a/tf-psa-crypto/include/psa/crypto.h +++ b/tf-psa-crypto/include/psa/crypto.h @@ -4900,7 +4900,7 @@ uint32_t psa_key_agreement_iop_get_num_ops(psa_key_agreement_iop_t *operation); * on the same operation object after a successful * call to this function until \c * psa_key_agreement_iop_complete() either returns - * 0 or an error. + * #PSA_SUCCESS or an error. * \c psa_key_agreement_iop_complete() will return * #PSA_OPERATION_INCOMPLETE if there is more work * to do. Alternatively users can call @@ -5049,10 +5049,10 @@ psa_status_t psa_key_agreement_iop_setup( * maximum time spent in a function call. * * \note Users should call this function on the same - * operation object repeatedly until it either - * returns 0 or an error. This function will return - * #PSA_OPERATION_INCOMPLETE if there is more work - * to do. Alternatively users can call + * operation object repeatedly whilst it returns + * #PSA_OPERATION_INCOMPLETE, stopping when it + * returns either #PSA_SUCCESS or an error. + * Alternatively users can call * \c psa_key_agreement_iop_abort() at any point if * they no longer want the result. * From 8e412871c190733db1151d1d076695dc02ce108f Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Thu, 1 Aug 2024 11:34:07 +0100 Subject: [PATCH 10/17] Clarify ops used reset logic Signed-off-by: Paul Elliott --- tf-psa-crypto/include/psa/crypto.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tf-psa-crypto/include/psa/crypto.h b/tf-psa-crypto/include/psa/crypto.h index 8d89204237..69b438e146 100644 --- a/tf-psa-crypto/include/psa/crypto.h +++ b/tf-psa-crypto/include/psa/crypto.h @@ -4961,6 +4961,12 @@ uint32_t psa_key_agreement_iop_get_num_ops(psa_key_agreement_iop_t *operation); * calling `psa_get_key_attributes()` with * the key's identifier. * + * \note This function clears the number of ops completed + * as part of the operation. Please ensure you copy + * this value via + * \c psa_key_agreement_iop_get_num_ops() if + * required before calling. + * * \retval #PSA_SUCCESS * The operation started successfully - please call \c * psa_key_agreement_iop_complete() with the same context to complete @@ -5117,9 +5123,9 @@ psa_status_t psa_key_agreement_iop_complete( * at any point. It is not bound by the usual * interface stability promises. * - * \note This function is the only function that clears - * the number of ops completed as part of the - * operation. Please ensure you copy this value via + * \note This function clears the number of ops completed + * as part of the operation. Please ensure you copy + * this value via * \c psa_key_agreement_iop_get_num_ops() if * required before calling. * From 4b0b35e1d7f609d66eb6fac7970c1e548f59a60d Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Thu, 1 Aug 2024 11:37:17 +0100 Subject: [PATCH 11/17] Clarify PSA_ERROR_NOT_SUPPORTED error reasons Signed-off-by: Paul Elliott --- tf-psa-crypto/include/psa/crypto.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tf-psa-crypto/include/psa/crypto.h b/tf-psa-crypto/include/psa/crypto.h index 69b438e146..310cfc768d 100644 --- a/tf-psa-crypto/include/psa/crypto.h +++ b/tf-psa-crypto/include/psa/crypto.h @@ -5006,10 +5006,8 @@ uint32_t psa_key_agreement_iop_get_num_ops(psa_key_agreement_iop_t *operation); * * \retval #PSA_ERROR_NOT_SUPPORTED * The following conditions can result in this error: - * * \p alg is not supported or is not a key agreement algorithm. - * * \p private_key is not supported for use with \p alg. The output - * key attributes, as a whole, are not supported, either by the - * implementation in general or in the specified storage location. + * * \p alg is not supported. + * * \p private_key is not supported for use with \p alg. * * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription From 459448b8cf3876a496533307f7776a4dffb8269c Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Thu, 1 Aug 2024 11:50:16 +0100 Subject: [PATCH 12/17] Neaten 'Please call next function' docs. Signed-off-by: Paul Elliott --- tf-psa-crypto/include/psa/crypto.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tf-psa-crypto/include/psa/crypto.h b/tf-psa-crypto/include/psa/crypto.h index 310cfc768d..3260620c8c 100644 --- a/tf-psa-crypto/include/psa/crypto.h +++ b/tf-psa-crypto/include/psa/crypto.h @@ -4968,9 +4968,9 @@ uint32_t psa_key_agreement_iop_get_num_ops(psa_key_agreement_iop_t *operation); * required before calling. * * \retval #PSA_SUCCESS - * The operation started successfully - please call \c - * psa_key_agreement_iop_complete() with the same context to complete - * the operation. + * The operation started successfully. + * Call \c psa_key_agreement_iop_complete() with the same context to + * complete the operation. * * \retval #PSA_ERROR_BAD_STATE * Another operation has already been started on this context, and is From 5238475ac6c459dce281e15c568ee61d71ecff8d Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Thu, 1 Aug 2024 17:52:51 +0100 Subject: [PATCH 13/17] Update key attribute documentation inline with PSA Signed-off-by: Paul Elliott --- tf-psa-crypto/include/psa/crypto.h | 43 +++++++++++++++--------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/tf-psa-crypto/include/psa/crypto.h b/tf-psa-crypto/include/psa/crypto.h index 3260620c8c..f90ea4ca1d 100644 --- a/tf-psa-crypto/include/psa/crypto.h +++ b/tf-psa-crypto/include/psa/crypto.h @@ -4933,27 +4933,28 @@ uint32_t psa_key_agreement_iop_get_num_ops(psa_key_agreement_iop_t *operation); * #PSA_ALG_IS_KEY_AGREEMENT(\p alg) is true). * * \param[in] attributes The attributes for the new key. - * This function uses the attributes as follows: - * * The key type must be one of - * `PSA_KEY_TYPE_DERIVE`,`PSA_KEY_TYPE_RAW_DATA`, - * `PSA_KEY_TYPE_HMAC`, or - * `PSA_KEY_TYPE_PASSWORD`. - * * The size of the returned key is always the - * bit-size of the shared secret, rounded up to a - * whole number of bytes. The key size in \p - * attributes can be zero; if it is nonzero, - * it must be equal to the output size of the key - * agreement, in bits. - * * The output size, in bits, of the key agreement - * is #PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(\c type, - * \c bits), where \c type and \c bits are the - * type and bit-size of \p private_key. - * * The key permitted-algorithm policy is required - * for keys that will be used for a cryptographic - * operation. The key usage flags define what - * operations are permitted with the key. The key - * lifetime and identifier are required for a - * persistent key. + * The following attributes are required for all + * keys: + * * The key type, which must be one of + * #PSA_KEY_TYPE_DERIVE, #PSA_KEY_TYPE_RAW_DATA, + * #PSA_KEY_TYPE_HMAC or #PSA_KEY_TYPE_PASSWORD. + * The following attributes must be set for keys + * used in cryptographic operations: + * * The key permitted-algorithm policy + * * The key usage flags + * The following attributes must be set for keys + * that do not use the default volatile lifetime: + * * The key lifetime + * * The key identifier is required for a key with + * a persistent lifetime + * The following attributes are optional: + * * If the key size is nonzero, it must be equal + * to the output size of the key agreement, + * in bits. + * The output size, in bits, of the key agreement + * is 8 * #PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(\c + * type, \c bits), where \c type and \c bits are + * the type and bit-size of \p private_key. * * \note \p attributes is an input parameter, it is not * updated with the final key attributes. The final From 623c09a1ebe6f4e0f778f0607f887c62b14214b6 Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Thu, 1 Aug 2024 18:16:35 +0100 Subject: [PATCH 14/17] Change over to psa_raw_key_agreement psa_key_agreement exists, but only in the PSA spec, we have not implemented it, so refer to the one we actually implemented. Signed-off-by: Paul Elliott --- tf-psa-crypto/include/psa/crypto.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tf-psa-crypto/include/psa/crypto.h b/tf-psa-crypto/include/psa/crypto.h index f90ea4ca1d..17a39c345e 100644 --- a/tf-psa-crypto/include/psa/crypto.h +++ b/tf-psa-crypto/include/psa/crypto.h @@ -4889,7 +4889,7 @@ uint32_t psa_key_agreement_iop_get_num_ops(psa_key_agreement_iop_t *operation); * * \note This function combined with \c * psa_key_agreement_iop_complete() is equivalent - * to \c psa_key_agreement() but \c + * to \c psa_raw_key_agreement() but \c * psa_key_agreement_iop_complete() can return * early and resume according to the limit set with * \c psa_interruptible_set_max_ops() to reduce the @@ -5047,7 +5047,7 @@ psa_status_t psa_key_agreement_iop_setup( * * \note This function combined with \c * psa_key_agreement_iop_setup() is equivalent to - * \c psa_key_agreement() but this + * \c psa_raw_key_agreement() but this * function can return early and resume according * to the limit set with \c * psa_interruptible_set_max_ops() to reduce the From 327da4774b040695e26be990c60a48000afb70f3 Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Thu, 1 Aug 2024 18:21:13 +0100 Subject: [PATCH 15/17] Clarify key type support Signed-off-by: Paul Elliott --- tf-psa-crypto/include/psa/crypto.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tf-psa-crypto/include/psa/crypto.h b/tf-psa-crypto/include/psa/crypto.h index 17a39c345e..e5c148dd87 100644 --- a/tf-psa-crypto/include/psa/crypto.h +++ b/tf-psa-crypto/include/psa/crypto.h @@ -5009,6 +5009,8 @@ uint32_t psa_key_agreement_iop_get_num_ops(psa_key_agreement_iop_t *operation); * The following conditions can result in this error: * * \p alg is not supported. * * \p private_key is not supported for use with \p alg. + * * Only elliptic curve Diffie-Hellman with ECC keys is supported, not + * finite field Diffie_hellman with DH keys. * * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription From e50edc0d954465449be0cde8a0b5a6d37bf6c618 Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Thu, 1 Aug 2024 18:28:07 +0100 Subject: [PATCH 16/17] Add warning about not using keys directly Keys that are the result of key agreement have biases and really should not be used directly. Warning taken in part from psa_raw_key_agreement() Signed-off-by: Paul Elliott --- tf-psa-crypto/include/psa/crypto.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tf-psa-crypto/include/psa/crypto.h b/tf-psa-crypto/include/psa/crypto.h index e5c148dd87..e840a40cde 100644 --- a/tf-psa-crypto/include/psa/crypto.h +++ b/tf-psa-crypto/include/psa/crypto.h @@ -4887,6 +4887,12 @@ uint32_t psa_key_agreement_iop_get_num_ops(psa_key_agreement_iop_t *operation); * at any point. It is not bound by the usual * interface stability promises. * + * \warning The raw result of a key agreement algorithm such + * 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. + * * \note This function combined with \c * psa_key_agreement_iop_complete() is equivalent * to \c psa_raw_key_agreement() but \c From 26561b71222e9e333a52481f63ebba7af7966ae0 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 5 Aug 2024 11:22:12 +0100 Subject: [PATCH 17/17] Fix typos Signed-off-by: Janos Follath --- tf-psa-crypto/include/psa/crypto.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tf-psa-crypto/include/psa/crypto.h b/tf-psa-crypto/include/psa/crypto.h index e840a40cde..bc758e644d 100644 --- a/tf-psa-crypto/include/psa/crypto.h +++ b/tf-psa-crypto/include/psa/crypto.h @@ -5016,7 +5016,7 @@ uint32_t psa_key_agreement_iop_get_num_ops(psa_key_agreement_iop_t *operation); * * \p alg is not supported. * * \p private_key is not supported for use with \p alg. * * Only elliptic curve Diffie-Hellman with ECC keys is supported, not - * finite field Diffie_hellman with DH keys. + * finite field Diffie-Hellman with DH keys. * * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription @@ -5062,7 +5062,7 @@ psa_status_t psa_key_agreement_iop_setup( * maximum time spent in a function call. * * \note Users should call this function on the same - * operation object repeatedly whilst it returns + * operation object repeatedly while it returns * #PSA_OPERATION_INCOMPLETE, stopping when it * returns either #PSA_SUCCESS or an error. * Alternatively users can call