From 5e5dcaced3276417a8fd25f9023b0c34e3577eeb Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Sat, 20 Mar 2021 14:35:20 +0000 Subject: [PATCH 01/69] PSA PAKE: Add function declarations Add function declarations for the draft version of PSA Crypto API PAKE interface. Signed-off-by: Janos Follath --- include/psa/crypto.h | 359 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 359 insertions(+) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 6aa7ccc92..0992a6510 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4126,6 +4126,365 @@ psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, /**@}*/ + +/** \defgroup Password-authenticated key agreement + * @{ + */ + +/** The type of the state data structure for PAKE operations. + * + * Before calling any function on a PAKE operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_pake_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_pake_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_PAKE_OPERATION_INIT, + * for example: + * \code + * psa_pake_operation_t operation = PSA_PAKE_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_pake_operation_init() + * to the structure, for example: + * \code + * psa_pake_operation_t operation; + * operation = psa_pake_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_pake_operation_s psa_pake_operation_t; + +/** \def PSA_PAKE_OPERATION_INIT + * + * This macro returns a suitable initializer for an PAKE operation object of + * type #psa_pake_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_PAKE_OPERATION_INIT {0} +#endif + +/** Return an initial value for an PAKE operation object. + */ +static psa_pake_operation_t psa_pake_operation_init(void); + +/** Set the session information for a password-authenticated key exchange. + * + * The sequence of operations to set up a password-authenticated key exchange + * 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_pake_operation_t, e.g. + * #PSA_PAKE_OPERATION_INIT. + * -# Call psa_pake_setup() to specify the algorithm, the key, cipher suite, + * identities and additional session information. + * + * A typical sequence of calls to perform a password-authenticated key + * exchange: + * -# Call psa_pake_get_key_share() to get the key share that needs to be sent + * to the peer. + * -# Call psa_pake_set_key_share() to provide the key share that was received + * from the peer. + * -# Call psa_pake_get_implicit_key() for accessing the shared secret. + * + * The exact sequence of calls to perform a password-authenticated key exchange + * depends on the protocol in use: + * -# Some protocols exchange more data than just a single key share. When using + * such a protocol, call psa_pake_output() and psa_pake_input() one or more + * times to exchange any further data that is needed to derive the shared + * secret. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * If an error occurs at any step after a call to psa_pake_setup(), + * the operation will need to be reset by a call to psa_pake_abort(). The + * application may call psa_pake_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_pake_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A call to psa_pake_abort(). + * - A successful call to psa_pake_get_implicit_key(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_pake_operation_t and not yet in use. + * \param password Identifier of the key holding the password or a + * value derived from the password (eg. by a + * memory-hard function). It must remain valid + * until the operation terminates. It must allow + * the usage #PSA_KEY_USAGE_PAKE. + * \param alg The PAKE protocol to use + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_PAKE(\p alg) is true). + * \param cipher_suite The cipher suite to use with the PAKE algorithm. + * \param[in] user_id The user ID to authenticate with. + * \param user_id_length Size of the \p user_id buffer in bytes. + * \param[in] peer_id The peer's ID to authenticate. + * \param peer_id_length Size of the \p peer_id buffer in bytes. + * \param[in] session_data Additional session related data if it is allowed + * or required by the protocol. This must be empty + * if additional session data is not used by the + * protocol. + * \param session_data_length Size of the \p session_data buffer in bytes. + * + * \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 key is not compatible with \p alg. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p session_data is not empty and is not allowed in \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p cipher_suite is not compatible with \p alg. (Eg. \p cipher_suite + * mandates algorithms or sets options that do not make sense for \p alg + * or are not supported with \p alg.) + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a PAKE 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_pake_setup(psa_pake_operation_t *operation, + mbedtls_svc_key_id_t password, + psa_algorithm_t alg, + psa_pake_cipher_suite_t cipher_suite, + psa_pake_side_t side, + const uint8_t *user_id, + size_t user_id_len, + const uint8_t *peer_id, + size_t peer_id_len, + const uint8_t *session_data, + size_t session_data_len); + +/** Get the key share from a password-authenticated key exchange operation. + * + * This function returns a simple key share (eg. group element). + * + * The exact sequence of calls to perform a password-authenticated key + * exchange depends on the protocol in use. Refer to the documentation of + * individual PAKE algorithm types (`PSA_ALG_XXX` values of type + * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more + * information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_pake_abort(). + * + * \param[in,out] operation Active PAKE operation. + * \param[out] key_share Buffer where the key share is to be written. + * \param key_share_size Size of the \p key_share buffer in bytes. + * \param[out] key_share_length On success, the number of bytes of the + * returned key_share. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, but beyond that + * validity is specific to the protocol). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p key_share 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_pake_get_key_share(psa_pake_operation_t *operation, + uint8_t *key_share, + size_t key_share_size, + size_t *key_share_length); + +/** Get additional key share from a password-authenticated key exchange. + * + * Depending on the protocol being executed, you might need to call this + * function several times or you might not need to call this at all. + * + * The exact sequence of calls to perform a password-authenticated key + * exchange depends on the protocol in use. Refer to the documentation of + * individual PAKE algorithm types (`PSA_ALG_XXX` values of type + * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more + * information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_pake_abort(). + * + * \param[in,out] operation Active PAKE operation. + * \param type The type of the data that is requested. + * \param[out] output Buffer where the output 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 of the returned + * output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, but beyond that + * validity is specific to the protocol). + * \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_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_pake_output(psa_pake_operation_t *operation, + psa_pake_data_t type, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Provide peer key share to a password-authenticated key exchange operation. + * + * This function inputs a simple key share (eg. group element). + * + * The exact sequence of calls to perform a password-authenticated key + * exchange depends on the protocol in use. Refer to the documentation of + * individual PAKE algorithm types (`PSA_ALG_XXX` values of type + * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more + * information. + * + * \param[in,out] operation Active PAKE operation. + * \param[in] key_share Buffer containing the peer's key share. + * \param key_share_length Size of the \p key_share buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, but beyond that + * validity is specific to the protocol). + * \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_pake_set_key_share(psa_pake_operation_t *operation, + const uint8_t *key_share, + size_t key_share_length); + +/** Provide additional peer key share for a password-authenticated key exchange. + * + * Depending on the protocol being executed, you might need to call this + * function several times or you might not need to call this at all. + * + * The exact sequence of calls to perform a password-authenticated key + * exchange depends on the protocol in use. Refer to the documentation of + * individual PAKE algorithm types (`PSA_ALG_XXX` values of type + * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more + * information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_pake_abort(). + * + * \param[in,out] operation Active PAKE operation. + * \param type The type of the data provided. + * \param[out] input Buffer containing the input. + * \param[out] 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, but beyond that + * validity is specific to the protocol). + * \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_pake_input(psa_pake_operation_t *operation, + psa_pake_data_t type, + uint8_t *input, + size_t input_length); + +/** Get implicitly confirmed shared secret from a PAKE. + * + * This function can be called after the key exchange phase of the operation + * has completed. It imports the shared secret output of the PAKE into the + * provided derivation operation. The input step + * #PSA_KEY_DERIVATION_INPUT_SECRET is used when placing the shared key + * material in the key derivation operation. + * + * The exact sequence of calls to perform a password-authenticated key + * exchange depends on the protocol in use. Refer to the documentation of + * individual PAKE algorithm types (`PSA_ALG_XXX` values of type + * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more + * information. + * + * 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 psa_pake_abort(). + * + * \param[in,out] operation Active PAKE operation. + * \param[out] output A key derivation operation that has been + * initialized and set up. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, but beyond that + * validity is specific to the protocol). + * \retval #PSA_ERROR_BAD_STATE + * The state of \p output is not valid for + * the #PSA_KEY_DERIVATION_INPUT_SECRET step. This can happen if the + * step is out of order or the application has done this step already + * and it may not be repeated. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * #PSA_KEY_DERIVATION_INPUT_SECRET is not compatible with the output’s + * 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_pake_get_implicit_key(psa_pake_operation_t *operation, + psa_key_derivation_operation_t *output); +/**@}*/ + #ifdef __cplusplus } #endif From b86273a6dc60a450a21841b2b9dc7c825619773a Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Sat, 20 Mar 2021 14:58:52 +0000 Subject: [PATCH 02/69] PSA PAKE: Add integral types Add integral types for the draft version of PSA Crypto API PAKE interface. Signed-off-by: Janos Follath --- include/psa/crypto_types.h | 11 +++++++++++ include/psa/crypto_values.h | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h index 386c7d794..cd8ac4b1c 100644 --- a/include/psa/crypto_types.h +++ b/include/psa/crypto_types.h @@ -380,4 +380,15 @@ typedef uint16_t psa_key_derivation_step_t; /**@}*/ +/** \defgroup pake Password-authenticated key exchange + * @{ + */ + +/** \brief Encoding of the side of PAKE */ +typedef uint16_t psa_pake_side_t; + +/** \brief Encoding of the type of input/output for PAKE */ +typedef uint16_t psa_pake_data_t; + +/**@}*/ #endif /* PSA_CRYPTO_TYPES_H */ diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 497bd8f01..3c2b7bec2 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -2381,4 +2381,38 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) /**@}*/ +/** \defgroup pake Password-authenticated key exchange + * @{ + */ + +/** The first peer in a balanced PAKE. + * + * Although balanced PAKE protocols are symmetric, some of them needs an + * ordering of peers for the transcript calculations. If the protocol does not + * need this, either #PSA_PAKE_SIDE_FIRST or #PSA_PAKE_SIDE_SECOND are + * accepted. + */ +#define PSA_PAKE_SIDE_FIRST ((psa_pake_side_t)0x0001) + +/** The second peer in a balanced PAKE. + * + * Although balanced PAKE protocols are symmetric, some of them needs an + * ordering of peers for the transcript calculations. If the protocol does not + * need this, either #PSA_PAKE_SIDE_FIRST or #PSA_PAKE_SIDE_SECOND are + * accepted. + */ +#define PSA_PAKE_SIDE_SECOND ((psa_pake_side_t)0x0002) + +/** The client in an augmented PAKE. + * + * Augmented PAKE protocols need to differentiate between client and server. + */ +#define PSA_PAKE_SIDE_CLIENT ((psa_pake_side_t)0x0101) + +/** The server in an augmented PAKE. + * + * Augmented PAKE protocols need to differentiate between client and server. + */ +#define PSA_PAKE_SIDE_SERVER ((psa_pake_side_t)0x0102) +/**@}*/ #endif /* PSA_CRYPTO_VALUES_H */ From 38a5d3564633f1e74aff0124f05d1f8e9895f74b Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Sun, 21 Mar 2021 07:01:53 +0000 Subject: [PATCH 03/69] PSA PAKE: Add type for representing primitives In most of the PAKEs the primitives are prime order groups, but some of them might need the ring structure or just are using completely different algebraic structures (eg. SRP or PQC schemes). Signed-off-by: Janos Follath --- include/psa/crypto_types.h | 22 ++++++++++++++++++++++ include/psa/crypto_values.h | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h index cd8ac4b1c..1c40f5bf7 100644 --- a/include/psa/crypto_types.h +++ b/include/psa/crypto_types.h @@ -390,5 +390,27 @@ typedef uint16_t psa_pake_side_t; /** \brief Encoding of the type of input/output for PAKE */ typedef uint16_t psa_pake_data_t; +/** Encoding of the type of the PAKE's primitive. + * + * Values defined by this standard will never be in the range 0x80-0xff. + * Vendors who define additional types must use an encoding in this range. + */ +typedef uint8_t psa_pake_primitive_type_t; + +/** Encoding of the bitsize for the PAKE's primitive. + * + * The type and family is not enough to identify the primitive to use in the + * PAKE, the implementation needs to know the bitsize too. + */ +typedef uint16_t psa_pake_bits_t; + +/** Encoding of the PAKE's primitive. + * + * In most of the PAKEs the primitives are prime order groups, but some of + * them might need the ring structure or just are using completely different + * algebraic structures (eg. SRP or PQC schemes). + */ +typedef uint32_t psa_pake_primitive_t; + /**@}*/ #endif /* PSA_CRYPTO_TYPES_H */ diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 3c2b7bec2..afdcaa9f6 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -2414,5 +2414,42 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * Augmented PAKE protocols need to differentiate between client and server. */ #define PSA_PAKE_SIDE_SERVER ((psa_pake_side_t)0x0102) + +/** The pake uses finite fields. + * + * The corresponding family type is ::psa_dh_family_t. In determining a + * specific curve in the family ::psa_pake_bits_t values are interpreted in the + * exact same way as ::psa_key_bits_t would. + */ +#define PSA_PAKE_PRIMITIVE_TYPE_FIELD ((psa_pake_primitive_type_t)0x01) + +/** The pake uses elliptic curves. + * + * The corresponding family type is ::psa_ecc_family_t. in determining a + * specific curve in the family ::psa_pake_bits_t values are interpreted in the + * exact same way as ::psa_key_bits_t would. + */ +#define PSA_PAKE_PRIMITIVE_TYPE_CURVE ((psa_pake_primitive_type_t)0x02) + +/** Construct a PAKE primitive from type, family and bitsize. + * + * \param type The type of the primitive + * (value of type ::psa_pake_primitive_type_t). + * \param family The family of the primitive + * (the type and interpretation of this parameter depends + * on \p type, for more information consult the + * documentation of individual ::psa_pake_primitive_type_t + * constants). + * \param bits The bitwise of the primitive + * (Value of type ::psa_pake_bits_t. The interpretation + * of this parameter depends on \p family, for more + * information consult the documentation of individual + * ::psa_pake_primitive_type_t constants). + * + * \return The constructed primitive value. + */ +#define PSA_PAKE_PRIMITIVE(type, family, bits) \ + ((psa_pake_primitive_t) (((type) << 24 | (persistence) << 16) | (bits))) + /**@}*/ #endif /* PSA_CRYPTO_VALUES_H */ From 508afeca67799a11631f68d8c45e846c7fc76dbc Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Sun, 21 Mar 2021 09:42:37 +0000 Subject: [PATCH 04/69] PSA PAKE: Add cipher suite structure PAKE protocols make use of a range of cryptographic schemes and primitives. Standards allow for several options to use for each of them. They call the combination of specific algorithms cipher suites, configurations or options. Cipher suites are represented by a separate data type for several reasons: 1. To allow for individual PAKE protocols to provide pre-defined cipher suites. 2. To organise cipher suites into a unit that can be handled separately from the operation context. The PAKE operation flow is already complex, will be even more so when key confirmation is added. Handling them separately should reduce the surface of the interface the application developer needs to pay attention at any given time. Signed-off-by: Janos Follath --- include/psa/crypto.h | 41 +++++++++++++++++++++++++++++++++++++ include/psa/crypto_struct.h | 33 +++++++++++++++++++++++++++++ include/psa/crypto_types.h | 10 ++++++++- 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 0992a6510..a0f5b135e 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4131,6 +4131,47 @@ psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, * @{ */ +/** The type of the data strucure for PAKE cipher suites. + * + * 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_pake_cipher_suite_s psa_pake_cipher_suite_t; + +/** Construct a cipher suite for a password-authenticated key exchange. + * + * \param primitive The primitive used in the cipher suite. + * \param hash The hash involved in the cipher suite. + * (`PSA_ALG_XXX` values of type ::psa_algorithm_t + * such that #PSA_ALG_IS_HASH(\c alg) is true.) + * \param algorithm1 Additional algorithm if needed in the cipher suite, + * 0 otherwise. + * \param bits1 A bit size qualifier if needed for \p algorithm1, + * 0 otherwise. + * \param algorithm2 Additional algorithm if needed in the cipher suite, + * 0 otherwise. + * \param bits2 A bit size qualifier if needed for \p algorithm2, + * 0 otherwise. + * \param options Additional options to be included with the cipher + * suite if needed, 0 otherwise. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \retval The constructed cipher suite. + */ +static psa_pake_cipher_suite_t psa_pake_cipher_suite( + psa_pake_primitive_t primitive, + psa_algorithm_t hash, + psa_algorithm_t algorithm1, + psa_pake_bits_t bits1, + psa_algorithm_t algorithm2, + psa_pake_bits_t bits2, + psa_pake_cipher_suite_options_t options + ); + /** The type of the state data structure for PAKE operations. * * Before calling any function on a PAKE operation object, the application diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index 47012fdd0..a4e6cca8e 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -461,6 +461,39 @@ static inline size_t psa_get_key_bits( return( attributes->core.bits ); } +struct psa_pake_cipher_suite_s +{ + psa_pake_primitive_t primitive; + psa_algorithm_t hash; + psa_algorithm_t algorithm1; + psa_pake_bits_t bits1; + psa_algorithm_t algorithm2; + psa_pake_bits_t bits2; + psa_pake_cipher_suite_options_t options; +}; + +static inline struct psa_pake_cipher_suite_s psa_pake_cipher_suite( + psa_pake_primitive_t primitive, + psa_algorithm_t hash, + psa_algorithm_t algorithm1, + psa_pake_bits_t bits1, + psa_algorithm_t algorithm2, + psa_pake_bits_t bits2, + psa_pake_cipher_suite_options_t options + ) +{ + struct psa_pake_cipher_suite_s cipher_suite; + + cipher_suite.primitive = primitive; + cipher_suite.hash = hash; + cipher_suite.algorithm1 = algorithm1; + cipher_suite.bits1 = bits1; + cipher_suite.algorithm2 = algorithm2; + cipher_suite.bits2 = bits2; + cipher_suite.options = options; + + return cipher_suite; +} #ifdef __cplusplus } #endif diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h index 1c40f5bf7..8031c9d27 100644 --- a/include/psa/crypto_types.h +++ b/include/psa/crypto_types.h @@ -380,7 +380,7 @@ typedef uint16_t psa_key_derivation_step_t; /**@}*/ -/** \defgroup pake Password-authenticated key exchange +/** \defgroup pake Password-authenticated key exchange (PAKE) * @{ */ @@ -412,5 +412,13 @@ typedef uint16_t psa_pake_bits_t; */ typedef uint32_t psa_pake_primitive_t; +/** Encoding of additional options for PAKE. + * + * This type is for encoding additional options into PAKE cipher suites. + * (Options like for example EnvelopeMode in OPAQUE or "Per-User M and N" in + * SPAKE2.) + */ +typedef uint32_t psa_pake_cipher_suite_options_t; + /**@}*/ #endif /* PSA_CRYPTO_TYPES_H */ From 8a09ca9d94da0963e003b7f28ddfc48e5fff5359 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Sun, 21 Mar 2021 10:14:08 +0000 Subject: [PATCH 05/69] PSA PAKE: Add dummy operation context Signed-off-by: Janos Follath --- include/psa/crypto_struct.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index a4e6cca8e..f289caf16 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -494,6 +494,25 @@ static inline struct psa_pake_cipher_suite_s psa_pake_cipher_suite( return cipher_suite; } + +struct psa_pake_operation_s +{ + psa_algorithm_t alg; + union + { + /* Make the union non-empty even with no supported algorithms. */ + uint8_t dummy; + } ctx; +}; + +/* This only zeroes out the first byte in the union, the rest is unspecified. */ +#define PSA_PAKE_OPERATION_INIT {0, {0}} +static inline struct psa_pake_operation_s psa_pake_operation_init( void ) +{ + const struct psa_pake_operation_s v = PSA_PAKE_OPERATION_INIT; + return( v ); +} + #ifdef __cplusplus } #endif From 9c6b147d98fac6a12ea0be7337fb4c679432d2ae Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Sun, 21 Mar 2021 15:11:01 +0000 Subject: [PATCH 06/69] PSA PAKE: Add J-PAKE to the interface Signed-off-by: Janos Follath --- include/psa/crypto.h | 6 + include/psa/crypto_types.h | 9 +- include/psa/crypto_values.h | 185 +++++++++++++++++- .../test_suite_psa_crypto_metadata.data | 3 + .../test_suite_psa_crypto_metadata.function | 26 +++ 5 files changed, 217 insertions(+), 12 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index a0f5b135e..88cc2d149 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4366,6 +4366,9 @@ psa_status_t psa_pake_get_key_share(psa_pake_operation_t *operation, * Depending on the protocol being executed, you might need to call this * function several times or you might not need to call this at all. * + * Calling this function with PSA_PAKE_DATA_KEY_SHARE as \p type is equivalent + * to calling psa_pake_get_key_share(). + * * The exact sequence of calls to perform a password-authenticated key * exchange depends on the protocol in use. Refer to the documentation of * individual PAKE algorithm types (`PSA_ALG_XXX` values of type @@ -4443,6 +4446,9 @@ psa_status_t psa_pake_set_key_share(psa_pake_operation_t *operation, * Depending on the protocol being executed, you might need to call this * function several times or you might not need to call this at all. * + * Calling this function with PSA_PAKE_DATA_KEY_SHARE as \p type is equivalent + * to calling psa_pake_set_key_share(). + * * The exact sequence of calls to perform a password-authenticated key * exchange depends on the protocol in use. Refer to the documentation of * individual PAKE algorithm types (`PSA_ALG_XXX` values of type diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h index 8031c9d27..4fa739547 100644 --- a/include/psa/crypto_types.h +++ b/include/psa/crypto_types.h @@ -387,8 +387,13 @@ typedef uint16_t psa_key_derivation_step_t; /** \brief Encoding of the side of PAKE */ typedef uint16_t psa_pake_side_t; -/** \brief Encoding of the type of input/output for PAKE */ -typedef uint16_t psa_pake_data_t; +/** Encoding of input and output indicators for PAKE. + * + * Some PAKE protocols need to exchange more data than just a single key share. + * This type is for encoding additional input and output data for such + * protocols. + */ +typedef uint8_t psa_pake_data_t; /** Encoding of the type of the PAKE's primitive. * diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index afdcaa9f6..be3325890 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -731,6 +731,7 @@ #define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x07000000) #define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x08000000) #define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x09000000) +#define PSA_ALG_CATEGORY_PAKE ((psa_algorithm_t)0x0a000000) /** Whether an algorithm is vendor-defined. * @@ -848,6 +849,18 @@ (PSA_ALG_IS_KEY_DERIVATION(alg) && \ (alg) & PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG) +/** Whether the specified algorithm is a password-authenticated key exchange. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a password-authenticated key exchange (PAKE) + * algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_PAKE(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_PAKE) + #define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) /** MD2 */ #define PSA_ALG_MD2 ((psa_algorithm_t)0x02000001) @@ -1953,6 +1966,58 @@ #define PSA_ALG_GET_HASH(alg) \ (((alg) & 0x000000ff) == 0 ? ((psa_algorithm_t)0) : 0x02000000 | ((alg) & 0x000000ff)) +/** The Password-authenticated key exchange by juggling (J-PAKE) protocol. + * + * J-PAKE can be instantiated over finite fields or elliptic curves. This can + * be achieved by passing either #PSA_PAKE_PRIMITIVE_TYPE_FIELD or + * #PSA_PAKE_PRIMITIVE_TYPE_CURVE to #PSA_PAKE_PRIMITIVE respectively, when + * creating the cipher suite. + * + * In theory the protocol works with any non-interactive zero-knowledge proof. + * Implementations of the present specification use Schnorr NIZK and this does + * not need to be configured in the cipher suites. + * + * J-PAKE can be used with any secure cryptographic hash function, the choice + * of hash must be supplied to the psa_pake_cipher_suite() as the second + * parameter (\p hash). + * + * All the remaining parameters passed to psa_pake_cipher_suite() when creating + * the cipher suite must be 0. + * + * The key exchange flow for JPAKE is as follows: + * -# To get the first round data that needs to be sent to the peer, call + * psa_pake_get_key_share(operation, ...); + * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PUBLIC, ...); + * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); + * psa_pake_output(operation, #PSA_PAKE_DATA_KEY_SHARE_2, ...); + * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PUBLIC_2, ...); + * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PROOF_2, ...); + * -# To provide the first round data received from the peer to the operation, + * call + * psa_pake_set_key_share(operation, ...); + * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PUBLIC, ...); + * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); + * psa_pake_input(operation, #PSA_PAKE_DATA_KEY_SHARE_2, ...); + * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PUBLIC_2, ...); + * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PROOF_2, ...); + * -# To get the second round data that needs to be sent to the peer, call + * psa_pake_output(operation, #PSA_PAKE_DATA_KEY_SHARE_3, ...); + * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PUBLIC_3, ...); + * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PROOF_3, ...); + * -# To provide the second round data received from the peer to the operation, + * call + * psa_pake_input(operation, #PSA_PAKE_DATA_KEY_SHARE_3, ...); + * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PUBLIC_3, ...); + * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PROOF_3, ...); + * -# Call psa_pake_get_implicit_key() for accessing the shared secret. + * + * For more information consult the documentation of the individual + * PSA_PAKE_DATA_XXX constants. + * + * J-PAKE is standardised for example in RFC 8236 and in THREAD. + */ +#define PSA_ALG_PAKE_JPAKE ((psa_algorithm_t)0x0a000001) + /**@}*/ /** \defgroup key_lifetimes Key lifetimes @@ -2415,21 +2480,39 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) */ #define PSA_PAKE_SIDE_SERVER ((psa_pake_side_t)0x0102) -/** The pake uses finite fields. - * - * The corresponding family type is ::psa_dh_family_t. In determining a - * specific curve in the family ::psa_pake_bits_t values are interpreted in the - * exact same way as ::psa_key_bits_t would. - */ -#define PSA_PAKE_PRIMITIVE_TYPE_FIELD ((psa_pake_primitive_type_t)0x01) - -/** The pake uses elliptic curves. +/** The PAKE uses elliptic curves. * * The corresponding family type is ::psa_ecc_family_t. in determining a * specific curve in the family ::psa_pake_bits_t values are interpreted in the * exact same way as ::psa_key_bits_t would. + * + * Input and output during the operation can involve group elements and scalar + * values: + * -# The format for group elements is the same as for public keys on the + * specific curve would be. For more information, consult the documentation of + * psa_export_public_key(). + * -# The format for scalars is the same as for private keys on the specific + * curve would be. For more information, consult the documentation of + * psa_export_key(). */ -#define PSA_PAKE_PRIMITIVE_TYPE_CURVE ((psa_pake_primitive_type_t)0x02) +#define PSA_PAKE_PRIMITIVE_TYPE_CURVE ((psa_pake_primitive_type_t)0x01) + +/** The PAKE uses finite fields based Diffie-Hellman groups. + * + * The corresponding family type is ::psa_dh_family_t. In determining a + * specific group in the family ::psa_pake_bits_t values are interpreted in the + * exact same way as ::psa_key_bits_t would. + * + * Input and output during the operation can involve group elements and scalar + * values: + * -# The format for group elements is the same as for public keys on the + * specific group would be. For more information, consult the documentation of + * psa_export_public_key(). + * -# The format for scalars is the same as for private keys on the specific + * group would be. For more information, consult the documentation of + * psa_export_key(). + */ +#define PSA_PAKE_PRIMITIVE_TYPE_FIELD_DH ((psa_pake_primitive_type_t)0x02) /** Construct a PAKE primitive from type, family and bitsize. * @@ -2451,5 +2534,87 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) #define PSA_PAKE_PRIMITIVE(type, family, bits) \ ((psa_pake_primitive_t) (((type) << 24 | (persistence) << 16) | (bits))) + +/** The key share being sent to or received from the peer. + * + * Unless the documentation of the PAKE algorithm says otherwise this is a + * group element. + * + * For information regarding representation consult the documentation of + * individual ::psa_pake_primitive_type_t constants. + * + * Some PAKE protocols need to exchange several key shares. If that is the + * case, this value marks the first key share sent and the first key share + * received. For values sent or received afterwards, use + * #PSA_PAKE_DATA_KEY_SHARE_2 and #PSA_PAKE_DATA_KEY_SHARE_3. + */ +#define PSA_PAKE_DATA_KEY_SHARE ((psa_pake_data_t)0x01) + + +/** A Schnorr NIZKP public key. + * + * This is a group element. + * + * For information regarding representation consult the documentation of + * individual ::psa_pake_primitive_type_t constants. + * + * Some PAKE protocols need to perform several zero-knowledge proofs. If that + * is the case, this value marks the first public key sent and the first public + * key received. For values sent or received afterwards, use + * #PSA_PAKE_DATA_ZK_PUBLIC_2 and #PSA_PAKE_DATA_ZK_PUBLIC_3. + */ +#define PSA_PAKE_DATA_ZK_PUBLIC ((psa_pake_data_t)0x02) + + +/** A Schnorr NIZKP proof. + * + * This is a skalar value. + * + * For information regarding representation consult the documentation of + * individual ::psa_pake_primitive_type_t constants. + * + * Some PAKE protocols need to perform several zero-knowledge proofs. If that + * is the case, this value marks the first proof sent and the first proof + * received. For values sent or received afterwards, use + * #PSA_PAKE_DATA_ZK_PROOF_2 and #PSA_PAKE_DATA_ZK_PROOF_3. + */ +#define PSA_PAKE_DATA_ZK_PROOF ((psa_pake_data_t)0x03) + +/** Marks the second key share sent and received. + * + * See #PSA_PAKE_DATA_KEY_SHARE. + */ +#define PSA_PAKE_DATA_KEY_SHARE_2 ((psa_pake_data_t)0x04) + +/** Marks the second Schnorr NIZKP public key sent and received. + * + * See #PSA_PAKE_DATA_ZK_PUBLIC. + */ +#define PSA_PAKE_DATA_ZK_PUBLIC_2 ((psa_pake_data_t)0x05) + +/** Marks the second Schnorr NIZKP proof sent and received. + * + * See #PSA_PAKE_DATA_ZK_PROOF. + */ +#define PSA_PAKE_DATA_ZK_PROOF_2 ((psa_pake_data_t)0x06) + +/** Marks the third key share sent and received. + * + * See #PSA_PAKE_DATA_KEY_SHARE. + */ +#define PSA_PAKE_DATA_KEY_SHARE_3 ((psa_pake_data_t)0x07) + +/** Marks the third Schnorr NIZKP public key sent and received. + * + * See #PSA_PAKE_DATA_ZK_PUBLIC. + */ +#define PSA_PAKE_DATA_ZK_PUBLIC_3 ((psa_pake_data_t)0x08) + +/** Marks the third Schnorr NIZKP proof sent and received. + * + * See #PSA_PAKE_DATA_ZK_PROOF. + */ +#define PSA_PAKE_DATA_ZK_PROOF_3 ((psa_pake_data_t)0x09) + /**@}*/ #endif /* PSA_CRYPTO_VALUES_H */ diff --git a/tests/suites/test_suite_psa_crypto_metadata.data b/tests/suites/test_suite_psa_crypto_metadata.data index 4e2f4d5af..0845b55d7 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.data +++ b/tests/suites/test_suite_psa_crypto_metadata.data @@ -294,6 +294,9 @@ Key agreement: ECDH, HKDF using SHA-384 depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_384 key_agreement_algorithm:PSA_ALG_KEY_AGREEMENT( PSA_ALG_ECDH, PSA_ALG_HKDF( PSA_ALG_SHA_384 ) ):ALG_IS_ECDH:PSA_ALG_ECDH:PSA_ALG_HKDF( PSA_ALG_SHA_384 ) +PAKE: J-PAKE +pake_algorithm:PSA_ALG_PAKE_JPAKE + Key type: raw data key_type:PSA_KEY_TYPE_RAW_DATA:KEY_TYPE_IS_UNSTRUCTURED diff --git a/tests/suites/test_suite_psa_crypto_metadata.function b/tests/suites/test_suite_psa_crypto_metadata.function index 8134f4471..3ed08a6a0 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.function +++ b/tests/suites/test_suite_psa_crypto_metadata.function @@ -156,6 +156,7 @@ void mac_algorithm_core( psa_algorithm_t alg, int classification_flags, TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_PAKE( alg ) ); algorithm_classification( alg, classification_flags ); /* Length */ @@ -181,6 +182,7 @@ void aead_algorithm_core( psa_algorithm_t alg, int classification_flags, TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_PAKE( alg ) ); algorithm_classification( alg, classification_flags ); /* Tag length */ @@ -220,6 +222,7 @@ void hash_algorithm( int alg_arg, int length_arg ) TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_PAKE( alg ) ); algorithm_classification( alg, 0 ); /* Dependent algorithms */ @@ -362,6 +365,7 @@ void cipher_algorithm( int alg_arg, int classification_flags ) TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_PAKE( alg ) ); algorithm_classification( alg, classification_flags ); } /* END_CASE */ @@ -462,6 +466,7 @@ void asymmetric_signature_algorithm( int alg_arg, int classification_flags ) TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_PAKE( alg ) ); algorithm_classification( alg, classification_flags ); } /* END_CASE */ @@ -491,6 +496,7 @@ void asymmetric_encryption_algorithm( int alg_arg, int classification_flags ) TEST_ASSERT( PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_PAKE( alg ) ); algorithm_classification( alg, classification_flags ); } /* END_CASE */ @@ -511,6 +517,7 @@ void key_derivation_algorithm( int alg_arg, int classification_flags ) TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ); TEST_ASSERT( PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_PAKE( alg ) ); algorithm_classification( alg, classification_flags ); /* Check combinations with key agreements */ @@ -540,6 +547,7 @@ void key_agreement_algorithm( int alg_arg, int classification_flags, TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); TEST_ASSERT( PSA_ALG_IS_KEY_AGREEMENT( alg ) ); TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_PAKE( alg ) ); algorithm_classification( alg, classification_flags ); /* Shared secret derivation properties */ @@ -548,6 +556,24 @@ void key_agreement_algorithm( int alg_arg, int classification_flags, } /* END_CASE */ +/* BEGIN_CASE */ +void pake_algorithm( int alg_arg ) +{ + psa_algorithm_t alg = alg_arg; + + /* Algorithm classification */ + TEST_ASSERT( ! PSA_ALG_IS_HASH( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_MAC( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_CIPHER( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_AEAD( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_SIGN( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ); + TEST_ASSERT( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ); + TEST_ASSERT( PSA_ALG_IS_PAKE( alg ) ); +} + +/* END_CASE */ /* BEGIN_CASE */ void key_type( int type_arg, int classification_flags ) { From b378d5784021405fb9801eed17a81714798532ae Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 8 Apr 2021 13:53:12 +0100 Subject: [PATCH 07/69] PSA PAKE: add output size macros Signed-off-by: Janos Follath --- include/psa/crypto_sizes.h | 50 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index 79f96739b..8497b14d0 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -1132,4 +1132,54 @@ #define PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE \ (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE) +/** A sufficient output buffer size for psa_pake_get_key_share(). + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_pake_get_key_share() will not fail due to an + * insufficient ciphertext buffer size. The actual size of the output might be + * smaller in any given call. + * + * See also #PSA_PAKE_OUTPUT_MAX_SIZE + * + * \param alg A PAKE algorithm (PSA_ALG_XXX value such that + * #PSA_ALG_IS_PAKE(\p alg) is true). + * \param cipher_suite A cipher suite that is compatible with algorithm \p alg. + * \return A sufficient key share buffer size for the specified + * cipher suite and algorithm. If the cipher suite or PAKE + * algorithm is not recognized, or the parameters are + * incompatible, return 0. + */ +#define PSA_PAKE_KEY_SHARE_SIZE(alg, cipher_suite) \ + (PSA_PAKE_OUTPUT_SIZE(alg, cipher_suite, PSA_PAKE_DATA_KEY_SHARE) + +/** A sufficient output buffer size for psa_pake_output(). + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_pake_output() will not fail due to an + * insufficient ciphertext buffer size. The actual size of the output might be + * smaller in any given call. + * + * See also #PSA_PAKE_OUTPUT_MAX_SIZE + * + * \param alg A PAKE algorithm (PSA_ALG_XXX value such that + * #PSA_ALG_IS_PAKE(\p alg) is true). + * \param cipher_suite A cipher suite that is compatible with algorithm \p alg. + * \param output An output type used with algorithm \p alg. + * \return A sufficient output buffer size for the specified + * output, cipher suite and algorithm. If the cipher suite, + * the output type or PAKE algorithm is not recognized, or + * the parameters are incompatible, return 0. + */ +#define PSA_PAKE_OUTPUT_SIZE(alg, cipher_suite, output) + +/** Output buffer size for psa_pake_output() and psa_pake_get_key_share(), + * for any of the supported cipher suites and PAKE algorithms. + * + * This macro must expand to a compile-time constant integer. + * + * See also #PSA_PAKE_KEY_SHARE_SIZE(\p alg, \p cipher_suite) and + * #PSA_PAKE_OUTPUT_SIZE(\p alg, \p cipher_suite, \p output). + */ +#define PSA_PAKE_OUTPUT_MAX_SIZE + #endif /* PSA_CRYPTO_SIZES_H */ From 7f1e81a98dd783edf1d572883d11e2de5ffd9bce Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 8 Apr 2021 14:20:55 +0100 Subject: [PATCH 08/69] PSA PAKE: specify key type and usage The PSA_KEY_TYPE_PASSWORD key type to which this documentation change refers to is not yet present in the code and will be introduced by a parallel line of work. Signed-off-by: Janos Follath --- include/psa/crypto.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 88cc2d149..79d997672 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4266,8 +4266,10 @@ static psa_pake_operation_t psa_pake_operation_init(void); * \param password Identifier of the key holding the password or a * value derived from the password (eg. by a * memory-hard function). It must remain valid - * until the operation terminates. It must allow - * the usage #PSA_KEY_USAGE_PAKE. + * until the operation terminates. It must be of + * type #PSA_KEY_TYPE_PASSWORD or + * #PSA_KEY_TYPE_DERIVE. It has to allow the usage + * #PSA_KEY_USAGE_DERIVE. * \param alg The PAKE protocol to use * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_PAKE(\p alg) is true). From ca2c167dcbb1e46c904f32fb24c219c16a7e64ab Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 12 Apr 2021 10:00:43 +0100 Subject: [PATCH 09/69] PSA PAKE: fix doxygen warnings Signed-off-by: Janos Follath --- include/psa/crypto.h | 12 ++++++++---- include/psa/crypto_types.h | 6 +++++- include/psa/crypto_values.h | 4 ++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 79d997672..8bc92e1f6 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4267,22 +4267,26 @@ static psa_pake_operation_t psa_pake_operation_init(void); * value derived from the password (eg. by a * memory-hard function). It must remain valid * until the operation terminates. It must be of - * type #PSA_KEY_TYPE_PASSWORD or + * type PSA_KEY_TYPE_PASSWORD or * #PSA_KEY_TYPE_DERIVE. It has to allow the usage * #PSA_KEY_USAGE_DERIVE. * \param alg The PAKE protocol to use * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_PAKE(\p alg) is true). * \param cipher_suite The cipher suite to use with the PAKE algorithm. + * \param side A value of type ::psa_pake_side_t signaling the + * side of the protocol that is being set up. For + * more information see the documentation of \c + * PSA_PAKE_SIDE_XXX constants. * \param[in] user_id The user ID to authenticate with. - * \param user_id_length Size of the \p user_id buffer in bytes. + * \param user_id_len Size of the \p user_id buffer in bytes. * \param[in] peer_id The peer's ID to authenticate. - * \param peer_id_length Size of the \p peer_id buffer in bytes. + * \param peer_id_len Size of the \p peer_id buffer in bytes. * \param[in] session_data Additional session related data if it is allowed * or required by the protocol. This must be empty * if additional session data is not used by the * protocol. - * \param session_data_length Size of the \p session_data buffer in bytes. + * \param session_data_len Size of the \p session_data buffer in bytes. * * \retval #PSA_SUCCESS * Success. diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h index 4fa739547..e434e01e3 100644 --- a/include/psa/crypto_types.h +++ b/include/psa/crypto_types.h @@ -384,7 +384,11 @@ typedef uint16_t psa_key_derivation_step_t; * @{ */ -/** \brief Encoding of the side of PAKE */ +/** \brief Encoding of the side of PAKE + * + * Encodes which side of the protocol is being executed. For more information + * see the documentation of individual PSA_PAKE_SIDE_XXX constants. + */ typedef uint16_t psa_pake_side_t; /** Encoding of input and output indicators for PAKE. diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index be3325890..3650fd772 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1969,7 +1969,7 @@ /** The Password-authenticated key exchange by juggling (J-PAKE) protocol. * * J-PAKE can be instantiated over finite fields or elliptic curves. This can - * be achieved by passing either #PSA_PAKE_PRIMITIVE_TYPE_FIELD or + * be achieved by passing either #PSA_PAKE_PRIMITIVE_TYPE_FIELD_DH or * #PSA_PAKE_PRIMITIVE_TYPE_CURVE to #PSA_PAKE_PRIMITIVE respectively, when * creating the cipher suite. * @@ -2446,7 +2446,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) /**@}*/ -/** \defgroup pake Password-authenticated key exchange +/** \defgroup pake Password-authenticated key exchange (PAKE) * @{ */ From 1101edb948fbe1e172eeb5a24233075e317b3b75 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 19 Apr 2021 09:34:44 +0100 Subject: [PATCH 10/69] PSA PAKE: typo fixes in documentation Also removes the mention of THREAD as we can't give a publicly available reference for it. Signed-off-by: Janos Follath --- include/psa/crypto_values.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 3650fd772..04b0303e8 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1974,7 +1974,7 @@ * creating the cipher suite. * * In theory the protocol works with any non-interactive zero-knowledge proof. - * Implementations of the present specification use Schnorr NIZK and this does + * Implementations of the present specification use Schnorr NIZKP and this does * not need to be configured in the cipher suites. * * J-PAKE can be used with any secure cryptographic hash function, the choice @@ -2014,7 +2014,7 @@ * For more information consult the documentation of the individual * PSA_PAKE_DATA_XXX constants. * - * J-PAKE is standardised for example in RFC 8236 and in THREAD. + * J-PAKE is standardised for example in RFC 8236. */ #define PSA_ALG_PAKE_JPAKE ((psa_algorithm_t)0x0a000001) @@ -2482,7 +2482,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) /** The PAKE uses elliptic curves. * - * The corresponding family type is ::psa_ecc_family_t. in determining a + * The corresponding family type is ::psa_ecc_family_t. In determining a * specific curve in the family ::psa_pake_bits_t values are interpreted in the * exact same way as ::psa_key_bits_t would. * @@ -2523,7 +2523,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * on \p type, for more information consult the * documentation of individual ::psa_pake_primitive_type_t * constants). - * \param bits The bitwise of the primitive + * \param bits The bitsize of the primitive * (Value of type ::psa_pake_bits_t. The interpretation * of this parameter depends on \p family, for more * information consult the documentation of individual @@ -2568,7 +2568,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) /** A Schnorr NIZKP proof. * - * This is a skalar value. + * This is a scalar value. * * For information regarding representation consult the documentation of * individual ::psa_pake_primitive_type_t constants. From 020da462d27b3a1de288a93a4ad0cee215eb46b7 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 19 Apr 2021 09:43:45 +0100 Subject: [PATCH 11/69] Fix PSA_PAKE_PRIMITIVE macro Fix the typo in the macro definition and more specific parameter names allow for future scripts to check validity of arguments. Signed-off-by: Janos Follath --- include/psa/crypto_values.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 04b0303e8..2d86136e0 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -2516,14 +2516,14 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) /** Construct a PAKE primitive from type, family and bitsize. * - * \param type The type of the primitive + * \param pake_type The type of the primitive * (value of type ::psa_pake_primitive_type_t). - * \param family The family of the primitive + * \param pake_family The family of the primitive * (the type and interpretation of this parameter depends * on \p type, for more information consult the * documentation of individual ::psa_pake_primitive_type_t * constants). - * \param bits The bitsize of the primitive + * \param pake_bits The bitsize of the primitive * (Value of type ::psa_pake_bits_t. The interpretation * of this parameter depends on \p family, for more * information consult the documentation of individual @@ -2531,8 +2531,9 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * * \return The constructed primitive value. */ -#define PSA_PAKE_PRIMITIVE(type, family, bits) \ - ((psa_pake_primitive_t) (((type) << 24 | (persistence) << 16) | (bits))) +#define PSA_PAKE_PRIMITIVE(pake_type, pake_family, pake_bits) \ + ((psa_pake_primitive_t) (((pake_type) << 24 | \ + (pake_family) << 16) | (pake_bits))) /** The key share being sent to or received from the peer. From fb4203dcffafeb5eb047373f9e550671673933b2 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 19 Apr 2021 09:53:17 +0100 Subject: [PATCH 12/69] PSA PAKE: Call the scheme algorithm The documentation is calling PAKEs protocols but it has an psa_algorithm_t identifier. To align the terminology, the documentation should call them algorithms as well. Signed-off-by: Janos Follath --- include/psa/crypto.h | 38 ++++++++++++++++++------------------- include/psa/crypto_types.h | 6 +++--- include/psa/crypto_values.h | 22 ++++++++++----------- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 8bc92e1f6..e6e78eb1c 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4239,9 +4239,9 @@ static psa_pake_operation_t psa_pake_operation_init(void); * -# Call psa_pake_get_implicit_key() for accessing the shared secret. * * The exact sequence of calls to perform a password-authenticated key exchange - * depends on the protocol in use: - * -# Some protocols exchange more data than just a single key share. When using - * such a protocol, call psa_pake_output() and psa_pake_input() one or more + * depends on the algorithm in use: + * -# Some algorithms exchange more data than just a single key share. When using + * such a algorithm, call psa_pake_output() and psa_pake_input() one or more * times to exchange any further data that is needed to derive the shared * secret. * @@ -4270,12 +4270,12 @@ static psa_pake_operation_t psa_pake_operation_init(void); * type PSA_KEY_TYPE_PASSWORD or * #PSA_KEY_TYPE_DERIVE. It has to allow the usage * #PSA_KEY_USAGE_DERIVE. - * \param alg The PAKE protocol to use + * \param alg The PAKE algorithm to use * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_PAKE(\p alg) is true). * \param cipher_suite The cipher suite to use with the PAKE algorithm. * \param side A value of type ::psa_pake_side_t signaling the - * side of the protocol that is being set up. For + * side of the algorithm that is being set up. For * more information see the documentation of \c * PSA_PAKE_SIDE_XXX constants. * \param[in] user_id The user ID to authenticate with. @@ -4283,9 +4283,9 @@ static psa_pake_operation_t psa_pake_operation_init(void); * \param[in] peer_id The peer's ID to authenticate. * \param peer_id_len Size of the \p peer_id buffer in bytes. * \param[in] session_data Additional session related data if it is allowed - * or required by the protocol. This must be empty + * or required by the algorithm. This must be empty * if additional session data is not used by the - * protocol. + * algorithm. * \param session_data_len Size of the \p session_data buffer in bytes. * * \retval #PSA_SUCCESS @@ -4331,7 +4331,7 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, * This function returns a simple key share (eg. group element). * * The exact sequence of calls to perform a password-authenticated key - * exchange depends on the protocol in use. Refer to the documentation of + * exchange depends on the algorithm in use. Refer to the documentation of * individual PAKE algorithm types (`PSA_ALG_XXX` values of type * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more * information. @@ -4349,7 +4349,7 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, * Success. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, but beyond that - * validity is specific to the protocol). + * validity is specific to the algorithm). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p key_share buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY @@ -4369,14 +4369,14 @@ psa_status_t psa_pake_get_key_share(psa_pake_operation_t *operation, /** Get additional key share from a password-authenticated key exchange. * - * Depending on the protocol being executed, you might need to call this + * Depending on the algorithm being executed, you might need to call this * function several times or you might not need to call this at all. * * Calling this function with PSA_PAKE_DATA_KEY_SHARE as \p type is equivalent * to calling psa_pake_get_key_share(). * * The exact sequence of calls to perform a password-authenticated key - * exchange depends on the protocol in use. Refer to the documentation of + * exchange depends on the algorithm in use. Refer to the documentation of * individual PAKE algorithm types (`PSA_ALG_XXX` values of type * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more * information. @@ -4395,7 +4395,7 @@ psa_status_t psa_pake_get_key_share(psa_pake_operation_t *operation, * Success. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, but beyond that - * validity is specific to the protocol). + * validity is specific to the algorithm). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY @@ -4419,7 +4419,7 @@ psa_status_t psa_pake_output(psa_pake_operation_t *operation, * This function inputs a simple key share (eg. group element). * * The exact sequence of calls to perform a password-authenticated key - * exchange depends on the protocol in use. Refer to the documentation of + * exchange depends on the algorithm in use. Refer to the documentation of * individual PAKE algorithm types (`PSA_ALG_XXX` values of type * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more * information. @@ -4432,7 +4432,7 @@ psa_status_t psa_pake_output(psa_pake_operation_t *operation, * Success. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, but beyond that - * validity is specific to the protocol). + * validity is specific to the algorithm). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE @@ -4449,14 +4449,14 @@ psa_status_t psa_pake_set_key_share(psa_pake_operation_t *operation, /** Provide additional peer key share for a password-authenticated key exchange. * - * Depending on the protocol being executed, you might need to call this + * Depending on the algorithm being executed, you might need to call this * function several times or you might not need to call this at all. * * Calling this function with PSA_PAKE_DATA_KEY_SHARE as \p type is equivalent * to calling psa_pake_set_key_share(). * * The exact sequence of calls to perform a password-authenticated key - * exchange depends on the protocol in use. Refer to the documentation of + * exchange depends on the algorithm in use. Refer to the documentation of * individual PAKE algorithm types (`PSA_ALG_XXX` values of type * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more * information. @@ -4473,7 +4473,7 @@ psa_status_t psa_pake_set_key_share(psa_pake_operation_t *operation, * Success. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, but beyond that - * validity is specific to the protocol). + * validity is specific to the algorithm). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE @@ -4498,7 +4498,7 @@ psa_status_t psa_pake_input(psa_pake_operation_t *operation, * material in the key derivation operation. * * The exact sequence of calls to perform a password-authenticated key - * exchange depends on the protocol in use. Refer to the documentation of + * exchange depends on the algorithm in use. Refer to the documentation of * individual PAKE algorithm types (`PSA_ALG_XXX` values of type * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more * information. @@ -4515,7 +4515,7 @@ psa_status_t psa_pake_input(psa_pake_operation_t *operation, * Success. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, but beyond that - * validity is specific to the protocol). + * validity is specific to the algorithm). * \retval #PSA_ERROR_BAD_STATE * The state of \p output is not valid for * the #PSA_KEY_DERIVATION_INPUT_SECRET step. This can happen if the diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h index e434e01e3..8635afd74 100644 --- a/include/psa/crypto_types.h +++ b/include/psa/crypto_types.h @@ -386,16 +386,16 @@ typedef uint16_t psa_key_derivation_step_t; /** \brief Encoding of the side of PAKE * - * Encodes which side of the protocol is being executed. For more information + * Encodes which side of the algorithm is being executed. For more information * see the documentation of individual PSA_PAKE_SIDE_XXX constants. */ typedef uint16_t psa_pake_side_t; /** Encoding of input and output indicators for PAKE. * - * Some PAKE protocols need to exchange more data than just a single key share. + * Some PAKE algorithms need to exchange more data than just a single key share. * This type is for encoding additional input and output data for such - * protocols. + * algorithms. */ typedef uint8_t psa_pake_data_t; diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 2d86136e0..4a6b06c76 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1966,14 +1966,14 @@ #define PSA_ALG_GET_HASH(alg) \ (((alg) & 0x000000ff) == 0 ? ((psa_algorithm_t)0) : 0x02000000 | ((alg) & 0x000000ff)) -/** The Password-authenticated key exchange by juggling (J-PAKE) protocol. +/** The Password-authenticated key exchange by juggling (J-PAKE) algorithm. * * J-PAKE can be instantiated over finite fields or elliptic curves. This can * be achieved by passing either #PSA_PAKE_PRIMITIVE_TYPE_FIELD_DH or * #PSA_PAKE_PRIMITIVE_TYPE_CURVE to #PSA_PAKE_PRIMITIVE respectively, when * creating the cipher suite. * - * In theory the protocol works with any non-interactive zero-knowledge proof. + * In theory the algorithm works with any non-interactive zero-knowledge proof. * Implementations of the present specification use Schnorr NIZKP and this does * not need to be configured in the cipher suites. * @@ -2452,8 +2452,8 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) /** The first peer in a balanced PAKE. * - * Although balanced PAKE protocols are symmetric, some of them needs an - * ordering of peers for the transcript calculations. If the protocol does not + * Although balanced PAKE algorithms are symmetric, some of them needs an + * ordering of peers for the transcript calculations. If the algorithm does not * need this, either #PSA_PAKE_SIDE_FIRST or #PSA_PAKE_SIDE_SECOND are * accepted. */ @@ -2461,8 +2461,8 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) /** The second peer in a balanced PAKE. * - * Although balanced PAKE protocols are symmetric, some of them needs an - * ordering of peers for the transcript calculations. If the protocol does not + * Although balanced PAKE algorithms are symmetric, some of them needs an + * ordering of peers for the transcript calculations. If the algorithm does not * need this, either #PSA_PAKE_SIDE_FIRST or #PSA_PAKE_SIDE_SECOND are * accepted. */ @@ -2470,13 +2470,13 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) /** The client in an augmented PAKE. * - * Augmented PAKE protocols need to differentiate between client and server. + * Augmented PAKE algorithms need to differentiate between client and server. */ #define PSA_PAKE_SIDE_CLIENT ((psa_pake_side_t)0x0101) /** The server in an augmented PAKE. * - * Augmented PAKE protocols need to differentiate between client and server. + * Augmented PAKE algorithms need to differentiate between client and server. */ #define PSA_PAKE_SIDE_SERVER ((psa_pake_side_t)0x0102) @@ -2544,7 +2544,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * For information regarding representation consult the documentation of * individual ::psa_pake_primitive_type_t constants. * - * Some PAKE protocols need to exchange several key shares. If that is the + * Some PAKE algorithms need to exchange several key shares. If that is the * case, this value marks the first key share sent and the first key share * received. For values sent or received afterwards, use * #PSA_PAKE_DATA_KEY_SHARE_2 and #PSA_PAKE_DATA_KEY_SHARE_3. @@ -2559,7 +2559,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * For information regarding representation consult the documentation of * individual ::psa_pake_primitive_type_t constants. * - * Some PAKE protocols need to perform several zero-knowledge proofs. If that + * Some PAKE algorithms need to perform several zero-knowledge proofs. If that * is the case, this value marks the first public key sent and the first public * key received. For values sent or received afterwards, use * #PSA_PAKE_DATA_ZK_PUBLIC_2 and #PSA_PAKE_DATA_ZK_PUBLIC_3. @@ -2574,7 +2574,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * For information regarding representation consult the documentation of * individual ::psa_pake_primitive_type_t constants. * - * Some PAKE protocols need to perform several zero-knowledge proofs. If that + * Some PAKE algorithms need to perform several zero-knowledge proofs. If that * is the case, this value marks the first proof sent and the first proof * received. For values sent or received afterwards, use * #PSA_PAKE_DATA_ZK_PROOF_2 and #PSA_PAKE_DATA_ZK_PROOF_3. From 7ebcbf34f99c62581f83c32e2dc294418c3af8cd Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 19 Apr 2021 13:57:13 +0100 Subject: [PATCH 13/69] Remove psa_pake_get/set_key_share() functions The main purpose of psa_pake_get_key_share() is to provide a more straightforward and convenient call flow for regular PAKEs. Most PAKEs have a single key share and need a flow like this: op=PSA_PAKE_OPERATION_INIT; psa_pake_setup(); psa_pake_get_key_share(); psa_pake_set_key_share(); psa_pake_get_implicit_key(); Adding psa_pake_get/set_key_share() functions cuts out the psa_pake_data_t constants from the users vision, hiding complexity that exists only for unrelated PAKEs that aren't relevant for the user. This comes with the cost of the two additional API functions that we need to maintain. Since the current stream of work focuses on enabling J-PAKE, there are no benefits to these functions for now. Once algorithms that can benefit from this simplification are added, adding back these functions can be reconsidered. Signed-off-by: Janos Follath --- include/psa/crypto.h | 88 ++----------------------------------- include/psa/crypto_sizes.h | 24 +--------- include/psa/crypto_values.h | 4 +- 3 files changed, 8 insertions(+), 108 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index e6e78eb1c..632006dfb 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4232,10 +4232,10 @@ static psa_pake_operation_t psa_pake_operation_init(void); * * A typical sequence of calls to perform a password-authenticated key * exchange: - * -# Call psa_pake_get_key_share() to get the key share that needs to be sent - * to the peer. - * -# Call psa_pake_set_key_share() to provide the key share that was received - * from the peer. + * -# Call psa_pake_output(operation, #PSA_PAKE_DATA_KEY_SHARE, ...) to get the + * key share that needs to be sent to the peer. + * -# Call psa_pake_input(operation, #PSA_PAKE_DATA_KEY_SHARE, ...) to provide + * the key share that was received from the peer. * -# Call psa_pake_get_implicit_key() for accessing the shared secret. * * The exact sequence of calls to perform a password-authenticated key exchange @@ -4326,55 +4326,11 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, const uint8_t *session_data, size_t session_data_len); -/** Get the key share from a password-authenticated key exchange operation. - * - * This function returns a simple key share (eg. group element). - * - * The exact sequence of calls to perform a password-authenticated key - * exchange depends on the algorithm in use. Refer to the documentation of - * individual PAKE algorithm types (`PSA_ALG_XXX` values of type - * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more - * information. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_pake_abort(). - * - * \param[in,out] operation Active PAKE operation. - * \param[out] key_share Buffer where the key share is to be written. - * \param key_share_size Size of the \p key_share buffer in bytes. - * \param[out] key_share_length On success, the number of bytes of the - * returned key_share. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, but beyond that - * validity is specific to the algorithm). - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p key_share 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_pake_get_key_share(psa_pake_operation_t *operation, - uint8_t *key_share, - size_t key_share_size, - size_t *key_share_length); - /** Get additional key share from a password-authenticated key exchange. * * Depending on the algorithm being executed, you might need to call this * function several times or you might not need to call this at all. * - * Calling this function with PSA_PAKE_DATA_KEY_SHARE as \p type is equivalent - * to calling psa_pake_get_key_share(). - * * The exact sequence of calls to perform a password-authenticated key * exchange depends on the algorithm in use. Refer to the documentation of * individual PAKE algorithm types (`PSA_ALG_XXX` values of type @@ -4414,47 +4370,11 @@ psa_status_t psa_pake_output(psa_pake_operation_t *operation, size_t output_size, size_t *output_length); -/** Provide peer key share to a password-authenticated key exchange operation. - * - * This function inputs a simple key share (eg. group element). - * - * The exact sequence of calls to perform a password-authenticated key - * exchange depends on the algorithm in use. Refer to the documentation of - * individual PAKE algorithm types (`PSA_ALG_XXX` values of type - * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more - * information. - * - * \param[in,out] operation Active PAKE operation. - * \param[in] key_share Buffer containing the peer's key share. - * \param key_share_length Size of the \p key_share buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, but beyond that - * validity is specific to the 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_pake_set_key_share(psa_pake_operation_t *operation, - const uint8_t *key_share, - size_t key_share_length); - /** Provide additional peer key share for a password-authenticated key exchange. * * Depending on the algorithm being executed, you might need to call this * function several times or you might not need to call this at all. * - * Calling this function with PSA_PAKE_DATA_KEY_SHARE as \p type is equivalent - * to calling psa_pake_set_key_share(). - * * The exact sequence of calls to perform a password-authenticated key * exchange depends on the algorithm in use. Refer to the documentation of * individual PAKE algorithm types (`PSA_ALG_XXX` values of type diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index 8497b14d0..482ff6806 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -1132,26 +1132,6 @@ #define PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE \ (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE) -/** A sufficient output buffer size for psa_pake_get_key_share(). - * - * If the size of the ciphertext buffer is at least this large, it is - * guaranteed that psa_pake_get_key_share() will not fail due to an - * insufficient ciphertext buffer size. The actual size of the output might be - * smaller in any given call. - * - * See also #PSA_PAKE_OUTPUT_MAX_SIZE - * - * \param alg A PAKE algorithm (PSA_ALG_XXX value such that - * #PSA_ALG_IS_PAKE(\p alg) is true). - * \param cipher_suite A cipher suite that is compatible with algorithm \p alg. - * \return A sufficient key share buffer size for the specified - * cipher suite and algorithm. If the cipher suite or PAKE - * algorithm is not recognized, or the parameters are - * incompatible, return 0. - */ -#define PSA_PAKE_KEY_SHARE_SIZE(alg, cipher_suite) \ - (PSA_PAKE_OUTPUT_SIZE(alg, cipher_suite, PSA_PAKE_DATA_KEY_SHARE) - /** A sufficient output buffer size for psa_pake_output(). * * If the size of the ciphertext buffer is at least this large, it is @@ -1172,8 +1152,8 @@ */ #define PSA_PAKE_OUTPUT_SIZE(alg, cipher_suite, output) -/** Output buffer size for psa_pake_output() and psa_pake_get_key_share(), - * for any of the supported cipher suites and PAKE algorithms. +/** Output buffer size for psa_pake_output() for any of the supported cipher + * suites and PAKE algorithms. * * This macro must expand to a compile-time constant integer. * diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 4a6b06c76..1e8c9fe38 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1986,7 +1986,7 @@ * * The key exchange flow for JPAKE is as follows: * -# To get the first round data that needs to be sent to the peer, call - * psa_pake_get_key_share(operation, ...); + * psa_pake_output(operation, #PSA_PAKE_DATA_KEY_SHARE, ...); * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PUBLIC, ...); * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); * psa_pake_output(operation, #PSA_PAKE_DATA_KEY_SHARE_2, ...); @@ -1994,7 +1994,7 @@ * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PROOF_2, ...); * -# To provide the first round data received from the peer to the operation, * call - * psa_pake_set_key_share(operation, ...); + * psa_pake_input(operation, #PSA_PAKE_DATA_KEY_SHARE, ...); * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PUBLIC, ...); * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); * psa_pake_input(operation, #PSA_PAKE_DATA_KEY_SHARE_2, ...); From ef1b8c9a76167937dd7e79f538250c3a309c9c7f Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 19 Apr 2021 14:35:03 +0100 Subject: [PATCH 14/69] PSA PAKE: Relate JPAKE documentation to RFC8236 Signed-off-by: Janos Follath --- include/psa/crypto_values.h | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 1e8c9fe38..21d0202ff 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1986,30 +1986,50 @@ * * The key exchange flow for JPAKE is as follows: * -# To get the first round data that needs to be sent to the peer, call + * // Get g1 * psa_pake_output(operation, #PSA_PAKE_DATA_KEY_SHARE, ...); + * // Get the ZKP public key for x1 * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PUBLIC, ...); + * // Get the ZKP proof for x1 * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); + * // Get g2 * psa_pake_output(operation, #PSA_PAKE_DATA_KEY_SHARE_2, ...); + * // Get the ZKP public key for x2 * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PUBLIC_2, ...); + * // Get the ZKP proof for x2 * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PROOF_2, ...); * -# To provide the first round data received from the peer to the operation, * call + * // Set g3 * psa_pake_input(operation, #PSA_PAKE_DATA_KEY_SHARE, ...); + * // Set the ZKP public key for x3 * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PUBLIC, ...); + * // Set the ZKP proof for x3 * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); + * // Set g4 * psa_pake_input(operation, #PSA_PAKE_DATA_KEY_SHARE_2, ...); + * // Set the ZKP public key for x4 * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PUBLIC_2, ...); + * // Set the ZKP proof for x4 * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PROOF_2, ...); * -# To get the second round data that needs to be sent to the peer, call + * // Get A * psa_pake_output(operation, #PSA_PAKE_DATA_KEY_SHARE_3, ...); + * // Get ZKP public key for x2*s * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PUBLIC_3, ...); + * // Get ZKP proof for x2*s * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PROOF_3, ...); * -# To provide the second round data received from the peer to the operation, * call + * // Set B * psa_pake_input(operation, #PSA_PAKE_DATA_KEY_SHARE_3, ...); + * // Set ZKP public key for x4*s * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PUBLIC_3, ...); + * // Set ZKP proof for x4*s * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PROOF_3, ...); - * -# Call psa_pake_get_implicit_key() for accessing the shared secret. + * -# To access the shared secret call + * // Get Ka=Kb=K + * psa_pake_get_implicit_key() * * For more information consult the documentation of the individual * PSA_PAKE_DATA_XXX constants. From 8005e8a167c196f1b10bdaf924c14eadc47bf629 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 19 Apr 2021 14:46:54 +0100 Subject: [PATCH 15/69] Shrink psa_pake_side_t to uint8_t Signed-off-by: Janos Follath --- include/psa/crypto_types.h | 2 +- include/psa/crypto_values.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h index 8635afd74..3ec77f28f 100644 --- a/include/psa/crypto_types.h +++ b/include/psa/crypto_types.h @@ -389,7 +389,7 @@ typedef uint16_t psa_key_derivation_step_t; * Encodes which side of the algorithm is being executed. For more information * see the documentation of individual PSA_PAKE_SIDE_XXX constants. */ -typedef uint16_t psa_pake_side_t; +typedef uint8_t psa_pake_side_t; /** Encoding of input and output indicators for PAKE. * diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 21d0202ff..0e3d9231a 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -2477,7 +2477,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * need this, either #PSA_PAKE_SIDE_FIRST or #PSA_PAKE_SIDE_SECOND are * accepted. */ -#define PSA_PAKE_SIDE_FIRST ((psa_pake_side_t)0x0001) +#define PSA_PAKE_SIDE_FIRST ((psa_pake_side_t)0x01) /** The second peer in a balanced PAKE. * @@ -2486,19 +2486,19 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * need this, either #PSA_PAKE_SIDE_FIRST or #PSA_PAKE_SIDE_SECOND are * accepted. */ -#define PSA_PAKE_SIDE_SECOND ((psa_pake_side_t)0x0002) +#define PSA_PAKE_SIDE_SECOND ((psa_pake_side_t)0x02) /** The client in an augmented PAKE. * * Augmented PAKE algorithms need to differentiate between client and server. */ -#define PSA_PAKE_SIDE_CLIENT ((psa_pake_side_t)0x0101) +#define PSA_PAKE_SIDE_CLIENT ((psa_pake_side_t)0x11) /** The server in an augmented PAKE. * * Augmented PAKE algorithms need to differentiate between client and server. */ -#define PSA_PAKE_SIDE_SERVER ((psa_pake_side_t)0x0102) +#define PSA_PAKE_SIDE_SERVER ((psa_pake_side_t)0x12) /** The PAKE uses elliptic curves. * From 8603fb09fe6864ad2be31ab996c6524bff129045 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 19 Apr 2021 15:12:46 +0100 Subject: [PATCH 16/69] PSA PAKE: add to PSA constant name test Signed-off-by: Janos Follath --- scripts/mbedtls_dev/macro_collector.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/mbedtls_dev/macro_collector.py b/scripts/mbedtls_dev/macro_collector.py index 0e76435f3..395e038ca 100644 --- a/scripts/mbedtls_dev/macro_collector.py +++ b/scripts/mbedtls_dev/macro_collector.py @@ -95,6 +95,7 @@ class PSAMacroEnumerator: self.mac_algorithms = set() #type: Set[str] self.ka_algorithms = set() #type: Set[str] self.kdf_algorithms = set() #type: Set[str] + self.pake_algorithms = set() #type: Set[str] self.aead_algorithms = set() #type: Set[str] # macro name -> list of argument names self.argspecs = {} #type: Dict[str, List[str]] @@ -364,6 +365,7 @@ enumerate 'asymmetric_signature_algorithm': [], 'asymmetric_signature_wildcard': [self.algorithms], 'asymmetric_encryption_algorithm': [], + 'pake_algorithm': [self.pake_algorithms], 'other_algorithm': [], } #type: Dict[str, List[Set[str]]] self.arguments_for['mac_length'] += ['1', '63'] @@ -389,6 +391,7 @@ enumerate self.mac_algorithms.add('0x03007fff') self.ka_algorithms.add('0x09fc0000') self.kdf_algorithms.add('0x080000ff') + self.pake_algorithms.add('0x0a0000ff') # For AEAD algorithms, the only variability is over the tag length, # and this only applies to known algorithms, so don't test an # unknown algorithm. From 2ba6079d473971b7271ca469b68ac2e4b72ff1a9 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 28 Apr 2021 09:37:34 +0100 Subject: [PATCH 17/69] PSA: fix wording for implementation defined types There were remnants of the PSA specification wording in the documentation that can be confusing in Mbed TLS. We need to make it clear what the consequences of being implementation defined are in Mbed TLS. Signed-off-by: Janos Follath --- include/psa/crypto.h | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 632006dfb..074cc93e1 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -938,8 +938,8 @@ psa_status_t psa_hash_compare(psa_algorithm_t alg, * \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. */ + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ typedef struct psa_hash_operation_s psa_hash_operation_t; /** \def PSA_HASH_OPERATION_INIT @@ -1307,9 +1307,10 @@ psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key, * operation = psa_mac_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. */ + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ typedef struct psa_mac_operation_s psa_mac_operation_t; /** \def PSA_MAC_OPERATION_INIT @@ -1732,8 +1733,8 @@ psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, * \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. */ + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ typedef struct psa_cipher_operation_s psa_cipher_operation_t; /** \def PSA_CIPHER_OPERATION_INIT @@ -2261,8 +2262,8 @@ psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key, * \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. */ + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ typedef struct psa_aead_operation_s psa_aead_operation_t; /** \def PSA_AEAD_OPERATION_INIT @@ -3260,8 +3261,8 @@ psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, * \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. + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ typedef struct psa_key_derivation_s psa_key_derivation_operation_t; @@ -4134,8 +4135,8 @@ psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, /** The type of the data strucure for PAKE cipher suites. * * 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. + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ typedef struct psa_pake_cipher_suite_s psa_pake_cipher_suite_t; @@ -4198,8 +4199,8 @@ static psa_pake_cipher_suite_t psa_pake_cipher_suite( * \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. */ + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ typedef struct psa_pake_operation_s psa_pake_operation_t; /** \def PSA_PAKE_OPERATION_INIT From fc3577daae6058b01c89cebb1b067c9712e85c62 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 28 Apr 2021 09:51:55 +0100 Subject: [PATCH 18/69] Remove reference to PSA_PAKE_KEY_SHARE_SIZE The macro PSA_PAKE_KEY_SHARE_SIZE has been removed, we need to remove references to it from the documentation as well. Signed-off-by: Janos Follath --- include/psa/crypto_sizes.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index 482ff6806..bb01d5315 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -1157,8 +1157,7 @@ * * This macro must expand to a compile-time constant integer. * - * See also #PSA_PAKE_KEY_SHARE_SIZE(\p alg, \p cipher_suite) and - * #PSA_PAKE_OUTPUT_SIZE(\p alg, \p cipher_suite, \p output). + * See also #PSA_PAKE_OUTPUT_SIZE(\p alg, \p cipher_suite, \p output). */ #define PSA_PAKE_OUTPUT_MAX_SIZE From 82b54b96d3e5be4d491a17e9e369a973bd51cbff Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 28 Apr 2021 13:47:12 +0100 Subject: [PATCH 19/69] PSA PAKE: Align macro names In the key types API, PSA Crypto uses ECC to denote Elliptic curve cryptography and DH to denote Finite Field Diffie-Hellman. Change PSA_PAKE_PRIMITIVE_TYPE_XXX macros to be aligned. Signed-off-by: Janos Follath --- include/psa/crypto_values.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 0e3d9231a..9a9f69e61 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1969,8 +1969,8 @@ /** The Password-authenticated key exchange by juggling (J-PAKE) algorithm. * * J-PAKE can be instantiated over finite fields or elliptic curves. This can - * be achieved by passing either #PSA_PAKE_PRIMITIVE_TYPE_FIELD_DH or - * #PSA_PAKE_PRIMITIVE_TYPE_CURVE to #PSA_PAKE_PRIMITIVE respectively, when + * be achieved by passing either #PSA_PAKE_PRIMITIVE_TYPE_DH or + * #PSA_PAKE_PRIMITIVE_TYPE_ECC to #PSA_PAKE_PRIMITIVE respectively, when * creating the cipher suite. * * In theory the algorithm works with any non-interactive zero-knowledge proof. @@ -2515,7 +2515,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * curve would be. For more information, consult the documentation of * psa_export_key(). */ -#define PSA_PAKE_PRIMITIVE_TYPE_CURVE ((psa_pake_primitive_type_t)0x01) +#define PSA_PAKE_PRIMITIVE_TYPE_ECC ((psa_pake_primitive_type_t)0x01) /** The PAKE uses finite fields based Diffie-Hellman groups. * @@ -2532,7 +2532,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * group would be. For more information, consult the documentation of * psa_export_key(). */ -#define PSA_PAKE_PRIMITIVE_TYPE_FIELD_DH ((psa_pake_primitive_type_t)0x02) +#define PSA_PAKE_PRIMITIVE_TYPE_DH ((psa_pake_primitive_type_t)0x02) /** Construct a PAKE primitive from type, family and bitsize. * From cd56ff9c596d591e738b54ee274ff6082d0d6b81 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 30 Apr 2021 11:51:55 +0100 Subject: [PATCH 20/69] PSA PAKE: make cipher suite opaque Hiding the structure of the cipher suite implementation allows for greater flexibility. To preserve maximum flexibility, the constructor is replaced by individual setter/getter functions. Convenience macros and or functions can be added later. Signed-off-by: Janos Follath --- include/psa/crypto.h | 200 +++++++++++++++++++++++++++++++----- include/psa/crypto_struct.h | 94 ++++++++++++----- include/psa/crypto_values.h | 21 ++-- 3 files changed, 256 insertions(+), 59 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 074cc93e1..9220b2ea7 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4140,38 +4140,188 @@ psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, */ typedef struct psa_pake_cipher_suite_s psa_pake_cipher_suite_t; -/** Construct a cipher suite for a password-authenticated key exchange. +/** Retrieve the PAKE algorithm from a PAKE cipher suite. * - * \param primitive The primitive used in the cipher suite. - * \param hash The hash involved in the cipher suite. - * (`PSA_ALG_XXX` values of type ::psa_algorithm_t - * such that #PSA_ALG_IS_HASH(\c alg) is true.) - * \param algorithm1 Additional algorithm if needed in the cipher suite, - * 0 otherwise. - * \param bits1 A bit size qualifier if needed for \p algorithm1, - * 0 otherwise. - * \param algorithm2 Additional algorithm if needed in the cipher suite, - * 0 otherwise. - * \param bits2 A bit size qualifier if needed for \p algorithm2, - * 0 otherwise. - * \param options Additional options to be included with the cipher - * suite if needed, 0 otherwise. + * 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] cipher_suite The cipher suite structure to query. + * + * \return The PAKE algorithm stored in the cipher suite structure. + */ +static psa_algorithm_t psa_pake_cs_get_algorithm( + const psa_pake_cipher_suite_t* cipher_suite + ); + +/** Declare the PAKE algorithm for the cipher suite. + * + * This function overwrites any PAKE algorithm + * previously set in \p cipher_suite. + * + * 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] cipher_suite The cipher suite structure to write to. + * \param algorithm The PAKE algorithm to write. + * (`PSA_ALG_XXX` values of type ::psa_algorithm_t + * such that #PSA_ALG_IS_PAKE(\c alg) is true.) + * If this is 0, the PAKE algorithm in + * \p cipher_suite becomes unspecified. + */ +static void psa_pake_cs_set_algorithm( + psa_pake_cipher_suite_t* cipher_suite, + psa_algorithm_t algorithm + ); + +/** Retrieve the primitive type from a PAKE cipher suite. + * + * 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. * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. * - * \retval The constructed cipher suite. + * \param[in] cipher_suite The cipher suite structure to query. + * + * \return The primitive type stored in the cipher suite structure. */ -static psa_pake_cipher_suite_t psa_pake_cipher_suite( - psa_pake_primitive_t primitive, - psa_algorithm_t hash, - psa_algorithm_t algorithm1, - psa_pake_bits_t bits1, - psa_algorithm_t algorithm2, - psa_pake_bits_t bits2, - psa_pake_cipher_suite_options_t options - ); +static psa_pake_primitive_type_t psa_pake_cs_get_type( + const psa_pake_cipher_suite_t* cipher_suite + ); + +/** Declare the primitive type for a PAKE cipher suite. + * + * This function overwrites any primitive type + * previously set in \p cipher_suite. + * + * 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] cipher_suite The cipher suite structure to write to. + * \param type The primitive type to write. + * If this is 0, the primitive type in + * \p cipher_suite becomes unspecified. + */ +static void psa_pake_cs_set_type( + psa_pake_cipher_suite_t* cipher_suite, + psa_pake_primitive_type_t type + ); + +/** Retrieve the primitive family from a PAKE cipher suite. + * + * 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] cipher_suite The cipher suite structure to query. + * + * \return The primitive family stored in the cipher suite structure. + */ +static uint8_t psa_pake_cs_get_family( + const psa_pake_cipher_suite_t* cipher_suite + ); + +/** Declare the primitive family for a PAKE cipher suite. + * + * This function overwrites any primitive family + * previously set in \p cipher_suite. + * + * 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] cipher_suite The cipher suite structure to write to. + * \param family The primitive family to write. + * If this is 0, the primitive family in + * \p cipher_suite becomes unspecified. The + * interpretation of this parameter depends on + * the primitive type, for more information consult the + * documentation of individual + * ::psa_pake_primitive_type_t constants). + */ +static void psa_pake_cs_set_family( + psa_pake_cipher_suite_t* cipher_suite, + uint8_t family + ); + +/** Retrieve the primitive bits from a PAKE cipher suite. + * + * 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] cipher_suite The cipher suite structure to query. + * + * \return The primitive bits stored in the cipher suite structure. + */ +static size_t psa_pake_cs_get_bits(const psa_pake_cipher_suite_t* cipher_suite); + +/** Declare the primitive bits for a PAKE cipher suite. + * + * This function overwrites any primitive bits + * previously set in \p cipher_suite. + * + * 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] cipher_suite The cipher suite structure to write to. + * \param bits The primitive bits to write. + * If this is 0, the primitive bits in + * \p cipher_suite becomes unspecified. The + * interpretation of this parameter depends on + * the family, for more information consult the + * documentation of individual + * ::psa_pake_primitive_type_t constants). + */ +static void psa_pake_cs_set_bits( + psa_pake_cipher_suite_t* cipher_suite, + size_t bits + ); + +/** Retrieve the hash algorithm from a PAKE cipher suite. + * + * 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] cipher_suite The cipher suite structure to query. + * + * \return The hash algorithm stored in the cipher suite structure. + */ +static psa_algorithm_t psa_pake_cs_get_hash( + const psa_pake_cipher_suite_t* cipher_suite + ); + +/** Declare the hash algorithm for a PAKE cipher suite. + * + * This function overwrites any hash algorithm + * previously set in \p cipher_suite. + * + * 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. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[out] cipher_suite The cipher suite structure to write to. + * \param hash The hash involved in the cipher suite. + * (`PSA_ALG_XXX` values of type ::psa_algorithm_t + * such that #PSA_ALG_IS_HASH(\c alg) is true.) + * If this is 0, the hash algorithm in + * \p cipher_suite becomes unspecified. + */ +static void psa_pake_cs_set_hash( + psa_pake_cipher_suite_t* cipher_suite, + psa_algorithm_t hash + ); /** The type of the state data structure for PAKE operations. * diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index f289caf16..881abcb2a 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -463,36 +463,82 @@ static inline size_t psa_get_key_bits( struct psa_pake_cipher_suite_s { - psa_pake_primitive_t primitive; + psa_algorithm_t algorithm; + psa_pake_primitive_type_t type; + uint8_t family; + size_t bits; psa_algorithm_t hash; - psa_algorithm_t algorithm1; - psa_pake_bits_t bits1; - psa_algorithm_t algorithm2; - psa_pake_bits_t bits2; - psa_pake_cipher_suite_options_t options; }; -static inline struct psa_pake_cipher_suite_s psa_pake_cipher_suite( - psa_pake_primitive_t primitive, - psa_algorithm_t hash, - psa_algorithm_t algorithm1, - psa_pake_bits_t bits1, - psa_algorithm_t algorithm2, - psa_pake_bits_t bits2, - psa_pake_cipher_suite_options_t options - ) +static inline void psa_pake_cs_set_algorithm( + psa_pake_cipher_suite_t *cipher_suite, + psa_algorithm_t algorithm) { - struct psa_pake_cipher_suite_s cipher_suite; + if( !PSA_ALG_IS_PAKE(algorithm) ) + cipher_suite->algorithm = 0; + else + cipher_suite->algorithm = algorithm; +} - cipher_suite.primitive = primitive; - cipher_suite.hash = hash; - cipher_suite.algorithm1 = algorithm1; - cipher_suite.bits1 = bits1; - cipher_suite.algorithm2 = algorithm2; - cipher_suite.bits2 = bits2; - cipher_suite.options = options; +static inline psa_algorithm_t psa_pake_cs_get_algorithm( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return( cipher_suite->algorithm ); +} - return cipher_suite; +static inline psa_pake_primitive_type_t psa_pake_cs_get_type( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return( cipher_suite->type ); +} + +static inline void psa_pake_cs_set_type( + psa_pake_cipher_suite_t *cipher_suite, + psa_pake_primitive_type_t type) +{ + cipher_suite->type = type; +} + +static inline uint8_t psa_pake_cs_get_family( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return( cipher_suite->family ); +} + +static inline void psa_pake_cs_set_family( + psa_pake_cipher_suite_t *cipher_suite, + uint8_t family) +{ + cipher_suite->family = family; +} + +static inline size_t psa_pake_cs_get_bits( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return( cipher_suite->bits ); +} + +static inline void psa_pake_cs_set_bits( + psa_pake_cipher_suite_t *cipher_suite, + size_t bits) +{ + cipher_suite->bits = bits; +} + +static inline psa_algorithm_t psa_pake_cs_get_hash( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return( cipher_suite->hash ); +} + +static inline void psa_pake_cs_set_hash( + psa_pake_cipher_suite_t *cipher_suite, + psa_algorithm_t hash) +{ + if( !PSA_ALG_IS_HASH(hash) ) + cipher_suite->hash = 0; + else + cipher_suite->hash = hash; } struct psa_pake_operation_s diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 9a9f69e61..bed48f79c 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1969,21 +1969,22 @@ /** The Password-authenticated key exchange by juggling (J-PAKE) algorithm. * * J-PAKE can be instantiated over finite fields or elliptic curves. This can - * be achieved by passing either #PSA_PAKE_PRIMITIVE_TYPE_DH or - * #PSA_PAKE_PRIMITIVE_TYPE_ECC to #PSA_PAKE_PRIMITIVE respectively, when - * creating the cipher suite. + * be achieved by setting either #PSA_PAKE_PRIMITIVE_TYPE_DH or + * #PSA_PAKE_PRIMITIVE_TYPE_ECC respectively in the cipher suite (see + * ::psa_pake_cipher_suite_t) via psa_pake_cs_set_type(). (Before using the + * cipher suite the field or curve must be fully specified by calling + * psa_pake_cs_set_family() and psa_pake_cs_set_bits() as well. For more + * information refer to the documentation of the individual + * `PSA_PAKE_PRIMITIVE_TYPE_XXX` constants.) + * + * J-PAKE can be used with any secure cryptographic hash function. The choice + * of hash must be supplied to the cipher suite by calling + * psa_pake_cs_set_hash(). * * In theory the algorithm works with any non-interactive zero-knowledge proof. * Implementations of the present specification use Schnorr NIZKP and this does * not need to be configured in the cipher suites. * - * J-PAKE can be used with any secure cryptographic hash function, the choice - * of hash must be supplied to the psa_pake_cipher_suite() as the second - * parameter (\p hash). - * - * All the remaining parameters passed to psa_pake_cipher_suite() when creating - * the cipher suite must be 0. - * * The key exchange flow for JPAKE is as follows: * -# To get the first round data that needs to be sent to the peer, call * // Get g1 From 684da035322b3b0e1d06dd9658235ceb1e7340cb Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 30 Apr 2021 12:50:32 +0100 Subject: [PATCH 21/69] PSA PAKE: remove obsolete types and macros Making the cipher suite struct internal made a number of types and macros in the interface unused. Signed-off-by: Janos Follath --- include/psa/crypto_types.h | 23 ----------------------- include/psa/crypto_values.h | 34 ++++++---------------------------- 2 files changed, 6 insertions(+), 51 deletions(-) diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h index 3ec77f28f..7c560b3a5 100644 --- a/include/psa/crypto_types.h +++ b/include/psa/crypto_types.h @@ -406,28 +406,5 @@ typedef uint8_t psa_pake_data_t; */ typedef uint8_t psa_pake_primitive_type_t; -/** Encoding of the bitsize for the PAKE's primitive. - * - * The type and family is not enough to identify the primitive to use in the - * PAKE, the implementation needs to know the bitsize too. - */ -typedef uint16_t psa_pake_bits_t; - -/** Encoding of the PAKE's primitive. - * - * In most of the PAKEs the primitives are prime order groups, but some of - * them might need the ring structure or just are using completely different - * algebraic structures (eg. SRP or PQC schemes). - */ -typedef uint32_t psa_pake_primitive_t; - -/** Encoding of additional options for PAKE. - * - * This type is for encoding additional options into PAKE cipher suites. - * (Options like for example EnvelopeMode in OPAQUE or "Per-User M and N" in - * SPAKE2.) - */ -typedef uint32_t psa_pake_cipher_suite_options_t; - /**@}*/ #endif /* PSA_CRYPTO_TYPES_H */ diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index bed48f79c..78d431b9b 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -2504,8 +2504,9 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) /** The PAKE uses elliptic curves. * * The corresponding family type is ::psa_ecc_family_t. In determining a - * specific curve in the family ::psa_pake_bits_t values are interpreted in the - * exact same way as ::psa_key_bits_t would. + * specific curve in the family the cipher suite (see + * ::psa_pake_cipher_suite_t) bits are interpreted in the exact same way + * as key bits are. * * Input and output during the operation can involve group elements and scalar * values: @@ -2521,8 +2522,9 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) /** The PAKE uses finite fields based Diffie-Hellman groups. * * The corresponding family type is ::psa_dh_family_t. In determining a - * specific group in the family ::psa_pake_bits_t values are interpreted in the - * exact same way as ::psa_key_bits_t would. + * specific group in the family the cipher suite (see + * ::psa_pake_cipher_suite_t) bits are interpreted in the exact same way + * as key bits are. * * Input and output during the operation can involve group elements and scalar * values: @@ -2535,28 +2537,6 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) */ #define PSA_PAKE_PRIMITIVE_TYPE_DH ((psa_pake_primitive_type_t)0x02) -/** Construct a PAKE primitive from type, family and bitsize. - * - * \param pake_type The type of the primitive - * (value of type ::psa_pake_primitive_type_t). - * \param pake_family The family of the primitive - * (the type and interpretation of this parameter depends - * on \p type, for more information consult the - * documentation of individual ::psa_pake_primitive_type_t - * constants). - * \param pake_bits The bitsize of the primitive - * (Value of type ::psa_pake_bits_t. The interpretation - * of this parameter depends on \p family, for more - * information consult the documentation of individual - * ::psa_pake_primitive_type_t constants). - * - * \return The constructed primitive value. - */ -#define PSA_PAKE_PRIMITIVE(pake_type, pake_family, pake_bits) \ - ((psa_pake_primitive_t) (((pake_type) << 24 | \ - (pake_family) << 16) | (pake_bits))) - - /** The key share being sent to or received from the peer. * * Unless the documentation of the PAKE algorithm says otherwise this is a @@ -2572,7 +2552,6 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) */ #define PSA_PAKE_DATA_KEY_SHARE ((psa_pake_data_t)0x01) - /** A Schnorr NIZKP public key. * * This is a group element. @@ -2587,7 +2566,6 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) */ #define PSA_PAKE_DATA_ZK_PUBLIC ((psa_pake_data_t)0x02) - /** A Schnorr NIZKP proof. * * This is a scalar value. From 5b44cfd430af591940845bc2c5ef6a4416007cea Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 30 Apr 2021 13:06:27 +0100 Subject: [PATCH 22/69] PSA PAKE: remove alg parameter from setup The cipher suite now defines the algorithm itself as well. Passing the algorithm separately is redundant and error prone. Signed-off-by: Janos Follath --- include/psa/crypto.h | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 9220b2ea7..17316795d 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4421,10 +4421,9 @@ static psa_pake_operation_t psa_pake_operation_init(void); * type PSA_KEY_TYPE_PASSWORD or * #PSA_KEY_TYPE_DERIVE. It has to allow the usage * #PSA_KEY_USAGE_DERIVE. - * \param alg The PAKE algorithm to use - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_PAKE(\p alg) is true). - * \param cipher_suite The cipher suite to use with the PAKE algorithm. + * \param cipher_suite The cipher suite to use. (A cipher suite fully + * characterizes a PAKE algorithm and determines + * the algorithm as well.) * \param side A value of type ::psa_pake_side_t signaling the * side of the algorithm that is being set up. For * more information see the documentation of \c @@ -4446,15 +4445,12 @@ static psa_pake_operation_t psa_pake_operation_init(void); * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p key is not compatible with \p alg. + * \p key is not compatible with the algorithm in \p cipher_suite. * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p session_data is not empty and is not allowed in \p alg. + * \p session_data is not empty and is not allowed in the algorithm in + * \p cipher_suite. * \retval #PSA_ERROR_NOT_SUPPORTED - * \p cipher_suite is not compatible with \p alg. (Eg. \p cipher_suite - * mandates algorithms or sets options that do not make sense for \p alg - * or are not supported with \p alg.) - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p alg is not supported or is not a PAKE algorithm. + * The \p cipher_suite is not supported or is not valid. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE @@ -4467,7 +4463,6 @@ static psa_pake_operation_t psa_pake_operation_init(void); */ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, mbedtls_svc_key_id_t password, - psa_algorithm_t alg, psa_pake_cipher_suite_t cipher_suite, psa_pake_side_t side, const uint8_t *user_id, From f75be64ef555f63f7b5bf4863f00d652f2300483 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 30 Apr 2021 13:11:05 +0100 Subject: [PATCH 23/69] PSA PAKE: fix identifier value Identifier value was not consistent with PSA conventions (last byte is reserved for hash algorithms or used in algorithms parametrized by a hash). Signed-off-by: Janos Follath --- include/psa/crypto_values.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 78d431b9b..a24337081 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -2037,7 +2037,7 @@ * * J-PAKE is standardised for example in RFC 8236. */ -#define PSA_ALG_PAKE_JPAKE ((psa_algorithm_t)0x0a000001) +#define PSA_ALG_PAKE_JPAKE ((psa_algorithm_t)0x0a000100) /**@}*/ From 1459aa5656935a07737ab1769403ff7f4eae8a3a Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 11 May 2021 08:24:56 +0100 Subject: [PATCH 24/69] PSA PAKE: improve documentation Minor documentation improvement and fixes. Signed-off-by: Janos Follath --- include/psa/crypto.h | 36 +++++++++++++++++++++++------------- include/psa/crypto_sizes.h | 5 +++-- include/psa/crypto_values.h | 24 ++++++++++++++---------- 3 files changed, 40 insertions(+), 25 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 17316795d..df8d4d4e9 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4240,8 +4240,8 @@ static uint8_t psa_pake_cs_get_family( * If this is 0, the primitive family in * \p cipher_suite becomes unspecified. The * interpretation of this parameter depends on - * the primitive type, for more information consult the - * documentation of individual + * the primitive type. For more information + * consult the documentation of individual * ::psa_pake_primitive_type_t constants). */ static void psa_pake_cs_set_family( @@ -4249,7 +4249,7 @@ static void psa_pake_cs_set_family( uint8_t family ); -/** Retrieve the primitive bits from a PAKE cipher suite. +/** Retrieve the size associated with the primitive from a PAKE cipher suite. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, @@ -4292,7 +4292,9 @@ static void psa_pake_cs_set_bits( * * \param[in] cipher_suite The cipher suite structure to query. * - * \return The hash algorithm stored in the cipher suite structure. + * \return The hash algorithm stored in the cipher suite structure. The return + * value is 0 if the PAKE is not parametrised by a hash algorithm or if + * the hash algorithm is not set. */ static psa_algorithm_t psa_pake_cs_get_hash( const psa_pake_cipher_suite_t* cipher_suite @@ -4378,8 +4380,8 @@ static psa_pake_operation_t psa_pake_operation_init(void); * -# Initialize the operation object with one of the methods described in the * documentation for #psa_pake_operation_t, e.g. * #PSA_PAKE_OPERATION_INIT. - * -# Call psa_pake_setup() to specify the algorithm, the key, cipher suite, - * identities and additional session information. + * -# Call psa_pake_setup() to specify the algorithm, the password, cipher + * suite, identities and additional session information. * * A typical sequence of calls to perform a password-authenticated key * exchange: @@ -4388,13 +4390,17 @@ static psa_pake_operation_t psa_pake_operation_init(void); * -# Call psa_pake_input(operation, #PSA_PAKE_DATA_KEY_SHARE, ...) to provide * the key share that was received from the peer. * -# Call psa_pake_get_implicit_key() for accessing the shared secret. + * -# Make a sequence of function calls to execute the password-authenticated + * key exchange as described below. + * -# Terminate the operation by a call to psa_pake_get_implicit_key() or + * psa_pake_abort(). * * The exact sequence of calls to perform a password-authenticated key exchange * depends on the algorithm in use: - * -# Some algorithms exchange more data than just a single key share. When using - * such a algorithm, call psa_pake_output() and psa_pake_input() one or more - * times to exchange any further data that is needed to derive the shared - * secret. + * - Some algorithms exchange more data than just a single key share. When using + * such a algorithm, call psa_pake_output() and psa_pake_input() one or more + * times to exchange any further data that is needed to derive the shared + * secret. * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) @@ -4489,7 +4495,10 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, * \param[in,out] operation Active PAKE operation. * \param type The type of the data that is requested. * \param[out] output Buffer where the output is to be written. - * \param output_size Size of the \p output buffer in bytes. + * \param output_size Size of the \p output buffer in bytes. This must + * be at least #PSA_PAKE_OUTPUT_SIZE(\p alg, \c + * cipher_suite, \p type). + * * \param[out] output_length On success, the number of bytes of the returned * output. * @@ -4574,8 +4583,9 @@ psa_status_t psa_pake_input(psa_pake_operation_t *operation, * state and must be aborted by calling psa_pake_abort(). * * \param[in,out] operation Active PAKE operation. - * \param[out] output A key derivation operation that has been - * initialized and set up. + * \param[out] output A key derivation operation that is ready + * for an input step of type + * #PSA_KEY_DERIVATION_INPUT_SECRET. * * \retval #PSA_SUCCESS * Success. diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index bb01d5315..4428fc01f 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -1144,13 +1144,14 @@ * \param alg A PAKE algorithm (PSA_ALG_XXX value such that * #PSA_ALG_IS_PAKE(\p alg) is true). * \param cipher_suite A cipher suite that is compatible with algorithm \p alg. - * \param output An output type used with algorithm \p alg. + * \param output_step A value of type ::psa_pake_data_t that is valid for the + * algorithm \p alg. * \return A sufficient output buffer size for the specified * output, cipher suite and algorithm. If the cipher suite, * the output type or PAKE algorithm is not recognized, or * the parameters are incompatible, return 0. */ -#define PSA_PAKE_OUTPUT_SIZE(alg, cipher_suite, output) +#define PSA_PAKE_OUTPUT_SIZE(alg, cipher_suite, output_step) /** Output buffer size for psa_pake_output() for any of the supported cipher * suites and PAKE algorithms. diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index a24337081..ab064dbdd 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -2501,12 +2501,14 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) */ #define PSA_PAKE_SIDE_SERVER ((psa_pake_side_t)0x12) -/** The PAKE uses elliptic curves. +/** The PAKE primitive type indicating the use of elliptic curves. * - * The corresponding family type is ::psa_ecc_family_t. In determining a - * specific curve in the family the cipher suite (see - * ::psa_pake_cipher_suite_t) bits are interpreted in the exact same way - * as key bits are. + * The values of the \c family and \c bits fields of the cipher suite identify a + * specific elliptic curve, using the same mapping that is used for ECC + * (::psa_ecc_family_t) keys. + * + * (Here \c familiy means the value returned by psa_pake_cs_get_family() and + * \c bits means the value returned by psa_pake_cs_get_bits().) * * Input and output during the operation can involve group elements and scalar * values: @@ -2519,12 +2521,14 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) */ #define PSA_PAKE_PRIMITIVE_TYPE_ECC ((psa_pake_primitive_type_t)0x01) -/** The PAKE uses finite fields based Diffie-Hellman groups. +/** The PAKE primitive type indicating the use of Diffie-Hellman groups. * - * The corresponding family type is ::psa_dh_family_t. In determining a - * specific group in the family the cipher suite (see - * ::psa_pake_cipher_suite_t) bits are interpreted in the exact same way - * as key bits are. + * The values of the \c family and \c bits fields of the cipher suite identify + * a specific Diffie-Hellman group, using the same mapping that is used for + * Diffie-Hellman (::psa_dh_family_t) keys. + * + * (Here \c familiy means the value returned by psa_pake_cs_get_family() and + * \c bits means the value returned by psa_pake_cs_get_bits().) * * Input and output during the operation can involve group elements and scalar * values: From f53c7af916877bfacf5fb9c27fbe0bfd21ff713d Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 11 May 2021 08:35:31 +0100 Subject: [PATCH 25/69] PSA PAKE: introduce psa_pake_family_t It is the size of something that has no a priori reason to consist of 8 bits. This should be psa_pake_family_t, both for documentation (and possibly static analysis) and in case 8 bits turn out not to be enough. Signed-off-by: Janos Follath --- include/psa/crypto.h | 4 ++-- include/psa/crypto_struct.h | 6 +++--- include/psa/crypto_types.h | 9 +++++++++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index df8d4d4e9..970aea324 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4222,7 +4222,7 @@ static void psa_pake_cs_set_type( * * \return The primitive family stored in the cipher suite structure. */ -static uint8_t psa_pake_cs_get_family( +static psa_pake_family_t psa_pake_cs_get_family( const psa_pake_cipher_suite_t* cipher_suite ); @@ -4246,7 +4246,7 @@ static uint8_t psa_pake_cs_get_family( */ static void psa_pake_cs_set_family( psa_pake_cipher_suite_t* cipher_suite, - uint8_t family + psa_pake_family_t family ); /** Retrieve the size associated with the primitive from a PAKE cipher suite. diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index 881abcb2a..97d5d2b41 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -465,7 +465,7 @@ struct psa_pake_cipher_suite_s { psa_algorithm_t algorithm; psa_pake_primitive_type_t type; - uint8_t family; + psa_pake_family_t family; size_t bits; psa_algorithm_t hash; }; @@ -499,7 +499,7 @@ static inline void psa_pake_cs_set_type( cipher_suite->type = type; } -static inline uint8_t psa_pake_cs_get_family( +static inline psa_pake_family_t psa_pake_cs_get_family( const psa_pake_cipher_suite_t *cipher_suite) { return( cipher_suite->family ); @@ -507,7 +507,7 @@ static inline uint8_t psa_pake_cs_get_family( static inline void psa_pake_cs_set_family( psa_pake_cipher_suite_t *cipher_suite, - uint8_t family) + psa_pake_family_t family) { cipher_suite->family = family; } diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h index 7c560b3a5..09ff1c5ed 100644 --- a/include/psa/crypto_types.h +++ b/include/psa/crypto_types.h @@ -403,8 +403,17 @@ typedef uint8_t psa_pake_data_t; * * Values defined by this standard will never be in the range 0x80-0xff. * Vendors who define additional types must use an encoding in this range. + * + * For more information see the documentation of individual + * PSA_PAKE_PRIMITIVE_TYPE_XXX constants. */ typedef uint8_t psa_pake_primitive_type_t; +/** \brief Encoding of the family of the primitive associated with the PAKE. + * + * For more information see the documentation of individual + * PSA_PAKE_PRIMITIVE_TYPE_XXX constants. + */ +typedef uint8_t psa_pake_family_t; /**@}*/ #endif /* PSA_CRYPTO_TYPES_H */ From 57cfc407e0ad421143e31fc6f8a656e560a249a2 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 11 May 2021 09:05:25 +0100 Subject: [PATCH 26/69] Remove obsolete __DOXYGEN_ONLY__ blocks __DOXYGEN_ONLY__ blocks were only used to typeset the PSA specification back when it was extracted from Mbed TLS headers. They are no longer used and should be removed. The PSA Crypto Driver API is still under development and might be extracted from Mbed TLS headers, leaving them there for now. Signed-off-by: Janos Follath --- include/psa/crypto.h | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 970aea324..7efa3154c 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -112,12 +112,6 @@ psa_status_t psa_crypto_init(void); * 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_ATTRIBUTES_INIT {0} -#endif /** Return an initial value for a key attributes structure. */ @@ -947,12 +941,6 @@ typedef struct psa_hash_operation_s psa_hash_operation_t; * This macro returns a suitable initializer for a hash operation object * of type #psa_hash_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_HASH_OPERATION_INIT {0} -#endif /** Return an initial value for a hash operation object. */ @@ -1318,12 +1306,6 @@ typedef struct psa_mac_operation_s psa_mac_operation_t; * This macro returns a suitable initializer for a MAC operation object of type * #psa_mac_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_MAC_OPERATION_INIT {0} -#endif /** Return an initial value for a MAC operation object. */ @@ -1742,12 +1724,6 @@ typedef struct psa_cipher_operation_s psa_cipher_operation_t; * This macro returns a suitable initializer for a cipher operation object of * type #psa_cipher_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_CIPHER_OPERATION_INIT {0} -#endif /** Return an initial value for a cipher operation object. */ @@ -2271,12 +2247,6 @@ typedef struct psa_aead_operation_s psa_aead_operation_t; * 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. */ @@ -3271,12 +3241,6 @@ typedef struct psa_key_derivation_s psa_key_derivation_operation_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_KEY_DERIVATION_OPERATION_INIT {0} -#endif /** Return an initial value for a key derivation operation object. */ @@ -4360,12 +4324,6 @@ typedef struct psa_pake_operation_s psa_pake_operation_t; * This macro returns a suitable initializer for an PAKE operation object of * type #psa_pake_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_PAKE_OPERATION_INIT {0} -#endif /** Return an initial value for an PAKE operation object. */ From beb78d4d415fd68a6262194ccdf6fa4d84737bdd Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 11 May 2021 09:11:39 +0100 Subject: [PATCH 27/69] Rename psa_pake_data_t "Data" is too vague, renaming it to psa_pake_step_t. It is still somewhat vague, but at least consistent with the naming used in key derivation. Signed-off-by: Janos Follath --- include/psa/crypto.h | 4 ++-- include/psa/crypto_sizes.h | 2 +- include/psa/crypto_types.h | 2 +- include/psa/crypto_values.h | 18 +++++++++--------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 7efa3154c..9ceac0a58 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4478,7 +4478,7 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, * results in this error code. */ psa_status_t psa_pake_output(psa_pake_operation_t *operation, - psa_pake_data_t type, + psa_pake_step_t type, uint8_t *output, size_t output_size, size_t *output_length); @@ -4518,7 +4518,7 @@ psa_status_t psa_pake_output(psa_pake_operation_t *operation, * results in this error code. */ psa_status_t psa_pake_input(psa_pake_operation_t *operation, - psa_pake_data_t type, + psa_pake_step_t type, uint8_t *input, size_t input_length); diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index 4428fc01f..9d2f6c49c 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -1144,7 +1144,7 @@ * \param alg A PAKE algorithm (PSA_ALG_XXX value such that * #PSA_ALG_IS_PAKE(\p alg) is true). * \param cipher_suite A cipher suite that is compatible with algorithm \p alg. - * \param output_step A value of type ::psa_pake_data_t that is valid for the + * \param output_step A value of type ::psa_pake_step_t that is valid for the * algorithm \p alg. * \return A sufficient output buffer size for the specified * output, cipher suite and algorithm. If the cipher suite, diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h index 09ff1c5ed..bf8ab15a7 100644 --- a/include/psa/crypto_types.h +++ b/include/psa/crypto_types.h @@ -397,7 +397,7 @@ typedef uint8_t psa_pake_side_t; * This type is for encoding additional input and output data for such * algorithms. */ -typedef uint8_t psa_pake_data_t; +typedef uint8_t psa_pake_step_t; /** Encoding of the type of the PAKE's primitive. * diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index ab064dbdd..06aeec5e4 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -2554,7 +2554,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * received. For values sent or received afterwards, use * #PSA_PAKE_DATA_KEY_SHARE_2 and #PSA_PAKE_DATA_KEY_SHARE_3. */ -#define PSA_PAKE_DATA_KEY_SHARE ((psa_pake_data_t)0x01) +#define PSA_PAKE_DATA_KEY_SHARE ((psa_pake_step_t)0x01) /** A Schnorr NIZKP public key. * @@ -2568,7 +2568,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * key received. For values sent or received afterwards, use * #PSA_PAKE_DATA_ZK_PUBLIC_2 and #PSA_PAKE_DATA_ZK_PUBLIC_3. */ -#define PSA_PAKE_DATA_ZK_PUBLIC ((psa_pake_data_t)0x02) +#define PSA_PAKE_DATA_ZK_PUBLIC ((psa_pake_step_t)0x02) /** A Schnorr NIZKP proof. * @@ -2582,43 +2582,43 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * received. For values sent or received afterwards, use * #PSA_PAKE_DATA_ZK_PROOF_2 and #PSA_PAKE_DATA_ZK_PROOF_3. */ -#define PSA_PAKE_DATA_ZK_PROOF ((psa_pake_data_t)0x03) +#define PSA_PAKE_DATA_ZK_PROOF ((psa_pake_step_t)0x03) /** Marks the second key share sent and received. * * See #PSA_PAKE_DATA_KEY_SHARE. */ -#define PSA_PAKE_DATA_KEY_SHARE_2 ((psa_pake_data_t)0x04) +#define PSA_PAKE_DATA_KEY_SHARE_2 ((psa_pake_step_t)0x04) /** Marks the second Schnorr NIZKP public key sent and received. * * See #PSA_PAKE_DATA_ZK_PUBLIC. */ -#define PSA_PAKE_DATA_ZK_PUBLIC_2 ((psa_pake_data_t)0x05) +#define PSA_PAKE_DATA_ZK_PUBLIC_2 ((psa_pake_step_t)0x05) /** Marks the second Schnorr NIZKP proof sent and received. * * See #PSA_PAKE_DATA_ZK_PROOF. */ -#define PSA_PAKE_DATA_ZK_PROOF_2 ((psa_pake_data_t)0x06) +#define PSA_PAKE_DATA_ZK_PROOF_2 ((psa_pake_step_t)0x06) /** Marks the third key share sent and received. * * See #PSA_PAKE_DATA_KEY_SHARE. */ -#define PSA_PAKE_DATA_KEY_SHARE_3 ((psa_pake_data_t)0x07) +#define PSA_PAKE_DATA_KEY_SHARE_3 ((psa_pake_step_t)0x07) /** Marks the third Schnorr NIZKP public key sent and received. * * See #PSA_PAKE_DATA_ZK_PUBLIC. */ -#define PSA_PAKE_DATA_ZK_PUBLIC_3 ((psa_pake_data_t)0x08) +#define PSA_PAKE_DATA_ZK_PUBLIC_3 ((psa_pake_step_t)0x08) /** Marks the third Schnorr NIZKP proof sent and received. * * See #PSA_PAKE_DATA_ZK_PROOF. */ -#define PSA_PAKE_DATA_ZK_PROOF_3 ((psa_pake_data_t)0x09) +#define PSA_PAKE_DATA_ZK_PROOF_3 ((psa_pake_step_t)0x09) /**@}*/ #endif /* PSA_CRYPTO_VALUES_H */ From a86c3131a8981d632585f83d8f5f61384b70c072 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 13 May 2021 10:51:01 +0100 Subject: [PATCH 28/69] PSA PAKE: divide setup into several steps There are too many parameters to the setup function. This makes it hard to figure out how to call the function and read code that calls the function. This also opens the suspicion that there's yet another parameter that we're missing. Signed-off-by: Janos Follath --- include/psa/crypto.h | 195 ++++++++++++++++++++++++++---------- include/psa/crypto_values.h | 5 + 2 files changed, 147 insertions(+), 53 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 9ceac0a58..a2f34cab0 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4319,12 +4319,6 @@ static void psa_pake_cs_set_hash( * Implementation details can change in future versions without notice. */ typedef struct psa_pake_operation_s psa_pake_operation_t; -/** \def PSA_PAKE_OPERATION_INIT - * - * This macro returns a suitable initializer for an PAKE operation object of - * type #psa_pake_operation_t. - */ - /** Return an initial value for an PAKE operation object. */ static psa_pake_operation_t psa_pake_operation_init(void); @@ -4338,8 +4332,21 @@ static psa_pake_operation_t psa_pake_operation_init(void); * -# Initialize the operation object with one of the methods described in the * documentation for #psa_pake_operation_t, e.g. * #PSA_PAKE_OPERATION_INIT. - * -# Call psa_pake_setup() to specify the algorithm, the password, cipher - * suite, identities and additional session information. + * -# Call psa_pake_setup() to specify cipher suite. + * -# Call \c psa_pake_set_xxx() functions on the operation to complete the + * setup. The exact sequence of \c psa_pake_set_xxx() functions that needs + * to be called depends on the algorithm in use. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * Like in the case of completing setup, the exact sequence of calls to perform + * a password-authenticated key exchange depends on the algorithm in use: + * - Some algorithms exchange more data than just a single key share. When using + * such a algorithm, call psa_pake_output() and psa_pake_input() one or more + * times to exchange any further data that is needed to derive the shared + * secret. * * A typical sequence of calls to perform a password-authenticated key * exchange: @@ -4353,13 +4360,6 @@ static psa_pake_operation_t psa_pake_operation_init(void); * -# Terminate the operation by a call to psa_pake_get_implicit_key() or * psa_pake_abort(). * - * The exact sequence of calls to perform a password-authenticated key exchange - * depends on the algorithm in use: - * - Some algorithms exchange more data than just a single key share. When using - * such a algorithm, call psa_pake_output() and psa_pake_input() one or more - * times to exchange any further data that is needed to derive the shared - * secret. - * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. @@ -4378,6 +4378,29 @@ static psa_pake_operation_t psa_pake_operation_init(void); * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_pake_operation_t and not yet in use. + * \param cipher_suite The cipher suite to use. (A cipher suite fully + * characterizes a PAKE algorithm and determines + * the algorithm as well.) + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_NOT_SUPPORTED + * The \p cipher_suite is not supported or is not valid. + * \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_pake_setup(psa_pake_operation_t *operation, + psa_pake_cipher_suite_t cipher_suite); + +/** Set the password for a password-authenticated key exchange. + * * \param password Identifier of the key holding the password or a * value derived from the password (eg. by a * memory-hard function). It must remain valid @@ -4385,56 +4408,122 @@ static psa_pake_operation_t psa_pake_operation_init(void); * type PSA_KEY_TYPE_PASSWORD or * #PSA_KEY_TYPE_DERIVE. It has to allow the usage * #PSA_KEY_USAGE_DERIVE. - * \param cipher_suite The cipher suite to use. (A cipher suite fully - * characterizes a PAKE algorithm and determines - * the algorithm as well.) - * \param side A value of type ::psa_pake_side_t signaling the - * side of the algorithm that is being set up. For - * more information see the documentation of \c - * PSA_PAKE_SIDE_XXX constants. - * \param[in] user_id The user ID to authenticate with. - * \param user_id_len Size of the \p user_id buffer in bytes. - * \param[in] peer_id The peer's ID to authenticate. - * \param peer_id_len Size of the \p peer_id buffer in bytes. - * \param[in] session_data Additional session related data if it is allowed - * or required by the algorithm. This must be empty - * if additional session data is not used by the - * algorithm. - * \param session_data_len Size of the \p session_data buffer in bytes. * * \retval #PSA_SUCCESS * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_CORRUPTION_DETECTED * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with the algorithm in \p cipher_suite. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p session_data is not empty and is not allowed in the algorithm in - * \p cipher_suite. - * \retval #PSA_ERROR_NOT_SUPPORTED - * The \p cipher_suite is not supported or is not valid. - * \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_pake_setup(psa_pake_operation_t *operation, - mbedtls_svc_key_id_t password, - psa_pake_cipher_suite_t cipher_suite, - psa_pake_side_t side, - const uint8_t *user_id, - size_t user_id_len, - const uint8_t *peer_id, - size_t peer_id_len, - const uint8_t *session_data, - size_t session_data_len); +psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, + mbedtls_svc_key_id_t password); + +/** Set the user ID for a password-authenticated key exchange. + * + * Some PAKE algorithms assiciate only a single user identifier with the + * session. Such algorithms must call this function (psa_pake_set_user()) to + * set the identifier for the PAKE context. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[in] user_id The user ID to authenticate with. + * \param user_id_len Size of the \p user_id buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p user_id is NULL. + * \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_pake_set_user(psa_pake_operation_t *operation, + const uint8_t *user_id, + size_t user_id_len); + +/** Set the peer ID for a password-authenticated key exchange. + * + * Some PAKE algorithms assiciate only a single user identifier with the + * session. Such algorithms must call psa_pake_set_user() to set the + * identifier for the PAKE context. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[in] peer_id The peer's ID to authenticate. + * \param peer_id_len Size of the \p peer_id buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The algorithm doesn't associate a second identity with the session. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p user_id is NULL. + * \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_pake_set_peer(psa_pake_operation_t *operation, + const uint8_t *peer_id, + size_t peer_id_len); + +/** Set the side for a password-authenticated key exchange. + * + * Not all PAKE algorithms need to differentiate the communicating entities. + * It is optional to call this function for PAKEs that don't require a side + * parameter. For such PAKEs the side parameter is ignored. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param side A value of type ::psa_pake_side_t signaling the + * side of the algorithm that is being set up. For + * more information see the documentation of \c + * PSA_PAKE_SIDE_XXX constants. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must have been set up). + * \retval #PSA_ERROR_NOT_SUPPORTED + * The \p side for this algorithm is not supported or is not valid. + * \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_pake_set_side(psa_pake_operation_t *operation, + psa_pake_side_t side); /** Get additional key share from a password-authenticated key exchange. * diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 06aeec5e4..a92002304 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1985,6 +1985,11 @@ * Implementations of the present specification use Schnorr NIZKP and this does * not need to be configured in the cipher suites. * + * J-PAKE doesn't differentiate between sides and has a distinct identifier + * associated with each entity. This means that both psa_pake_set_user() and + * psa_pake_set_peer() needs to be called before commencing the operation. + * Another conseque is that psa_pake_set_side() is optional and is ignored. + * * The key exchange flow for JPAKE is as follows: * -# To get the first round data that needs to be sent to the peer, call * // Get g1 From 78b9e40662bca1b594537433594dc130fffbc507 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 13 May 2021 11:45:14 +0100 Subject: [PATCH 29/69] PSA PAKE: reintroduce psa_pake_primitive_t If PSA_PAKE_OUTPUT_SIZE takes cipher_suite as a parameter and it is a structure it can't be a compile-time constant anymore. Reintroducing psa_pake_primitive_t, because it can be constructed as an integral type and holds enough information to allow PSA_PAKE_OUTPUT_SIZE calculating accurate estimates on the output size in compile time. Signed-off-by: Janos Follath --- include/psa/crypto.h | 93 ++++--------------------------------- include/psa/crypto_sizes.h | 4 +- include/psa/crypto_struct.h | 53 ++++++--------------- include/psa/crypto_types.h | 6 +++ include/psa/crypto_values.h | 24 ++++++++++ 5 files changed, 55 insertions(+), 125 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index a2f34cab0..ec5c16c48 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4145,107 +4145,30 @@ static void psa_pake_cs_set_algorithm( * This function may be provided as a function-like macro, but in this case it * must evaluate its argument exactly once. * - * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` - * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) - * for more information. - * * \param[in] cipher_suite The cipher suite structure to query. * - * \return The primitive type stored in the cipher suite structure. + * \return The primitive stored in the cipher suite structure. */ -static psa_pake_primitive_type_t psa_pake_cs_get_type( +static psa_pake_primitive_t psa_pake_cs_get_primitive( const psa_pake_cipher_suite_t* cipher_suite ); /** Declare the primitive type for a PAKE cipher suite. * - * This function overwrites any primitive type - * previously set in \p cipher_suite. + * This function overwrites any primitive previously set in \p cipher_suite. * * 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] cipher_suite The cipher suite structure to write to. - * \param type The primitive type to write. - * If this is 0, the primitive type in - * \p cipher_suite becomes unspecified. + * \param primitive The primitive to write. If this is 0, the + * primitive type in \p cipher_suite becomes + * unspecified. */ -static void psa_pake_cs_set_type( +static void psa_pake_cs_set_primitive( psa_pake_cipher_suite_t* cipher_suite, - psa_pake_primitive_type_t type - ); - -/** Retrieve the primitive family from a PAKE cipher suite. - * - * 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] cipher_suite The cipher suite structure to query. - * - * \return The primitive family stored in the cipher suite structure. - */ -static psa_pake_family_t psa_pake_cs_get_family( - const psa_pake_cipher_suite_t* cipher_suite - ); - -/** Declare the primitive family for a PAKE cipher suite. - * - * This function overwrites any primitive family - * previously set in \p cipher_suite. - * - * 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] cipher_suite The cipher suite structure to write to. - * \param family The primitive family to write. - * If this is 0, the primitive family in - * \p cipher_suite becomes unspecified. The - * interpretation of this parameter depends on - * the primitive type. For more information - * consult the documentation of individual - * ::psa_pake_primitive_type_t constants). - */ -static void psa_pake_cs_set_family( - psa_pake_cipher_suite_t* cipher_suite, - psa_pake_family_t family - ); - -/** Retrieve the size associated with the primitive from a PAKE cipher suite. - * - * 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] cipher_suite The cipher suite structure to query. - * - * \return The primitive bits stored in the cipher suite structure. - */ -static size_t psa_pake_cs_get_bits(const psa_pake_cipher_suite_t* cipher_suite); - -/** Declare the primitive bits for a PAKE cipher suite. - * - * This function overwrites any primitive bits - * previously set in \p cipher_suite. - * - * 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] cipher_suite The cipher suite structure to write to. - * \param bits The primitive bits to write. - * If this is 0, the primitive bits in - * \p cipher_suite becomes unspecified. The - * interpretation of this parameter depends on - * the family, for more information consult the - * documentation of individual - * ::psa_pake_primitive_type_t constants). - */ -static void psa_pake_cs_set_bits( - psa_pake_cipher_suite_t* cipher_suite, - size_t bits + psa_pake_primitive_t primitive ); /** Retrieve the hash algorithm from a PAKE cipher suite. diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index 9d2f6c49c..d8fc9979b 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -1143,7 +1143,7 @@ * * \param alg A PAKE algorithm (PSA_ALG_XXX value such that * #PSA_ALG_IS_PAKE(\p alg) is true). - * \param cipher_suite A cipher suite that is compatible with algorithm \p alg. + * \param primitive A primitive that is compatible with algorithm \p alg. * \param output_step A value of type ::psa_pake_step_t that is valid for the * algorithm \p alg. * \return A sufficient output buffer size for the specified @@ -1151,7 +1151,7 @@ * the output type or PAKE algorithm is not recognized, or * the parameters are incompatible, return 0. */ -#define PSA_PAKE_OUTPUT_SIZE(alg, cipher_suite, output_step) +#define PSA_PAKE_OUTPUT_SIZE(alg, primitive, output_step) /** Output buffer size for psa_pake_output() for any of the supported cipher * suites and PAKE algorithms. diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index 97d5d2b41..a5f35cb9c 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -466,10 +466,16 @@ struct psa_pake_cipher_suite_s psa_algorithm_t algorithm; psa_pake_primitive_type_t type; psa_pake_family_t family; - size_t bits; + uint16_t bits; psa_algorithm_t hash; }; +static inline psa_algorithm_t psa_pake_cs_get_algorithm( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return( cipher_suite->algorithm ); +} + static inline void psa_pake_cs_set_algorithm( psa_pake_cipher_suite_t *cipher_suite, psa_algorithm_t algorithm) @@ -480,49 +486,20 @@ static inline void psa_pake_cs_set_algorithm( cipher_suite->algorithm = algorithm; } -static inline psa_algorithm_t psa_pake_cs_get_algorithm( +static inline psa_pake_primitive_t psa_pake_cs_get_primitive( const psa_pake_cipher_suite_t *cipher_suite) { - return( cipher_suite->algorithm ); + return( PSA_PAKE_PRIMITIVE( cipher_suite->type, cipher_suite->family, + cipher_suite->bits) ); } -static inline psa_pake_primitive_type_t psa_pake_cs_get_type( - const psa_pake_cipher_suite_t *cipher_suite) -{ - return( cipher_suite->type ); -} - -static inline void psa_pake_cs_set_type( +static inline void psa_pake_cs_set_primitive( psa_pake_cipher_suite_t *cipher_suite, - psa_pake_primitive_type_t type) + psa_pake_primitive_t primitive) { - cipher_suite->type = type; -} - -static inline psa_pake_family_t psa_pake_cs_get_family( - const psa_pake_cipher_suite_t *cipher_suite) -{ - return( cipher_suite->family ); -} - -static inline void psa_pake_cs_set_family( - psa_pake_cipher_suite_t *cipher_suite, - psa_pake_family_t family) -{ - cipher_suite->family = family; -} - -static inline size_t psa_pake_cs_get_bits( - const psa_pake_cipher_suite_t *cipher_suite) -{ - return( cipher_suite->bits ); -} - -static inline void psa_pake_cs_set_bits( - psa_pake_cipher_suite_t *cipher_suite, - size_t bits) -{ - cipher_suite->bits = bits; + cipher_suite->type = (psa_pake_primitive_type_t) primitive >> 24; + cipher_suite->family = (psa_pake_family_t) ( 0xFF & (primitive >> 16) ); + cipher_suite->bits = (uint16_t) ( 0xFFFF & primitive ); } static inline psa_algorithm_t psa_pake_cs_get_hash( diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h index bf8ab15a7..5418bd76e 100644 --- a/include/psa/crypto_types.h +++ b/include/psa/crypto_types.h @@ -415,5 +415,11 @@ typedef uint8_t psa_pake_primitive_type_t; * PSA_PAKE_PRIMITIVE_TYPE_XXX constants. */ typedef uint8_t psa_pake_family_t; + +/** \brief Encoding of the primitive associated with the PAKE. + * + * For more information see the documentation of the #PSA_PAKE_PRIMITIVE macro. + */ +typedef uint32_t psa_pake_primitive_t; /**@}*/ #endif /* PSA_CRYPTO_TYPES_H */ diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index a92002304..cb4c604a6 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -2546,6 +2546,30 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) */ #define PSA_PAKE_PRIMITIVE_TYPE_DH ((psa_pake_primitive_type_t)0x02) +/** Construct a PAKE primitive from type, family and bitsize. + * + * \param pake_type The type of the primitive + * (value of type ::psa_pake_primitive_type_t). + * \param pake_family The family of the primitive + * (the type and interpretation of this parameter depends + * on \p type, for more information consult the + * documentation of individual ::psa_pake_primitive_type_t + * constants). + * \param pake_bits The bitsize of the primitive + * (Value of type \c size_t. The interpretation + * of this parameter depends on \p family, for more + * information consult the documentation of individual + * ::psa_pake_primitive_type_t constants). + * + * \return The constructed primitive value of type ::psa_pake_primitive_t. + * Return 0 if the requested primitive can't be encoded as + * ::psa_pake_primitive_t. + */ +#define PSA_PAKE_PRIMITIVE(pake_type, pake_family, pake_bits) \ + (pake_bits > 0xFFFF) ? 0 : \ + ((psa_pake_primitive_t) (((pake_type) << 24 | \ + (pake_family) << 16) | (pake_bits))) + /** The key share being sent to or received from the peer. * * Unless the documentation of the PAKE algorithm says otherwise this is a From a71811aa4c4958998a1a750dd99f4cb3be8b249d Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 13 May 2021 11:50:01 +0100 Subject: [PATCH 30/69] Fix typo Signed-off-by: Janos Follath --- include/psa/crypto_values.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index cb4c604a6..9fc84f34d 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -2512,7 +2512,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * specific elliptic curve, using the same mapping that is used for ECC * (::psa_ecc_family_t) keys. * - * (Here \c familiy means the value returned by psa_pake_cs_get_family() and + * (Here \c family means the value returned by psa_pake_cs_get_family() and * \c bits means the value returned by psa_pake_cs_get_bits().) * * Input and output during the operation can involve group elements and scalar @@ -2532,7 +2532,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * a specific Diffie-Hellman group, using the same mapping that is used for * Diffie-Hellman (::psa_dh_family_t) keys. * - * (Here \c familiy means the value returned by psa_pake_cs_get_family() and + * (Here \c family means the value returned by psa_pake_cs_get_family() and * \c bits means the value returned by psa_pake_cs_get_bits().) * * Input and output during the operation can involve group elements and scalar From 3c09c4733342ab0a142df1d7ec263ce4f4bb68e0 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 13 May 2021 11:57:49 +0100 Subject: [PATCH 31/69] PSA PAKE: remove redundant steps PAKE constructions that have multiple key shares will always consume and produce the key shares in numerical order. So using PSA_PAKE_DATA_XXX_X would demand step-sequence validation, and provides no functional utility over having only PSA_PAKE_DATA_XXX. Signed-off-by: Janos Follath --- include/psa/crypto_values.h | 75 ++++++------------------------------- 1 file changed, 12 insertions(+), 63 deletions(-) diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 9fc84f34d..229485e66 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1999,11 +1999,11 @@ * // Get the ZKP proof for x1 * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); * // Get g2 - * psa_pake_output(operation, #PSA_PAKE_DATA_KEY_SHARE_2, ...); + * psa_pake_output(operation, #PSA_PAKE_DATA_KEY_SHARE, ...); * // Get the ZKP public key for x2 - * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PUBLIC_2, ...); + * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PUBLIC, ...); * // Get the ZKP proof for x2 - * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PROOF_2, ...); + * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); * -# To provide the first round data received from the peer to the operation, * call * // Set g3 @@ -2013,26 +2013,26 @@ * // Set the ZKP proof for x3 * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); * // Set g4 - * psa_pake_input(operation, #PSA_PAKE_DATA_KEY_SHARE_2, ...); + * psa_pake_input(operation, #PSA_PAKE_DATA_KEY_SHARE, ...); * // Set the ZKP public key for x4 - * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PUBLIC_2, ...); + * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PUBLIC, ...); * // Set the ZKP proof for x4 - * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PROOF_2, ...); + * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); * -# To get the second round data that needs to be sent to the peer, call * // Get A - * psa_pake_output(operation, #PSA_PAKE_DATA_KEY_SHARE_3, ...); + * psa_pake_output(operation, #PSA_PAKE_DATA_KEY_SHARE, ...); * // Get ZKP public key for x2*s - * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PUBLIC_3, ...); + * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PUBLIC, ...); * // Get ZKP proof for x2*s - * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PROOF_3, ...); + * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); * -# To provide the second round data received from the peer to the operation, * call * // Set B - * psa_pake_input(operation, #PSA_PAKE_DATA_KEY_SHARE_3, ...); + * psa_pake_input(operation, #PSA_PAKE_DATA_KEY_SHARE, ...); * // Set ZKP public key for x4*s - * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PUBLIC_3, ...); + * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PUBLIC, ...); * // Set ZKP proof for x4*s - * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PROOF_3, ...); + * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); * -# To access the shared secret call * // Get Ka=Kb=K * psa_pake_get_implicit_key() @@ -2577,11 +2577,6 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * * For information regarding representation consult the documentation of * individual ::psa_pake_primitive_type_t constants. - * - * Some PAKE algorithms need to exchange several key shares. If that is the - * case, this value marks the first key share sent and the first key share - * received. For values sent or received afterwards, use - * #PSA_PAKE_DATA_KEY_SHARE_2 and #PSA_PAKE_DATA_KEY_SHARE_3. */ #define PSA_PAKE_DATA_KEY_SHARE ((psa_pake_step_t)0x01) @@ -2591,11 +2586,6 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * * For information regarding representation consult the documentation of * individual ::psa_pake_primitive_type_t constants. - * - * Some PAKE algorithms need to perform several zero-knowledge proofs. If that - * is the case, this value marks the first public key sent and the first public - * key received. For values sent or received afterwards, use - * #PSA_PAKE_DATA_ZK_PUBLIC_2 and #PSA_PAKE_DATA_ZK_PUBLIC_3. */ #define PSA_PAKE_DATA_ZK_PUBLIC ((psa_pake_step_t)0x02) @@ -2605,49 +2595,8 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * * For information regarding representation consult the documentation of * individual ::psa_pake_primitive_type_t constants. - * - * Some PAKE algorithms need to perform several zero-knowledge proofs. If that - * is the case, this value marks the first proof sent and the first proof - * received. For values sent or received afterwards, use - * #PSA_PAKE_DATA_ZK_PROOF_2 and #PSA_PAKE_DATA_ZK_PROOF_3. */ #define PSA_PAKE_DATA_ZK_PROOF ((psa_pake_step_t)0x03) -/** Marks the second key share sent and received. - * - * See #PSA_PAKE_DATA_KEY_SHARE. - */ -#define PSA_PAKE_DATA_KEY_SHARE_2 ((psa_pake_step_t)0x04) - -/** Marks the second Schnorr NIZKP public key sent and received. - * - * See #PSA_PAKE_DATA_ZK_PUBLIC. - */ -#define PSA_PAKE_DATA_ZK_PUBLIC_2 ((psa_pake_step_t)0x05) - -/** Marks the second Schnorr NIZKP proof sent and received. - * - * See #PSA_PAKE_DATA_ZK_PROOF. - */ -#define PSA_PAKE_DATA_ZK_PROOF_2 ((psa_pake_step_t)0x06) - -/** Marks the third key share sent and received. - * - * See #PSA_PAKE_DATA_KEY_SHARE. - */ -#define PSA_PAKE_DATA_KEY_SHARE_3 ((psa_pake_step_t)0x07) - -/** Marks the third Schnorr NIZKP public key sent and received. - * - * See #PSA_PAKE_DATA_ZK_PUBLIC. - */ -#define PSA_PAKE_DATA_ZK_PUBLIC_3 ((psa_pake_step_t)0x08) - -/** Marks the third Schnorr NIZKP proof sent and received. - * - * See #PSA_PAKE_DATA_ZK_PROOF. - */ -#define PSA_PAKE_DATA_ZK_PROOF_3 ((psa_pake_step_t)0x09) - /**@}*/ #endif /* PSA_CRYPTO_VALUES_H */ From 56cc9ccc39b45a384a4ad5e60061bb4f49a63bd9 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 13 May 2021 12:01:11 +0100 Subject: [PATCH 32/69] PSA PAKE: Align macro names with psa_pake_step_t Signed-off-by: Janos Follath --- include/psa/crypto.h | 4 ++-- include/psa/crypto_values.h | 44 ++++++++++++++++++------------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index ec5c16c48..5473fbfd0 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4273,9 +4273,9 @@ static psa_pake_operation_t psa_pake_operation_init(void); * * A typical sequence of calls to perform a password-authenticated key * exchange: - * -# Call psa_pake_output(operation, #PSA_PAKE_DATA_KEY_SHARE, ...) to get the + * -# Call psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to get the * key share that needs to be sent to the peer. - * -# Call psa_pake_input(operation, #PSA_PAKE_DATA_KEY_SHARE, ...) to provide + * -# Call psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to provide * the key share that was received from the peer. * -# Call psa_pake_get_implicit_key() for accessing the shared secret. * -# Make a sequence of function calls to execute the password-authenticated diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 229485e66..174a1f1e0 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1993,52 +1993,52 @@ * The key exchange flow for JPAKE is as follows: * -# To get the first round data that needs to be sent to the peer, call * // Get g1 - * psa_pake_output(operation, #PSA_PAKE_DATA_KEY_SHARE, ...); + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Get the ZKP public key for x1 - * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PUBLIC, ...); + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Get the ZKP proof for x1 - * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * // Get g2 - * psa_pake_output(operation, #PSA_PAKE_DATA_KEY_SHARE, ...); + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Get the ZKP public key for x2 - * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PUBLIC, ...); + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Get the ZKP proof for x2 - * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * -# To provide the first round data received from the peer to the operation, * call * // Set g3 - * psa_pake_input(operation, #PSA_PAKE_DATA_KEY_SHARE, ...); + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Set the ZKP public key for x3 - * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PUBLIC, ...); + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Set the ZKP proof for x3 - * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * // Set g4 - * psa_pake_input(operation, #PSA_PAKE_DATA_KEY_SHARE, ...); + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Set the ZKP public key for x4 - * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PUBLIC, ...); + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Set the ZKP proof for x4 - * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * -# To get the second round data that needs to be sent to the peer, call * // Get A - * psa_pake_output(operation, #PSA_PAKE_DATA_KEY_SHARE, ...); + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Get ZKP public key for x2*s - * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PUBLIC, ...); + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Get ZKP proof for x2*s - * psa_pake_output(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * -# To provide the second round data received from the peer to the operation, * call * // Set B - * psa_pake_input(operation, #PSA_PAKE_DATA_KEY_SHARE, ...); + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Set ZKP public key for x4*s - * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PUBLIC, ...); + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Set ZKP proof for x4*s - * psa_pake_input(operation, #PSA_PAKE_DATA_ZK_PROOF, ...); + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * -# To access the shared secret call * // Get Ka=Kb=K * psa_pake_get_implicit_key() * * For more information consult the documentation of the individual - * PSA_PAKE_DATA_XXX constants. + * PSA_PAKE_STEP_XXX constants. * * J-PAKE is standardised for example in RFC 8236. */ @@ -2578,7 +2578,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * For information regarding representation consult the documentation of * individual ::psa_pake_primitive_type_t constants. */ -#define PSA_PAKE_DATA_KEY_SHARE ((psa_pake_step_t)0x01) +#define PSA_PAKE_STEP_KEY_SHARE ((psa_pake_step_t)0x01) /** A Schnorr NIZKP public key. * @@ -2587,7 +2587,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * For information regarding representation consult the documentation of * individual ::psa_pake_primitive_type_t constants. */ -#define PSA_PAKE_DATA_ZK_PUBLIC ((psa_pake_step_t)0x02) +#define PSA_PAKE_STEP_ZK_PUBLIC ((psa_pake_step_t)0x02) /** A Schnorr NIZKP proof. * @@ -2596,7 +2596,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * For information regarding representation consult the documentation of * individual ::psa_pake_primitive_type_t constants. */ -#define PSA_PAKE_DATA_ZK_PROOF ((psa_pake_step_t)0x03) +#define PSA_PAKE_STEP_ZK_PROOF ((psa_pake_step_t)0x03) /**@}*/ #endif /* PSA_CRYPTO_VALUES_H */ From fe0c4493f5a3118d56759ad0f4b4478aadfdb077 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 13 May 2021 12:25:15 +0100 Subject: [PATCH 33/69] Add psa_pake_set_password_mhf() Using memory hard functions with PAKEs is the more secure option. It should be as convenient and efficient to use as less secure options, but so far it required creating an additional temporary key object. With psa_pake_set_password_mhf() this eliminates the need for this. Similarly we could add a convenience function to supply the password directly from character strings, but that would make the less secure option more convenient again and therfore we are not doing it now. Signed-off-by: Janos Follath --- include/psa/crypto.h | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 5473fbfd0..e94a95713 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4322,7 +4322,7 @@ static psa_pake_operation_t psa_pake_operation_init(void); psa_status_t psa_pake_setup(psa_pake_operation_t *operation, psa_pake_cipher_suite_t cipher_suite); -/** Set the password for a password-authenticated key exchange. +/** Set the password for a password-authenticated key exchange from key ID. * * \param password Identifier of the key holding the password or a * value derived from the password (eg. by a @@ -4350,6 +4350,37 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, mbedtls_svc_key_id_t password); +/** Set the password for a password-authenticated key exchange with memory hard + * function. + * + * Some protocols require using values derived from passwords via memory hard + * functions to mitigate dictionary attacks. Memory hard functions can be + * accessed through the key derivation interface and the result can be supplied + * to the PAKE operation in the form of a key derivation object. + * + * \param key_derivation An ongoing key derivation operation set up from + * the password and in a state suitable for + * calling psa_key_derivation_output_bytes(). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key_derivation is not ready for a call to + * psa_key_derivation_output_bytes(). + * \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_pake_set_password_mhf(psa_pake_operation_t *operation, + psa_pake_operation_t *key_derivation); + /** Set the user ID for a password-authenticated key exchange. * * Some PAKE algorithms assiciate only a single user identifier with the From b0bcb633ffb567aaa9ff2a17fe5043df6485bfd7 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 13 May 2021 13:21:43 +0100 Subject: [PATCH 34/69] Link PSA_KEY_TYPE_PASSWORD in the documentation Signed-off-by: Janos Follath --- include/psa/crypto.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index e94a95713..8759d6975 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4328,7 +4328,7 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, * value derived from the password (eg. by a * memory-hard function). It must remain valid * until the operation terminates. It must be of - * type PSA_KEY_TYPE_PASSWORD or + * type #PSA_KEY_TYPE_PASSWORD or * #PSA_KEY_TYPE_DERIVE. It has to allow the usage * #PSA_KEY_USAGE_DERIVE. * From 60fa7c59b26aa1f5eee0aeaca00428159c391b0d Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 13 May 2021 13:36:32 +0100 Subject: [PATCH 35/69] PSA PAKE: document operation parameters Signed-off-by: Janos Follath --- include/psa/crypto.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 8759d6975..f49286ca7 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4324,6 +4324,9 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, /** Set the password for a password-authenticated key exchange from key ID. * + * \param[in,out] operation The operation object to set the password for. It + * must have been set up by psa_pake_setup() and + * not yet in use. * \param password Identifier of the key holding the password or a * value derived from the password (eg. by a * memory-hard function). It must remain valid @@ -4358,6 +4361,9 @@ psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, * accessed through the key derivation interface and the result can be supplied * to the PAKE operation in the form of a key derivation object. * + * \param[in,out] operation The operation object to set the password for. It + * must have been set up by psa_pake_setup() and + * not yet in use. * \param key_derivation An ongoing key derivation operation set up from * the password and in a state suitable for * calling psa_key_derivation_output_bytes(). @@ -4391,6 +4397,9 @@ psa_status_t psa_pake_set_password_mhf(psa_pake_operation_t *operation, * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. * + * \param[in,out] operation The operation object to set the user ID for. It + * must have been set up by psa_pake_setup() and + * not yet in use. * \param[in] user_id The user ID to authenticate with. * \param user_id_len Size of the \p user_id buffer in bytes. * @@ -4423,6 +4432,9 @@ psa_status_t psa_pake_set_user(psa_pake_operation_t *operation, * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. * + * \param[in,out] operation The operation object to set the peer ID for. It + * must have been set up by psa_pake_setup() and + * not yet in use. * \param[in] peer_id The peer's ID to authenticate. * \param peer_id_len Size of the \p peer_id buffer in bytes. * @@ -4457,6 +4469,9 @@ psa_status_t psa_pake_set_peer(psa_pake_operation_t *operation, * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. * + * \param[in,out] operation The operation object to set the side for. It + * must have been set up by psa_pake_setup() and + * not yet in use. * \param side A value of type ::psa_pake_side_t signaling the * side of the algorithm that is being set up. For * more information see the documentation of \c From ed82716546567583b42419338ffd0448f66a6171 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 13 May 2021 14:38:15 +0100 Subject: [PATCH 36/69] Remove always false comparison PSA_PAKE_PRIMITIVE Always false comparison triggered compiler warnings. Removing comparison while preserving semantics to achieve clean build. Signed-off-by: Janos Follath --- include/psa/crypto_values.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 174a1f1e0..94616aad7 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -2566,7 +2566,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * ::psa_pake_primitive_t. */ #define PSA_PAKE_PRIMITIVE(pake_type, pake_family, pake_bits) \ - (pake_bits > 0xFFFF) ? 0 : \ + ((pake_bits & 0xFFFF) != pake_bits) ? 0 : \ ((psa_pake_primitive_t) (((pake_type) << 24 | \ (pake_family) << 16) | (pake_bits))) From ef816f37be9e1d33639152bb4349680c973b8449 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 13 May 2021 16:01:47 +0100 Subject: [PATCH 37/69] Fix precedence in psa_pake_cs_set_primitive() Signed-off-by: Janos Follath --- include/psa/crypto_struct.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index a5f35cb9c..b20a17972 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -497,7 +497,7 @@ static inline void psa_pake_cs_set_primitive( psa_pake_cipher_suite_t *cipher_suite, psa_pake_primitive_t primitive) { - cipher_suite->type = (psa_pake_primitive_type_t) primitive >> 24; + cipher_suite->type = (psa_pake_primitive_type_t) (primitive >> 24); cipher_suite->family = (psa_pake_family_t) ( 0xFF & (primitive >> 16) ); cipher_suite->bits = (uint16_t) ( 0xFFFF & primitive ); } From 14ce06afe270687e6490e038ab5d2e647b193b17 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 14 May 2021 11:26:23 +0100 Subject: [PATCH 38/69] PSA PAKE: fix documentation Signed-off-by: Janos Follath --- include/psa/crypto.h | 6 +++--- include/psa/crypto_values.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index f49286ca7..87b4526eb 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4139,7 +4139,7 @@ static void psa_pake_cs_set_algorithm( psa_algorithm_t algorithm ); -/** Retrieve the primitive type from a PAKE cipher suite. +/** Retrieve the primitive from a PAKE cipher suite. * * 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 @@ -4153,7 +4153,7 @@ static psa_pake_primitive_t psa_pake_cs_get_primitive( const psa_pake_cipher_suite_t* cipher_suite ); -/** Declare the primitive type for a PAKE cipher suite. +/** Declare the primitive for a PAKE cipher suite. * * This function overwrites any primitive previously set in \p cipher_suite. * @@ -4353,7 +4353,7 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, mbedtls_svc_key_id_t password); -/** Set the password for a password-authenticated key exchange with memory hard +/** Set the password for a password-authenticated key exchange via a memory hard * function. * * Some protocols require using values derived from passwords via memory hard diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 94616aad7..d1924db67 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1988,7 +1988,7 @@ * J-PAKE doesn't differentiate between sides and has a distinct identifier * associated with each entity. This means that both psa_pake_set_user() and * psa_pake_set_peer() needs to be called before commencing the operation. - * Another conseque is that psa_pake_set_side() is optional and is ignored. + * Another consequence is that psa_pake_set_side() is optional and is ignored. * * The key exchange flow for JPAKE is as follows: * -# To get the first round data that needs to be sent to the peer, call From 1062a24152c32228ff0750256e84d77f97d39cb8 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 14 May 2021 12:02:55 +0100 Subject: [PATCH 39/69] Fix psa_pake_set_password_mhf() parameter list The type of the key derivation operation was incorrect. Also neither the PAKE nor key_derivation algorithm knows how many bytes to transfer at this stage. There is no optimal or recommended size, PAKEs don't mandate it either (with the exception of OPAQUE, but that uses it internally and won't be using this interface). Adding an input length parameter to allow the application to control how many bytes the PAKE takes from the key derivation. Signed-off-by: Janos Follath --- include/psa/crypto.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 87b4526eb..00317f7ff 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4367,6 +4367,8 @@ psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, * \param key_derivation An ongoing key derivation operation set up from * the password and in a state suitable for * calling psa_key_derivation_output_bytes(). + * \param input_length Number of bytes to input from the + * \p key_derivation operation. * * \retval #PSA_SUCCESS * Success. @@ -4385,7 +4387,8 @@ psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, * results in this error code. */ psa_status_t psa_pake_set_password_mhf(psa_pake_operation_t *operation, - psa_pake_operation_t *key_derivation); + psa_key_derivation_operation_t *key_derivation, + size_t input_length); /** Set the user ID for a password-authenticated key exchange. * From e1a080f1f8c82386da370d2893cf9d2b985d1e51 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 14 May 2021 12:16:36 +0100 Subject: [PATCH 40/69] Improve psa_pake_set_password_mhf() documentation Signed-off-by: Janos Follath --- include/psa/crypto.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 00317f7ff..205c5fd8a 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4361,14 +4361,14 @@ psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, * accessed through the key derivation interface and the result can be supplied * to the PAKE operation in the form of a key derivation object. * - * \param[in,out] operation The operation object to set the password for. It - * must have been set up by psa_pake_setup() and - * not yet in use. - * \param key_derivation An ongoing key derivation operation set up from - * the password and in a state suitable for - * calling psa_key_derivation_output_bytes(). - * \param input_length Number of bytes to input from the - * \p key_derivation operation. + * \param[in,out] operation The operation object to set the password for. + * It must have been set up by psa_pake_setup() + * and not yet in use. + * \param[in,out] key_derivation An ongoing key derivation operation set up + * from the password and in a state suitable for + * calling psa_key_derivation_output_bytes(). + * \param input_length Number of bytes to input from the + * \p key_derivation operation. * * \retval #PSA_SUCCESS * Success. From 7b8910322c701bb85a1ba7690ce1634537f0845a Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 14 May 2021 15:42:46 +0100 Subject: [PATCH 41/69] PSA PAKE: refine documentation of return values The key derivation operation passed to psa_pake_set_password_mhf() might enter an error state before the function returns. If this happens, the user needs to know about it so that they can properly abort it. Signed-off-by: Janos Follath --- include/psa/crypto.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 205c5fd8a..6706ef8ea 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4337,6 +4337,8 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must have been set up.) * \retval #PSA_ERROR_CORRUPTION_DETECTED * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_COMMUNICATION_FAILURE @@ -4361,6 +4363,16 @@ psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, * accessed through the key derivation interface and the result can be supplied * to the PAKE operation in the form of a key derivation object. * + * This function draws bytes from a key derivation algorithm and sets those + * bytes as a password for the password-authenticated key exchange. 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 key derivation operation's capacity decreases by the number of bytes read. + * + * If this function returns #PSA_ERROR_INVALID_ARGUMENT, \p key_derivation + * enters an error state and must be aborted by calling + * psa_key_derivation_abort(). + * * \param[in,out] operation The operation object to set the password for. * It must have been set up by psa_pake_setup() * and not yet in use. @@ -4372,6 +4384,11 @@ psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must have been set up.) + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The \p key_derivation operation's capacity was less than + * \p input_length bytes. * \retval #PSA_ERROR_CORRUPTION_DETECTED * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_COMMUNICATION_FAILURE @@ -4379,8 +4396,8 @@ psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, * \retval #PSA_ERROR_STORAGE_FAILURE * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p key_derivation is not ready for a call to - * psa_key_derivation_output_bytes(). + * The call to psa_key_derivation_output_bytes() returned something + * other than #PSA_ERROR_INSUFFICIENT_DATA. * \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 @@ -4409,7 +4426,7 @@ psa_status_t psa_pake_set_password_mhf(psa_pake_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid. + * The operation state is not valid (it must have been set up.) * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE @@ -4444,7 +4461,7 @@ psa_status_t psa_pake_set_user(psa_pake_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid. + * The operation state is not valid (it must have been set up.) * \retval #PSA_ERROR_NOT_SUPPORTED * The algorithm doesn't associate a second identity with the session. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY From 9a04aeaff5e01abde65a972030e23ce9cf700c99 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 20 May 2021 16:21:01 +0100 Subject: [PATCH 42/69] PSA PAKE: improve and fix documentation Signed-off-by: Janos Follath --- include/psa/crypto.h | 30 ++++++++++++++++++------------ include/psa/crypto_sizes.h | 3 ++- include/psa/crypto_types.h | 6 +++--- include/psa/crypto_values.h | 12 ++++++------ 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 6706ef8ea..fa4102278 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4092,7 +4092,7 @@ psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, /**@}*/ -/** \defgroup Password-authenticated key agreement +/** \defgroup pake Password-authenticated key exchange (PAKE) * @{ */ @@ -4255,7 +4255,7 @@ static psa_pake_operation_t psa_pake_operation_init(void); * -# Initialize the operation object with one of the methods described in the * documentation for #psa_pake_operation_t, e.g. * #PSA_PAKE_OPERATION_INIT. - * -# Call psa_pake_setup() to specify cipher suite. + * -# Call psa_pake_setup() to specify the cipher suite. * -# Call \c psa_pake_set_xxx() functions on the operation to complete the * setup. The exact sequence of \c psa_pake_set_xxx() functions that needs * to be called depends on the algorithm in use. @@ -4323,6 +4323,11 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, psa_pake_cipher_suite_t cipher_suite); /** Set the password for a password-authenticated key exchange from key ID. + * + * Call this function when the password, or a value derived from the password, + * is already present in the key store. To calculate the password-derived value + * from a password input, use the key derivation interface and + * psa_pake_set_password_stretch() instead. * * \param[in,out] operation The operation object to set the password for. It * must have been set up by psa_pake_setup() and @@ -4332,8 +4337,8 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, * memory-hard function). It must remain valid * until the operation terminates. It must be of * type #PSA_KEY_TYPE_PASSWORD or - * #PSA_KEY_TYPE_DERIVE. It has to allow the usage - * #PSA_KEY_USAGE_DERIVE. + * #PSA_KEY_TYPE_PASSWORD_HASH. It has to allow + * the usage #PSA_KEY_USAGE_DERIVE. * * \retval #PSA_SUCCESS * Success. @@ -4409,7 +4414,7 @@ psa_status_t psa_pake_set_password_mhf(psa_pake_operation_t *operation, /** Set the user ID for a password-authenticated key exchange. * - * Some PAKE algorithms assiciate only a single user identifier with the + * Some PAKE algorithms associate only a single user identifier with the * session. Such algorithms must call this function (psa_pake_set_user()) to * set the identifier for the PAKE context. * @@ -4444,7 +4449,7 @@ psa_status_t psa_pake_set_user(psa_pake_operation_t *operation, /** Set the peer ID for a password-authenticated key exchange. * - * Some PAKE algorithms assiciate only a single user identifier with the + * Some PAKE algorithms associate only a single user identifier with the * session. Such algorithms must call psa_pake_set_user() to set the * identifier for the PAKE context. * @@ -4514,7 +4519,7 @@ psa_status_t psa_pake_set_peer(psa_pake_operation_t *operation, psa_status_t psa_pake_set_side(psa_pake_operation_t *operation, psa_pake_side_t side); -/** Get additional key share from a password-authenticated key exchange. +/** Get output for a step of a password-authenticated key exchange. * * Depending on the algorithm being executed, you might need to call this * function several times or you might not need to call this at all. @@ -4529,7 +4534,8 @@ psa_status_t psa_pake_set_side(psa_pake_operation_t *operation, * state and must be aborted by calling psa_pake_abort(). * * \param[in,out] operation Active PAKE operation. - * \param type The type of the data that is requested. + * \param step The step of the algorithm for which the output is + * requested. * \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_PAKE_OUTPUT_SIZE(\p alg, \c @@ -4556,12 +4562,12 @@ psa_status_t psa_pake_set_side(psa_pake_operation_t *operation, * results in this error code. */ psa_status_t psa_pake_output(psa_pake_operation_t *operation, - psa_pake_step_t type, + psa_pake_step_t step, uint8_t *output, size_t output_size, size_t *output_length); -/** Provide additional peer key share for a password-authenticated key exchange. +/** Provide input for a step of a password-authenticated key exchange. * * Depending on the algorithm being executed, you might need to call this * function several times or you might not need to call this at all. @@ -4576,7 +4582,7 @@ psa_status_t psa_pake_output(psa_pake_operation_t *operation, * state and must be aborted by calling psa_pake_abort(). * * \param[in,out] operation Active PAKE operation. - * \param type The type of the data provided. + * \param step The step for which the input is provided. * \param[out] input Buffer containing the input. * \param[out] input_length Size of the \p input buffer in bytes. * @@ -4596,7 +4602,7 @@ psa_status_t psa_pake_output(psa_pake_operation_t *operation, * results in this error code. */ psa_status_t psa_pake_input(psa_pake_operation_t *operation, - psa_pake_step_t type, + psa_pake_step_t step, uint8_t *input, size_t input_length); diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index d8fc9979b..a603c9d29 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -1143,7 +1143,8 @@ * * \param alg A PAKE algorithm (PSA_ALG_XXX value such that * #PSA_ALG_IS_PAKE(\p alg) is true). - * \param primitive A primitive that is compatible with algorithm \p alg. + * \param primitive A primitive of type ::psa_pake_primitive_t that is + * compatible with algorithm \p alg. * \param output_step A value of type ::psa_pake_step_t that is valid for the * algorithm \p alg. * \return A sufficient output buffer size for the specified diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h index 5418bd76e..5a66a8709 100644 --- a/include/psa/crypto_types.h +++ b/include/psa/crypto_types.h @@ -387,7 +387,7 @@ typedef uint16_t psa_key_derivation_step_t; /** \brief Encoding of the side of PAKE * * Encodes which side of the algorithm is being executed. For more information - * see the documentation of individual PSA_PAKE_SIDE_XXX constants. + * see the documentation of individual \c PSA_PAKE_SIDE_XXX constants. */ typedef uint8_t psa_pake_side_t; @@ -405,14 +405,14 @@ typedef uint8_t psa_pake_step_t; * Vendors who define additional types must use an encoding in this range. * * For more information see the documentation of individual - * PSA_PAKE_PRIMITIVE_TYPE_XXX constants. + * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. */ typedef uint8_t psa_pake_primitive_type_t; /** \brief Encoding of the family of the primitive associated with the PAKE. * * For more information see the documentation of individual - * PSA_PAKE_PRIMITIVE_TYPE_XXX constants. + * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. */ typedef uint8_t psa_pake_family_t; diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index d1924db67..c8a074cae 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1975,7 +1975,7 @@ * cipher suite the field or curve must be fully specified by calling * psa_pake_cs_set_family() and psa_pake_cs_set_bits() as well. For more * information refer to the documentation of the individual - * `PSA_PAKE_PRIMITIVE_TYPE_XXX` constants.) + * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants.) * * J-PAKE can be used with any secure cryptographic hash function. The choice * of hash must be supplied to the cipher suite by calling @@ -1987,7 +1987,7 @@ * * J-PAKE doesn't differentiate between sides and has a distinct identifier * associated with each entity. This means that both psa_pake_set_user() and - * psa_pake_set_peer() needs to be called before commencing the operation. + * psa_pake_set_peer() need to be called before commencing the operation. * Another consequence is that psa_pake_set_side() is optional and is ignored. * * The key exchange flow for JPAKE is as follows: @@ -2038,7 +2038,7 @@ * psa_pake_get_implicit_key() * * For more information consult the documentation of the individual - * PSA_PAKE_STEP_XXX constants. + * \c PSA_PAKE_STEP_XXX constants. * * J-PAKE is standardised for example in RFC 8236. */ @@ -2480,7 +2480,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * * Although balanced PAKE algorithms are symmetric, some of them needs an * ordering of peers for the transcript calculations. If the algorithm does not - * need this, either #PSA_PAKE_SIDE_FIRST or #PSA_PAKE_SIDE_SECOND are + * need this, both #PSA_PAKE_SIDE_FIRST and #PSA_PAKE_SIDE_SECOND are * accepted. */ #define PSA_PAKE_SIDE_FIRST ((psa_pake_side_t)0x01) @@ -2546,7 +2546,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) */ #define PSA_PAKE_PRIMITIVE_TYPE_DH ((psa_pake_primitive_type_t)0x02) -/** Construct a PAKE primitive from type, family and bitsize. +/** Construct a PAKE primitive from type, family and bit-size. * * \param pake_type The type of the primitive * (value of type ::psa_pake_primitive_type_t). @@ -2555,7 +2555,7 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) * on \p type, for more information consult the * documentation of individual ::psa_pake_primitive_type_t * constants). - * \param pake_bits The bitsize of the primitive + * \param pake_bits The bit-size of the primitive * (Value of type \c size_t. The interpretation * of this parameter depends on \p family, for more * information consult the documentation of individual From 19271ea1833b3fb24e9ca4e940cfcb87357fcd72 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 21 May 2021 12:38:12 +0100 Subject: [PATCH 43/69] PSA PAKE: Clarify documentation of valid states Signed-off-by: Janos Follath --- include/psa/crypto.h | 72 ++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index fa4102278..ce941ed2e 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4300,7 +4300,9 @@ static psa_pake_operation_t psa_pake_operation_init(void); * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for - * #psa_pake_operation_t and not yet in use. + * #psa_pake_operation_t and not yet in use (no + * other function has been called on it since the + * last initialization). * \param cipher_suite The cipher suite to use. (A cipher suite fully * characterizes a PAKE algorithm and determines * the algorithm as well.) @@ -4308,7 +4310,7 @@ static psa_pake_operation_t psa_pake_operation_init(void); * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be inactive). + * The operation state is not valid. * \retval #PSA_ERROR_NOT_SUPPORTED * The \p cipher_suite is not supported or is not valid. * \retval #PSA_ERROR_COMMUNICATION_FAILURE @@ -4331,7 +4333,13 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, * * \param[in,out] operation The operation object to set the password for. It * must have been set up by psa_pake_setup() and - * not yet in use. + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the password hasn't + * been set yet (neither + * psa_pake_set_password_mhf() nor + * psa_pake_set_password_key() has been called + * yet). * \param password Identifier of the key holding the password or a * value derived from the password (eg. by a * memory-hard function). It must remain valid @@ -4374,13 +4382,19 @@ psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, * destructively reads the requested number of bytes from the stream. * The key derivation operation's capacity decreases by the number of bytes read. * - * If this function returns #PSA_ERROR_INVALID_ARGUMENT, \p key_derivation - * enters an error state and must be aborted by calling - * psa_key_derivation_abort(). + * If this function returns anything other than #PSA_SUCCESS, both \p operation + * and \p key_derivation operations enter an error state and must be aborted by + * calling psa_pake_abort() and psa_key_derivation_abort() respectively. * * \param[in,out] operation The operation object to set the password for. * It must have been set up by psa_pake_setup() - * and not yet in use. + * and not yet in use (neither psa_pake_output() + * nor psa_pake_input() has been called yet). It + * must be on operation for which the password + * hasn't been set yet (neither + * psa_pake_set_password_mhf() nor + * psa_pake_set_password_key() has been called + * yet). * \param[in,out] key_derivation An ongoing key derivation operation set up * from the password and in a state suitable for * calling psa_key_derivation_output_bytes(). @@ -4390,7 +4404,7 @@ psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must have been set up.) + * The state of \p operation or \p key_derivation is not valid. * \retval #PSA_ERROR_INSUFFICIENT_DATA * The \p key_derivation operation's capacity was less than * \p input_length bytes. @@ -4400,9 +4414,8 @@ psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, * \retval #PSA_ERROR_HARDWARE_FAILURE * \retval #PSA_ERROR_STORAGE_FAILURE * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The call to psa_key_derivation_output_bytes() returned something - * other than #PSA_ERROR_INSUFFICIENT_DATA. + * One of the inputs to \p key_derivation was a key whose policy didn't + * allow #PSA_KEY_USAGE_DERIVE. * \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 @@ -4424,14 +4437,18 @@ psa_status_t psa_pake_set_password_mhf(psa_pake_operation_t *operation, * * \param[in,out] operation The operation object to set the user ID for. It * must have been set up by psa_pake_setup() and - * not yet in use. + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the user ID hasn't + * been set (psa_pake_set_user() hasn't been + * called yet). * \param[in] user_id The user ID to authenticate with. * \param user_id_len Size of the \p user_id buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must have been set up.) + * The operation state is not valid. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE @@ -4459,14 +4476,18 @@ psa_status_t psa_pake_set_user(psa_pake_operation_t *operation, * * \param[in,out] operation The operation object to set the peer ID for. It * must have been set up by psa_pake_setup() and - * not yet in use. + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the peer ID hasn't + * been set (psa_pake_set_peer() hasn't been + * called yet). * \param[in] peer_id The peer's ID to authenticate. * \param peer_id_len Size of the \p peer_id buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must have been set up.) + * The operation state is not valid. * \retval #PSA_ERROR_NOT_SUPPORTED * The algorithm doesn't associate a second identity with the session. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY @@ -4496,7 +4517,11 @@ psa_status_t psa_pake_set_peer(psa_pake_operation_t *operation, * * \param[in,out] operation The operation object to set the side for. It * must have been set up by psa_pake_setup() and - * not yet in use. + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the side hasn't been + * set (psa_pake_set_side() hasn't been called + * yet). * \param side A value of type ::psa_pake_side_t signaling the * side of the algorithm that is being set up. For * more information see the documentation of \c @@ -4505,7 +4530,7 @@ psa_status_t psa_pake_set_peer(psa_pake_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must have been set up). + * The operation state is not valid. * \retval #PSA_ERROR_NOT_SUPPORTED * The \p side for this algorithm is not supported or is not valid. * \retval #PSA_ERROR_COMMUNICATION_FAILURE @@ -4602,9 +4627,9 @@ psa_status_t psa_pake_output(psa_pake_operation_t *operation, * results in this error code. */ psa_status_t psa_pake_input(psa_pake_operation_t *operation, - psa_pake_step_t step, - uint8_t *input, - size_t input_length); + psa_pake_step_t step, + uint8_t *input, + size_t input_length); /** Get implicitly confirmed shared secret from a PAKE. * @@ -4620,9 +4645,10 @@ psa_status_t psa_pake_input(psa_pake_operation_t *operation, * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more * information. * - * 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 psa_pake_abort(). + * When this function returns successfully, \p operation becomes inactive. + * If this function returns an error status, both \p operation + * and \p key_derivation operations enter an error state and must be aborted by + * calling psa_pake_abort() and psa_key_derivation_abort() respectively. * * \param[in,out] operation Active PAKE operation. * \param[out] output A key derivation operation that is ready From 3ae6696811089c7211a69139fed840e489798b42 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 24 May 2021 12:09:00 +0100 Subject: [PATCH 44/69] Clarify psa_pake_setup() documentation Signed-off-by: Janos Follath --- include/psa/crypto.h | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index ce941ed2e..02ed57557 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4264,24 +4264,15 @@ static psa_pake_operation_t psa_pake_operation_init(void); * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. * - * Like in the case of completing setup, the exact sequence of calls to perform - * a password-authenticated key exchange depends on the algorithm in use: - * - Some algorithms exchange more data than just a single key share. When using - * such a algorithm, call psa_pake_output() and psa_pake_input() one or more - * times to exchange any further data that is needed to derive the shared - * secret. - * * A typical sequence of calls to perform a password-authenticated key * exchange: * -# Call psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to get the * key share that needs to be sent to the peer. * -# Call psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to provide * the key share that was received from the peer. + * -# Depending on the algorithm additional calls to psa_pake_output() and + * psa_pake_input() might be necessary. * -# Call psa_pake_get_implicit_key() for accessing the shared secret. - * -# Make a sequence of function calls to execute the password-authenticated - * key exchange as described below. - * -# Terminate the operation by a call to psa_pake_get_implicit_key() or - * psa_pake_abort(). * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) From d416838ffd590563e819e7a1fac8f4389b216b3c Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 24 May 2021 12:20:12 +0100 Subject: [PATCH 45/69] Rename psa_pake_set_password_mhf() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This step is not necessarily a memory-hard function. Memory-hard functions are the best of the breed at the moment, but that's due to current hardware designs, and CPU-hard-but-not-memory-hard functions like PBKDF2 are acceptable as well. We're using “key stretching” as the generic term for such functions. Signed-off-by: Janos Follath --- include/psa/crypto.h | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 02ed57557..abf3da0df 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4328,7 +4328,7 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, * psa_pake_input() has been called yet). It must * be on operation for which the password hasn't * been set yet (neither - * psa_pake_set_password_mhf() nor + * psa_pake_set_password_stretch() nor * psa_pake_set_password_key() has been called * yet). * \param password Identifier of the key holding the password or a @@ -4359,11 +4359,11 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, mbedtls_svc_key_id_t password); -/** Set the password for a password-authenticated key exchange via a memory hard - * function. +/** Set the password for a password-authenticated key exchange via a key + * stretching function. * - * Some protocols require using values derived from passwords via memory hard - * functions to mitigate dictionary attacks. Memory hard functions can be + * Some protocols use values derived from passwords via key stretching + * functions to mitigate dictionary attacks. Key stretching functions can be * accessed through the key derivation interface and the result can be supplied * to the PAKE operation in the form of a key derivation object. * @@ -4383,7 +4383,7 @@ psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, * nor psa_pake_input() has been called yet). It * must be on operation for which the password * hasn't been set yet (neither - * psa_pake_set_password_mhf() nor + * psa_pake_set_password_stretch() nor * psa_pake_set_password_key() has been called * yet). * \param[in,out] key_derivation An ongoing key derivation operation set up @@ -4412,9 +4412,11 @@ psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_pake_set_password_mhf(psa_pake_operation_t *operation, - psa_key_derivation_operation_t *key_derivation, - size_t input_length); +psa_status_t psa_pake_set_password_stretch( + psa_pake_operation_t *operation, + psa_key_derivation_operation_t *key_derivation, + size_t input_length + ); /** Set the user ID for a password-authenticated key exchange. * From ead0e4fc7b6b9be06992d4e584f6eb93b0c899bc Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 25 May 2021 14:16:52 +0100 Subject: [PATCH 46/69] PSA PAKE: Clarify J-PAKE algorithm documentation - Transformed setup description to a more explicit pseudocode based approach. - Explained implicit vs explicit key confirmation Signed-off-by: Janos Follath --- include/psa/crypto.h | 4 ++- include/psa/crypto_values.h | 65 +++++++++++++++++++++++++------------ 2 files changed, 48 insertions(+), 21 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index abf3da0df..2fe797a3b 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4350,7 +4350,7 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, * \retval #PSA_ERROR_STORAGE_FAILURE * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p key is not compatible with the algorithm in \p cipher_suite. + * \p key is not compatible with the algorithm or the cipher suite. * \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 @@ -4407,6 +4407,8 @@ psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, * \retval #PSA_ERROR_NOT_PERMITTED * One of the inputs to \p key_derivation was a key whose policy didn't * allow #PSA_KEY_USAGE_DERIVE. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with the algorithm or the cipher suite. * \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 diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index c8a074cae..527b9c30d 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1968,29 +1968,44 @@ /** The Password-authenticated key exchange by juggling (J-PAKE) algorithm. * - * J-PAKE can be instantiated over finite fields or elliptic curves. This can - * be achieved by setting either #PSA_PAKE_PRIMITIVE_TYPE_DH or - * #PSA_PAKE_PRIMITIVE_TYPE_ECC respectively in the cipher suite (see - * ::psa_pake_cipher_suite_t) via psa_pake_cs_set_type(). (Before using the - * cipher suite the field or curve must be fully specified by calling - * psa_pake_cs_set_family() and psa_pake_cs_set_bits() as well. For more - * information refer to the documentation of the individual - * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants.) + * This is J-PAKE as defined by RFC 8236, instantiated with the following + * parameters: * - * J-PAKE can be used with any secure cryptographic hash function. The choice - * of hash must be supplied to the cipher suite by calling - * psa_pake_cs_set_hash(). + * - The group can be either an elliptic curve or defined over a finite field. + * - Schnorr NIZK proof as defined by RFC 8235 and using the same group as the + * J-PAKE algorithm. + * - A secure cryptographic hash function. * - * In theory the algorithm works with any non-interactive zero-knowledge proof. - * Implementations of the present specification use Schnorr NIZKP and this does - * not need to be configured in the cipher suites. + * To select these parameters and set up the cipher suite, call + * psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_PAKE_JPAKE); + * psa_pake_cs_set_primitive(cipher_suite, + * PSA_PAKE_PRIMITIVE(type, family, bits)); + * psa_pake_cs_set_hash(cipher_suite, hash); * - * J-PAKE doesn't differentiate between sides and has a distinct identifier - * associated with each entity. This means that both psa_pake_set_user() and - * psa_pake_set_peer() need to be called before commencing the operation. - * Another consequence is that psa_pake_set_side() is optional and is ignored. + * For more information on how to set a specific curve or field, refer to the + * documentation of the individual \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. * - * The key exchange flow for JPAKE is as follows: + * After initializing a J-PAKE operation, call + * psa_pake_setup(operation, cipher_suite); + * psa_pake_set_user(operation, ...); + * psa_pake_set_peer(operation, ...); + * and either + * psa_pake_set_password_stretch(operation, ...); + * or + * psa_pake_set_password_key(operation, ...); + * + * Either way the password is read as a byte array and must be non-empty. This + * can be the password itself (in some pre-defined character encoding) or some + * value derived from the password as mandated by some higher level protocol. + * + * (The implementation converts this byte array to a number as described in + * Section 2.3.8 of _SEC 1: Elliptic Curve Cryptography_ + * (https://www.secg.org/sec1-v2.pdf), before reducing it modulo \c q. Here + * \c q is order of the group defined by the primitive set in the cipher suite. + * The \c psa_pake_set_password_xxx() functions return an error if the result + * of the reduction is 0.) + * + * The key exchange flow for J-PAKE is as follows: * -# To get the first round data that needs to be sent to the peer, call * // Get g1 * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); @@ -2040,7 +2055,17 @@ * For more information consult the documentation of the individual * \c PSA_PAKE_STEP_XXX constants. * - * J-PAKE is standardised for example in RFC 8236. + * At this point there is a cryptographic guarantee that only the authenticated + * party who used the same password is able to compute the key. But there is no + * guarantee that the peer is the party he claims to be and was able to do so. + * + * That is, the authentication is only implicit (the peer is not authenticated + * at this point, and no action should be taken that assume that they are - like + * for example accessing restricted files). + * + * To make the authentication explicit there are various methods, see Section 5 + * of RFC 8236 for two examples. + * */ #define PSA_ALG_PAKE_JPAKE ((psa_algorithm_t)0x0a000100) From 56a4d7a59fb171f4c16ca4fde54ba04aaf7e8d91 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 25 May 2021 15:35:11 +0100 Subject: [PATCH 47/69] Simplify PAKE input/output format documentation Make input/output format documentation easier to find: - Add direct reference to the steps from the input/output functions - Move the format description directly to the step constants Signed-off-by: Janos Follath --- include/psa/crypto.h | 12 ++++++++++-- include/psa/crypto_values.h | 38 +++++++++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 2fe797a3b..3df82d91d 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4556,7 +4556,11 @@ psa_status_t psa_pake_set_side(psa_pake_operation_t *operation, * \param[in,out] operation Active PAKE operation. * \param step The step of the algorithm for which the output is * requested. - * \param[out] output Buffer where the output is to be written. + * \param[out] output Buffer where the output is to be written in the + * format appropriate for this \p step. Refer to + * the documentation of the individual + * \c PSA_PAKE_STEP_XXX constants for more + * information. * \param output_size Size of the \p output buffer in bytes. This must * be at least #PSA_PAKE_OUTPUT_SIZE(\p alg, \c * cipher_suite, \p type). @@ -4603,7 +4607,11 @@ psa_status_t psa_pake_output(psa_pake_operation_t *operation, * * \param[in,out] operation Active PAKE operation. * \param step The step for which the input is provided. - * \param[out] input Buffer containing the input. + * \param[out] input Buffer containing the input in the format + * appropriate for this \p step. Refer to the + * documentation of the individual + * \c PSA_PAKE_STEP_XXX constants for more + * information. * \param[out] input_length Size of the \p input buffer in bytes. * * \retval #PSA_SUCCESS diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 527b9c30d..ab9bb5b8b 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -2597,29 +2597,47 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) /** The key share being sent to or received from the peer. * - * Unless the documentation of the PAKE algorithm says otherwise this is a - * group element. + * The format for both input and output at this step is the same as for public + * keys on the group determined by the primitive (::psa_pake_primitive_t) would + * be. * - * For information regarding representation consult the documentation of - * individual ::psa_pake_primitive_type_t constants. + * For more information on the format, consult the documentation of + * psa_export_public_key(). + * + * For information regarding how the group is determined, consult the + * documentation #PSA_PAKE_PRIMITIVE. */ #define PSA_PAKE_STEP_KEY_SHARE ((psa_pake_step_t)0x01) /** A Schnorr NIZKP public key. * - * This is a group element. + * The format for both input and output at this step is the same as for public + * keys on the group determined by the primitive (::psa_pake_primitive_t) would + * be. * - * For information regarding representation consult the documentation of - * individual ::psa_pake_primitive_type_t constants. + * For more information on the format, consult the documentation of + * psa_export_public_key(). + * + * For information regarding how the group is determined, consult the + * documentation #PSA_PAKE_PRIMITIVE. */ #define PSA_PAKE_STEP_ZK_PUBLIC ((psa_pake_step_t)0x02) /** A Schnorr NIZKP proof. * - * This is a scalar value. + * The format for both input and output at this step is the same as for private + * keys on the group determined by the primitive (::psa_pake_primitive_t) would + * be. * - * For information regarding representation consult the documentation of - * individual ::psa_pake_primitive_type_t constants. + * Some public key algorithms mask the private keys and this might be reflected + * in the export format. Even if this is the case the masking is omitted at + * this step. + * + * For more information on the format, consult the documentation of + * psa_export_key(). + * + * For information regarding how the group is determined, consult the + * documentation #PSA_PAKE_PRIMITIVE. */ #define PSA_PAKE_STEP_ZK_PROOF ((psa_pake_step_t)0x03) From 7c59b7a073fc6430bda38177769eb4e93c82ba0e Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 25 May 2021 15:46:56 +0100 Subject: [PATCH 48/69] Improve psa_pake_set_peer()/user() documentation Signed-off-by: Janos Follath --- include/psa/crypto.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 3df82d91d..2d4c80df9 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4422,9 +4422,10 @@ psa_status_t psa_pake_set_password_stretch( /** Set the user ID for a password-authenticated key exchange. * - * Some PAKE algorithms associate only a single user identifier with the - * session. Such algorithms must call this function (psa_pake_set_user()) to - * set the identifier for the PAKE context. + * Call this function to set the user ID. For PAKE algorithms that associate a + * user identifier with each side of the session you need to call + * psa_pake_set_peer() as well. For PAKE algorithms that associate a single + * user identifier with the session, call psa_pake_set_user() only. * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) @@ -4461,9 +4462,10 @@ psa_status_t psa_pake_set_user(psa_pake_operation_t *operation, /** Set the peer ID for a password-authenticated key exchange. * - * Some PAKE algorithms associate only a single user identifier with the - * session. Such algorithms must call psa_pake_set_user() to set the - * identifier for the PAKE context. + * Call this function in addition to psa_pake_set_user() for PAKE algorithms + * that associate a user identifier with each side of the session. For PAKE + * algorithms that associate a single user identifier with the session, call + * psa_pake_set_user() only. * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) From 79e1c47a54c0504b42827343df0b61a2e10ef721 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 25 May 2021 15:53:13 +0100 Subject: [PATCH 49/69] PSA PAKE: explain implicit key confirmation Signed-off-by: Janos Follath --- include/psa/crypto.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 2d4c80df9..bbdd06d5a 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4637,6 +4637,14 @@ psa_status_t psa_pake_input(psa_pake_operation_t *operation, size_t input_length); /** Get implicitly confirmed shared secret from a PAKE. + * + * At this point there is a cryptographic guarantee that only the authenticated + * party who used the same password is able to compute the key. But there is no + * guarantee that the peer is the party he claims to be and was able to do so. + * + * That is, the authentication is only implicit (the peer is not authenticated + * at this point, and no action should be taken that assume that they are - like + * for example accessing restricted files). * * This function can be called after the key exchange phase of the operation * has completed. It imports the shared secret output of the PAKE into the From 5e1948d2a311a64254265431a4ab8d10024b7941 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 26 May 2021 09:27:03 +0100 Subject: [PATCH 50/69] PSA PAKE: define size macros as 0 Define the size macros to 0 rather than empty. That will lead to fewer weird errors when we start implementing. Signed-off-by: Janos Follath --- include/psa/crypto_sizes.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index a603c9d29..a1b89446e 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -1152,7 +1152,7 @@ * the output type or PAKE algorithm is not recognized, or * the parameters are incompatible, return 0. */ -#define PSA_PAKE_OUTPUT_SIZE(alg, primitive, output_step) +#define PSA_PAKE_OUTPUT_SIZE(alg, primitive, output_step) 0 /** Output buffer size for psa_pake_output() for any of the supported cipher * suites and PAKE algorithms. @@ -1161,6 +1161,6 @@ * * See also #PSA_PAKE_OUTPUT_SIZE(\p alg, \p cipher_suite, \p output). */ -#define PSA_PAKE_OUTPUT_MAX_SIZE +#define PSA_PAKE_OUTPUT_MAX_SIZE 0 #endif /* PSA_CRYPTO_SIZES_H */ From a2959185969fd26fb42643e135ae5ce4672d5eac Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 26 May 2021 09:41:39 +0100 Subject: [PATCH 51/69] PSA PAKE: add input size macros The caller is likely to receive the inputs on the wire, and having a known size for which they can confidently reject longer inputs would be helpful in cases where the application can't just use the input in place. Signed-off-by: Janos Follath --- include/psa/crypto.h | 2 ++ include/psa/crypto_sizes.h | 36 ++++++++++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index bbdd06d5a..e84c757d1 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4626,6 +4626,8 @@ psa_status_t psa_pake_output(psa_pake_operation_t *operation, * \retval #PSA_ERROR_HARDWARE_FAILURE * \retval #PSA_ERROR_CORRUPTION_DETECTED * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The input is not valid for the algorithm, ciphersuite or \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 diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index a1b89446e..62254fab5 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -1134,10 +1134,9 @@ /** A sufficient output buffer size for psa_pake_output(). * - * If the size of the ciphertext buffer is at least this large, it is - * guaranteed that psa_pake_output() will not fail due to an - * insufficient ciphertext buffer size. The actual size of the output might be - * smaller in any given call. + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_pake_output() will not fail due to an insufficient output buffer + * size. The actual size of the output might be smaller in any given call. * * See also #PSA_PAKE_OUTPUT_MAX_SIZE * @@ -1154,6 +1153,26 @@ */ #define PSA_PAKE_OUTPUT_SIZE(alg, primitive, output_step) 0 +/** A sufficient input buffer size for psa_pake_input(). + * + * If the size of the input is larger than this, it is guaranteed + * that psa_pake_input() will fail with #PSA_ERROR_INVALID_ARGUMENT. + * + * See also #PSA_PAKE_INPUT_MAX_SIZE + * + * \param alg A PAKE algorithm (PSA_ALG_XXX value such that + * #PSA_ALG_IS_PAKE(\p alg) is true). + * \param primitive A primitive of type ::psa_pake_primitive_t that is + * compatible with algorithm \p alg. + * \param output_step A value of type ::psa_pake_step_t that is valid for the + * algorithm \p alg. + * \return A sufficient output buffer size for the specified + * output, cipher suite and algorithm. If the cipher suite, + * the output type or PAKE algorithm is not recognized, or + * the parameters are incompatible, return 0. + */ +#define PSA_PAKE_INPUT_SIZE(alg, primitive, input_step) 0 + /** Output buffer size for psa_pake_output() for any of the supported cipher * suites and PAKE algorithms. * @@ -1163,4 +1182,13 @@ */ #define PSA_PAKE_OUTPUT_MAX_SIZE 0 +/** Input buffer size for psa_pake_input() for any of the supported cipher + * suites and PAKE algorithms. + * + * This macro must expand to a compile-time constant integer. + * + * See also #PSA_PAKE_INPUT_SIZE(\p alg, \p cipher_suite, \p output). + */ +#define PSA_PAKE_INPUT_MAX_SIZE 0 + #endif /* PSA_CRYPTO_SIZES_H */ From 304766e11ef35d17c549b9df9e46617ce12c5291 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 26 May 2021 09:48:08 +0100 Subject: [PATCH 52/69] PSA PAKE: make algorithm macro name consistent The API has PSA_ALG_GCM and not PSA_ALG_AEAD_GCM, PSA_ALG_MD5 and not PSA_ALG_HASH_MD5, etc., so PSA_ALG_PAKE_JPAKE should be PSA_ALG_JPAKE as well. Signed-off-by: Janos Follath --- include/psa/crypto_values.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index ab9bb5b8b..37cd03024 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1977,7 +1977,7 @@ * - A secure cryptographic hash function. * * To select these parameters and set up the cipher suite, call - * psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_PAKE_JPAKE); + * psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_JPAKE); * psa_pake_cs_set_primitive(cipher_suite, * PSA_PAKE_PRIMITIVE(type, family, bits)); * psa_pake_cs_set_hash(cipher_suite, hash); @@ -2067,7 +2067,7 @@ * of RFC 8236 for two examples. * */ -#define PSA_ALG_PAKE_JPAKE ((psa_algorithm_t)0x0a000100) +#define PSA_ALG_JPAKE ((psa_algorithm_t)0x0a000100) /**@}*/ From 702cf09ae9fdb180fc1a4b56206aaf9425d99e39 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 26 May 2021 12:58:23 +0100 Subject: [PATCH 53/69] PSA PAKE: move the API to crypto_extra.h At this point this is a proposed PAKE interface for the PSA Crypto API and not part of the official standard. Place the interface in crypto_extra.h to make this clear. Signed-off-by: Janos Follath --- include/psa/crypto.h | 606 -------------------- include/psa/crypto_extra.h | 1041 +++++++++++++++++++++++++++++++++++ include/psa/crypto_sizes.h | 59 -- include/psa/crypto_struct.h | 75 --- include/psa/crypto_types.h | 42 -- include/psa/crypto_values.h | 261 --------- 6 files changed, 1041 insertions(+), 1043 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index e84c757d1..534902f2d 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -4091,612 +4091,6 @@ psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, /**@}*/ - -/** \defgroup pake Password-authenticated key exchange (PAKE) - * @{ - */ - -/** The type of the data strucure for PAKE cipher suites. - * - * 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_pake_cipher_suite_s psa_pake_cipher_suite_t; - -/** Retrieve the PAKE algorithm from a PAKE cipher suite. - * - * 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] cipher_suite The cipher suite structure to query. - * - * \return The PAKE algorithm stored in the cipher suite structure. - */ -static psa_algorithm_t psa_pake_cs_get_algorithm( - const psa_pake_cipher_suite_t* cipher_suite - ); - -/** Declare the PAKE algorithm for the cipher suite. - * - * This function overwrites any PAKE algorithm - * previously set in \p cipher_suite. - * - * 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] cipher_suite The cipher suite structure to write to. - * \param algorithm The PAKE algorithm to write. - * (`PSA_ALG_XXX` values of type ::psa_algorithm_t - * such that #PSA_ALG_IS_PAKE(\c alg) is true.) - * If this is 0, the PAKE algorithm in - * \p cipher_suite becomes unspecified. - */ -static void psa_pake_cs_set_algorithm( - psa_pake_cipher_suite_t* cipher_suite, - psa_algorithm_t algorithm - ); - -/** Retrieve the primitive from a PAKE cipher suite. - * - * 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] cipher_suite The cipher suite structure to query. - * - * \return The primitive stored in the cipher suite structure. - */ -static psa_pake_primitive_t psa_pake_cs_get_primitive( - const psa_pake_cipher_suite_t* cipher_suite - ); - -/** Declare the primitive for a PAKE cipher suite. - * - * This function overwrites any primitive previously set in \p cipher_suite. - * - * 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] cipher_suite The cipher suite structure to write to. - * \param primitive The primitive to write. If this is 0, the - * primitive type in \p cipher_suite becomes - * unspecified. - */ -static void psa_pake_cs_set_primitive( - psa_pake_cipher_suite_t* cipher_suite, - psa_pake_primitive_t primitive - ); - -/** Retrieve the hash algorithm from a PAKE cipher suite. - * - * 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] cipher_suite The cipher suite structure to query. - * - * \return The hash algorithm stored in the cipher suite structure. The return - * value is 0 if the PAKE is not parametrised by a hash algorithm or if - * the hash algorithm is not set. - */ -static psa_algorithm_t psa_pake_cs_get_hash( - const psa_pake_cipher_suite_t* cipher_suite - ); - -/** Declare the hash algorithm for a PAKE cipher suite. - * - * This function overwrites any hash algorithm - * previously set in \p cipher_suite. - * - * 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. - * - * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` - * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) - * for more information. - * - * \param[out] cipher_suite The cipher suite structure to write to. - * \param hash The hash involved in the cipher suite. - * (`PSA_ALG_XXX` values of type ::psa_algorithm_t - * such that #PSA_ALG_IS_HASH(\c alg) is true.) - * If this is 0, the hash algorithm in - * \p cipher_suite becomes unspecified. - */ -static void psa_pake_cs_set_hash( - psa_pake_cipher_suite_t* cipher_suite, - psa_algorithm_t hash - ); - -/** The type of the state data structure for PAKE operations. - * - * Before calling any function on a PAKE operation object, the application - * must initialize it by any of the following means: - * - Set the structure to all-bits-zero, for example: - * \code - * psa_pake_operation_t operation; - * memset(&operation, 0, sizeof(operation)); - * \endcode - * - Initialize the structure to logical zero values, for example: - * \code - * psa_pake_operation_t operation = {0}; - * \endcode - * - Initialize the structure to the initializer #PSA_PAKE_OPERATION_INIT, - * for example: - * \code - * psa_pake_operation_t operation = PSA_PAKE_OPERATION_INIT; - * \endcode - * - Assign the result of the function psa_pake_operation_init() - * to the structure, for example: - * \code - * psa_pake_operation_t operation; - * operation = psa_pake_operation_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_pake_operation_s psa_pake_operation_t; - -/** Return an initial value for an PAKE operation object. - */ -static psa_pake_operation_t psa_pake_operation_init(void); - -/** Set the session information for a password-authenticated key exchange. - * - * The sequence of operations to set up a password-authenticated key exchange - * 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_pake_operation_t, e.g. - * #PSA_PAKE_OPERATION_INIT. - * -# Call psa_pake_setup() to specify the cipher suite. - * -# Call \c psa_pake_set_xxx() functions on the operation to complete the - * setup. The exact sequence of \c psa_pake_set_xxx() functions that needs - * to be called depends on the algorithm in use. - * - * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` - * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) - * for more information. - * - * A typical sequence of calls to perform a password-authenticated key - * exchange: - * -# Call psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to get the - * key share that needs to be sent to the peer. - * -# Call psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to provide - * the key share that was received from the peer. - * -# Depending on the algorithm additional calls to psa_pake_output() and - * psa_pake_input() might be necessary. - * -# Call psa_pake_get_implicit_key() for accessing the shared secret. - * - * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` - * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) - * for more information. - * - * If an error occurs at any step after a call to psa_pake_setup(), - * the operation will need to be reset by a call to psa_pake_abort(). The - * application may call psa_pake_abort() at any time after the operation - * has been initialized. - * - * After a successful call to psa_pake_setup(), the application must - * eventually terminate the operation. The following events terminate an - * operation: - * - A call to psa_pake_abort(). - * - A successful call to psa_pake_get_implicit_key(). - * - * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_pake_operation_t and not yet in use (no - * other function has been called on it since the - * last initialization). - * \param cipher_suite The cipher suite to use. (A cipher suite fully - * characterizes a PAKE algorithm and determines - * the algorithm as well.) - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid. - * \retval #PSA_ERROR_NOT_SUPPORTED - * The \p cipher_suite is not supported or is not valid. - * \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_pake_setup(psa_pake_operation_t *operation, - psa_pake_cipher_suite_t cipher_suite); - -/** Set the password for a password-authenticated key exchange from key ID. - * - * Call this function when the password, or a value derived from the password, - * is already present in the key store. To calculate the password-derived value - * from a password input, use the key derivation interface and - * psa_pake_set_password_stretch() instead. - * - * \param[in,out] operation The operation object to set the password for. It - * must have been set up by psa_pake_setup() and - * not yet in use (neither psa_pake_output() nor - * psa_pake_input() has been called yet). It must - * be on operation for which the password hasn't - * been set yet (neither - * psa_pake_set_password_stretch() nor - * psa_pake_set_password_key() has been called - * yet). - * \param password Identifier of the key holding the password or a - * value derived from the password (eg. by a - * memory-hard function). It must remain valid - * until the operation terminates. It must be of - * type #PSA_KEY_TYPE_PASSWORD or - * #PSA_KEY_TYPE_PASSWORD_HASH. It has to allow - * the usage #PSA_KEY_USAGE_DERIVE. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must have been set up.) - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p key is not compatible with the algorithm or the cipher suite. - * \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_pake_set_password_key(psa_pake_operation_t *operation, - mbedtls_svc_key_id_t password); - -/** Set the password for a password-authenticated key exchange via a key - * stretching function. - * - * Some protocols use values derived from passwords via key stretching - * functions to mitigate dictionary attacks. Key stretching functions can be - * accessed through the key derivation interface and the result can be supplied - * to the PAKE operation in the form of a key derivation object. - * - * This function draws bytes from a key derivation algorithm and sets those - * bytes as a password for the password-authenticated key exchange. 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 key derivation operation's capacity decreases by the number of bytes read. - * - * If this function returns anything other than #PSA_SUCCESS, both \p operation - * and \p key_derivation operations enter an error state and must be aborted by - * calling psa_pake_abort() and psa_key_derivation_abort() respectively. - * - * \param[in,out] operation The operation object to set the password for. - * It must have been set up by psa_pake_setup() - * and not yet in use (neither psa_pake_output() - * nor psa_pake_input() has been called yet). It - * must be on operation for which the password - * hasn't been set yet (neither - * psa_pake_set_password_stretch() nor - * psa_pake_set_password_key() has been called - * yet). - * \param[in,out] key_derivation An ongoing key derivation operation set up - * from the password and in a state suitable for - * calling psa_key_derivation_output_bytes(). - * \param input_length Number of bytes to input from the - * \p key_derivation operation. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The state of \p operation or \p key_derivation is not valid. - * \retval #PSA_ERROR_INSUFFICIENT_DATA - * The \p key_derivation operation's capacity was less than - * \p input_length bytes. - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_NOT_PERMITTED - * One of the inputs to \p key_derivation was a key whose policy didn't - * allow #PSA_KEY_USAGE_DERIVE. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p key is not compatible with the algorithm or the cipher suite. - * \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_pake_set_password_stretch( - psa_pake_operation_t *operation, - psa_key_derivation_operation_t *key_derivation, - size_t input_length - ); - -/** Set the user ID for a password-authenticated key exchange. - * - * Call this function to set the user ID. For PAKE algorithms that associate a - * user identifier with each side of the session you need to call - * psa_pake_set_peer() as well. For PAKE algorithms that associate a single - * user identifier with the session, call psa_pake_set_user() only. - * - * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` - * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) - * for more information. - * - * \param[in,out] operation The operation object to set the user ID for. It - * must have been set up by psa_pake_setup() and - * not yet in use (neither psa_pake_output() nor - * psa_pake_input() has been called yet). It must - * be on operation for which the user ID hasn't - * been set (psa_pake_set_user() hasn't been - * called yet). - * \param[in] user_id The user ID to authenticate with. - * \param user_id_len Size of the \p user_id buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p user_id is NULL. - * \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_pake_set_user(psa_pake_operation_t *operation, - const uint8_t *user_id, - size_t user_id_len); - -/** Set the peer ID for a password-authenticated key exchange. - * - * Call this function in addition to psa_pake_set_user() for PAKE algorithms - * that associate a user identifier with each side of the session. For PAKE - * algorithms that associate a single user identifier with the session, call - * psa_pake_set_user() only. - * - * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` - * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) - * for more information. - * - * \param[in,out] operation The operation object to set the peer ID for. It - * must have been set up by psa_pake_setup() and - * not yet in use (neither psa_pake_output() nor - * psa_pake_input() has been called yet). It must - * be on operation for which the peer ID hasn't - * been set (psa_pake_set_peer() hasn't been - * called yet). - * \param[in] peer_id The peer's ID to authenticate. - * \param peer_id_len Size of the \p peer_id buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid. - * \retval #PSA_ERROR_NOT_SUPPORTED - * The algorithm doesn't associate a second identity with the session. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p user_id is NULL. - * \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_pake_set_peer(psa_pake_operation_t *operation, - const uint8_t *peer_id, - size_t peer_id_len); - -/** Set the side for a password-authenticated key exchange. - * - * Not all PAKE algorithms need to differentiate the communicating entities. - * It is optional to call this function for PAKEs that don't require a side - * parameter. For such PAKEs the side parameter is ignored. - * - * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` - * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) - * for more information. - * - * \param[in,out] operation The operation object to set the side for. It - * must have been set up by psa_pake_setup() and - * not yet in use (neither psa_pake_output() nor - * psa_pake_input() has been called yet). It must - * be on operation for which the side hasn't been - * set (psa_pake_set_side() hasn't been called - * yet). - * \param side A value of type ::psa_pake_side_t signaling the - * side of the algorithm that is being set up. For - * more information see the documentation of \c - * PSA_PAKE_SIDE_XXX constants. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid. - * \retval #PSA_ERROR_NOT_SUPPORTED - * The \p side for this algorithm is not supported or is not valid. - * \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_pake_set_side(psa_pake_operation_t *operation, - psa_pake_side_t side); - -/** Get output for a step of a password-authenticated key exchange. - * - * Depending on the algorithm being executed, you might need to call this - * function several times or you might not need to call this at all. - * - * The exact sequence of calls to perform a password-authenticated key - * exchange depends on the algorithm in use. Refer to the documentation of - * individual PAKE algorithm types (`PSA_ALG_XXX` values of type - * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more - * information. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_pake_abort(). - * - * \param[in,out] operation Active PAKE operation. - * \param step The step of the algorithm for which the output is - * requested. - * \param[out] output Buffer where the output is to be written in the - * format appropriate for this \p step. Refer to - * the documentation of the individual - * \c PSA_PAKE_STEP_XXX constants for more - * information. - * \param output_size Size of the \p output buffer in bytes. This must - * be at least #PSA_PAKE_OUTPUT_SIZE(\p alg, \c - * cipher_suite, \p type). - * - * \param[out] output_length On success, the number of bytes of the returned - * output. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, but beyond that - * validity is specific to 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_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_pake_output(psa_pake_operation_t *operation, - psa_pake_step_t step, - uint8_t *output, - size_t output_size, - size_t *output_length); - -/** Provide input for a step of a password-authenticated key exchange. - * - * Depending on the algorithm being executed, you might need to call this - * function several times or you might not need to call this at all. - * - * The exact sequence of calls to perform a password-authenticated key - * exchange depends on the algorithm in use. Refer to the documentation of - * individual PAKE algorithm types (`PSA_ALG_XXX` values of type - * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more - * information. - * - * If this function returns an error status, the operation enters an error - * state and must be aborted by calling psa_pake_abort(). - * - * \param[in,out] operation Active PAKE operation. - * \param step The step for which the input is provided. - * \param[out] input Buffer containing the input in the format - * appropriate for this \p step. Refer to the - * documentation of the individual - * \c PSA_PAKE_STEP_XXX constants for more - * information. - * \param[out] 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, but beyond that - * validity is specific to the 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_INVALID_ARGUMENT - * The input is not valid for the algorithm, ciphersuite or \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_pake_input(psa_pake_operation_t *operation, - psa_pake_step_t step, - uint8_t *input, - size_t input_length); - -/** Get implicitly confirmed shared secret from a PAKE. - * - * At this point there is a cryptographic guarantee that only the authenticated - * party who used the same password is able to compute the key. But there is no - * guarantee that the peer is the party he claims to be and was able to do so. - * - * That is, the authentication is only implicit (the peer is not authenticated - * at this point, and no action should be taken that assume that they are - like - * for example accessing restricted files). - * - * This function can be called after the key exchange phase of the operation - * has completed. It imports the shared secret output of the PAKE into the - * provided derivation operation. The input step - * #PSA_KEY_DERIVATION_INPUT_SECRET is used when placing the shared key - * material in the key derivation operation. - * - * The exact sequence of calls to perform a password-authenticated key - * exchange depends on the algorithm in use. Refer to the documentation of - * individual PAKE algorithm types (`PSA_ALG_XXX` values of type - * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more - * information. - * - * When this function returns successfully, \p operation becomes inactive. - * If this function returns an error status, both \p operation - * and \p key_derivation operations enter an error state and must be aborted by - * calling psa_pake_abort() and psa_key_derivation_abort() respectively. - * - * \param[in,out] operation Active PAKE operation. - * \param[out] output A key derivation operation that is ready - * for an input step of type - * #PSA_KEY_DERIVATION_INPUT_SECRET. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, but beyond that - * validity is specific to the algorithm). - * \retval #PSA_ERROR_BAD_STATE - * The state of \p output is not valid for - * the #PSA_KEY_DERIVATION_INPUT_SECRET step. This can happen if the - * step is out of order or the application has done this step already - * and it may not be repeated. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * #PSA_KEY_DERIVATION_INPUT_SECRET is not compatible with the output’s - * 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_pake_get_implicit_key(psa_pake_operation_t *operation, - psa_key_derivation_operation_t *output); -/**@}*/ - #ifdef __cplusplus } #endif diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index a7b4ab599..615b6511c 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -813,6 +813,1047 @@ psa_status_t mbedtls_psa_platform_get_builtin_key( /** @} */ +/** \addtogroup crypto_types + * @{ + */ + +#define PSA_ALG_CATEGORY_PAKE ((psa_algorithm_t)0x0a000000) + +/** Whether the specified algorithm is a password-authenticated key exchange. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a password-authenticated key exchange (PAKE) + * algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_PAKE(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_PAKE) + +/** The Password-authenticated key exchange by juggling (J-PAKE) algorithm. + * + * This is J-PAKE as defined by RFC 8236, instantiated with the following + * parameters: + * + * - The group can be either an elliptic curve or defined over a finite field. + * - Schnorr NIZK proof as defined by RFC 8235 and using the same group as the + * J-PAKE algorithm. + * - A secure cryptographic hash function. + * + * To select these parameters and set up the cipher suite, call + * psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_JPAKE); + * psa_pake_cs_set_primitive(cipher_suite, + * PSA_PAKE_PRIMITIVE(type, family, bits)); + * psa_pake_cs_set_hash(cipher_suite, hash); + * + * For more information on how to set a specific curve or field, refer to the + * documentation of the individual \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. + * + * After initializing a J-PAKE operation, call + * psa_pake_setup(operation, cipher_suite); + * psa_pake_set_user(operation, ...); + * psa_pake_set_peer(operation, ...); + * and either + * psa_pake_set_password_stretch(operation, ...); + * or + * psa_pake_set_password_key(operation, ...); + * + * Either way the password is read as a byte array and must be non-empty. This + * can be the password itself (in some pre-defined character encoding) or some + * value derived from the password as mandated by some higher level protocol. + * + * (The implementation converts this byte array to a number as described in + * Section 2.3.8 of _SEC 1: Elliptic Curve Cryptography_ + * (https://www.secg.org/sec1-v2.pdf), before reducing it modulo \c q. Here + * \c q is order of the group defined by the primitive set in the cipher suite. + * The \c psa_pake_set_password_xxx() functions return an error if the result + * of the reduction is 0.) + * + * The key exchange flow for J-PAKE is as follows: + * -# To get the first round data that needs to be sent to the peer, call + * // Get g1 + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Get the ZKP public key for x1 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Get the ZKP proof for x1 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * // Get g2 + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Get the ZKP public key for x2 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Get the ZKP proof for x2 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * -# To provide the first round data received from the peer to the operation, + * call + * // Set g3 + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Set the ZKP public key for x3 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Set the ZKP proof for x3 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * // Set g4 + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Set the ZKP public key for x4 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Set the ZKP proof for x4 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * -# To get the second round data that needs to be sent to the peer, call + * // Get A + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Get ZKP public key for x2*s + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Get ZKP proof for x2*s + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * -# To provide the second round data received from the peer to the operation, + * call + * // Set B + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Set ZKP public key for x4*s + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Set ZKP proof for x4*s + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * -# To access the shared secret call + * // Get Ka=Kb=K + * psa_pake_get_implicit_key() + * + * For more information consult the documentation of the individual + * \c PSA_PAKE_STEP_XXX constants. + * + * At this point there is a cryptographic guarantee that only the authenticated + * party who used the same password is able to compute the key. But there is no + * guarantee that the peer is the party he claims to be and was able to do so. + * + * That is, the authentication is only implicit (the peer is not authenticated + * at this point, and no action should be taken that assume that they are - like + * for example accessing restricted files). + * + * To make the authentication explicit there are various methods, see Section 5 + * of RFC 8236 for two examples. + * + */ +#define PSA_ALG_JPAKE ((psa_algorithm_t)0x0a000100) + +/** @} */ + +/** \defgroup pake Password-authenticated key exchange (PAKE) + * @{ + */ + +/** \brief Encoding of the side of PAKE + * + * Encodes which side of the algorithm is being executed. For more information + * see the documentation of individual \c PSA_PAKE_SIDE_XXX constants. + */ +typedef uint8_t psa_pake_side_t; + +/** Encoding of input and output indicators for PAKE. + * + * Some PAKE algorithms need to exchange more data than just a single key share. + * This type is for encoding additional input and output data for such + * algorithms. + */ +typedef uint8_t psa_pake_step_t; + +/** Encoding of the type of the PAKE's primitive. + * + * Values defined by this standard will never be in the range 0x80-0xff. + * Vendors who define additional types must use an encoding in this range. + * + * For more information see the documentation of individual + * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. + */ +typedef uint8_t psa_pake_primitive_type_t; + +/** \brief Encoding of the family of the primitive associated with the PAKE. + * + * For more information see the documentation of individual + * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. + */ +typedef uint8_t psa_pake_family_t; + +/** \brief Encoding of the primitive associated with the PAKE. + * + * For more information see the documentation of the #PSA_PAKE_PRIMITIVE macro. + */ +typedef uint32_t psa_pake_primitive_t; + +/** The first peer in a balanced PAKE. + * + * Although balanced PAKE algorithms are symmetric, some of them needs an + * ordering of peers for the transcript calculations. If the algorithm does not + * need this, both #PSA_PAKE_SIDE_FIRST and #PSA_PAKE_SIDE_SECOND are + * accepted. + */ +#define PSA_PAKE_SIDE_FIRST ((psa_pake_side_t)0x01) + +/** The second peer in a balanced PAKE. + * + * Although balanced PAKE algorithms are symmetric, some of them needs an + * ordering of peers for the transcript calculations. If the algorithm does not + * need this, either #PSA_PAKE_SIDE_FIRST or #PSA_PAKE_SIDE_SECOND are + * accepted. + */ +#define PSA_PAKE_SIDE_SECOND ((psa_pake_side_t)0x02) + +/** The client in an augmented PAKE. + * + * Augmented PAKE algorithms need to differentiate between client and server. + */ +#define PSA_PAKE_SIDE_CLIENT ((psa_pake_side_t)0x11) + +/** The server in an augmented PAKE. + * + * Augmented PAKE algorithms need to differentiate between client and server. + */ +#define PSA_PAKE_SIDE_SERVER ((psa_pake_side_t)0x12) + +/** The PAKE primitive type indicating the use of elliptic curves. + * + * The values of the \c family and \c bits fields of the cipher suite identify a + * specific elliptic curve, using the same mapping that is used for ECC + * (::psa_ecc_family_t) keys. + * + * (Here \c family means the value returned by psa_pake_cs_get_family() and + * \c bits means the value returned by psa_pake_cs_get_bits().) + * + * Input and output during the operation can involve group elements and scalar + * values: + * -# The format for group elements is the same as for public keys on the + * specific curve would be. For more information, consult the documentation of + * psa_export_public_key(). + * -# The format for scalars is the same as for private keys on the specific + * curve would be. For more information, consult the documentation of + * psa_export_key(). + */ +#define PSA_PAKE_PRIMITIVE_TYPE_ECC ((psa_pake_primitive_type_t)0x01) + +/** The PAKE primitive type indicating the use of Diffie-Hellman groups. + * + * The values of the \c family and \c bits fields of the cipher suite identify + * a specific Diffie-Hellman group, using the same mapping that is used for + * Diffie-Hellman (::psa_dh_family_t) keys. + * + * (Here \c family means the value returned by psa_pake_cs_get_family() and + * \c bits means the value returned by psa_pake_cs_get_bits().) + * + * Input and output during the operation can involve group elements and scalar + * values: + * -# The format for group elements is the same as for public keys on the + * specific group would be. For more information, consult the documentation of + * psa_export_public_key(). + * -# The format for scalars is the same as for private keys on the specific + * group would be. For more information, consult the documentation of + * psa_export_key(). + */ +#define PSA_PAKE_PRIMITIVE_TYPE_DH ((psa_pake_primitive_type_t)0x02) + +/** Construct a PAKE primitive from type, family and bit-size. + * + * \param pake_type The type of the primitive + * (value of type ::psa_pake_primitive_type_t). + * \param pake_family The family of the primitive + * (the type and interpretation of this parameter depends + * on \p type, for more information consult the + * documentation of individual ::psa_pake_primitive_type_t + * constants). + * \param pake_bits The bit-size of the primitive + * (Value of type \c size_t. The interpretation + * of this parameter depends on \p family, for more + * information consult the documentation of individual + * ::psa_pake_primitive_type_t constants). + * + * \return The constructed primitive value of type ::psa_pake_primitive_t. + * Return 0 if the requested primitive can't be encoded as + * ::psa_pake_primitive_t. + */ +#define PSA_PAKE_PRIMITIVE(pake_type, pake_family, pake_bits) \ + ((pake_bits & 0xFFFF) != pake_bits) ? 0 : \ + ((psa_pake_primitive_t) (((pake_type) << 24 | \ + (pake_family) << 16) | (pake_bits))) + +/** The key share being sent to or received from the peer. + * + * The format for both input and output at this step is the same as for public + * keys on the group determined by the primitive (::psa_pake_primitive_t) would + * be. + * + * For more information on the format, consult the documentation of + * psa_export_public_key(). + * + * For information regarding how the group is determined, consult the + * documentation #PSA_PAKE_PRIMITIVE. + */ +#define PSA_PAKE_STEP_KEY_SHARE ((psa_pake_step_t)0x01) + +/** A Schnorr NIZKP public key. + * + * The format for both input and output at this step is the same as for public + * keys on the group determined by the primitive (::psa_pake_primitive_t) would + * be. + * + * For more information on the format, consult the documentation of + * psa_export_public_key(). + * + * For information regarding how the group is determined, consult the + * documentation #PSA_PAKE_PRIMITIVE. + */ +#define PSA_PAKE_STEP_ZK_PUBLIC ((psa_pake_step_t)0x02) + +/** A Schnorr NIZKP proof. + * + * The format for both input and output at this step is the same as for private + * keys on the group determined by the primitive (::psa_pake_primitive_t) would + * be. + * + * Some public key algorithms mask the private keys and this might be reflected + * in the export format. Even if this is the case the masking is omitted at + * this step. + * + * For more information on the format, consult the documentation of + * psa_export_key(). + * + * For information regarding how the group is determined, consult the + * documentation #PSA_PAKE_PRIMITIVE. + */ +#define PSA_PAKE_STEP_ZK_PROOF ((psa_pake_step_t)0x03) + +/** The type of the data strucure for PAKE cipher suites. + * + * 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_pake_cipher_suite_s psa_pake_cipher_suite_t; + +/** Retrieve the PAKE algorithm from a PAKE cipher suite. + * + * 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] cipher_suite The cipher suite structure to query. + * + * \return The PAKE algorithm stored in the cipher suite structure. + */ +static psa_algorithm_t psa_pake_cs_get_algorithm( + const psa_pake_cipher_suite_t* cipher_suite + ); + +/** Declare the PAKE algorithm for the cipher suite. + * + * This function overwrites any PAKE algorithm + * previously set in \p cipher_suite. + * + * 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] cipher_suite The cipher suite structure to write to. + * \param algorithm The PAKE algorithm to write. + * (`PSA_ALG_XXX` values of type ::psa_algorithm_t + * such that #PSA_ALG_IS_PAKE(\c alg) is true.) + * If this is 0, the PAKE algorithm in + * \p cipher_suite becomes unspecified. + */ +static void psa_pake_cs_set_algorithm( + psa_pake_cipher_suite_t* cipher_suite, + psa_algorithm_t algorithm + ); + +/** Retrieve the primitive from a PAKE cipher suite. + * + * 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] cipher_suite The cipher suite structure to query. + * + * \return The primitive stored in the cipher suite structure. + */ +static psa_pake_primitive_t psa_pake_cs_get_primitive( + const psa_pake_cipher_suite_t* cipher_suite + ); + +/** Declare the primitive for a PAKE cipher suite. + * + * This function overwrites any primitive previously set in \p cipher_suite. + * + * 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] cipher_suite The cipher suite structure to write to. + * \param primitive The primitive to write. If this is 0, the + * primitive type in \p cipher_suite becomes + * unspecified. + */ +static void psa_pake_cs_set_primitive( + psa_pake_cipher_suite_t* cipher_suite, + psa_pake_primitive_t primitive + ); + +/** Retrieve the hash algorithm from a PAKE cipher suite. + * + * 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] cipher_suite The cipher suite structure to query. + * + * \return The hash algorithm stored in the cipher suite structure. The return + * value is 0 if the PAKE is not parametrised by a hash algorithm or if + * the hash algorithm is not set. + */ +static psa_algorithm_t psa_pake_cs_get_hash( + const psa_pake_cipher_suite_t* cipher_suite + ); + +/** Declare the hash algorithm for a PAKE cipher suite. + * + * This function overwrites any hash algorithm + * previously set in \p cipher_suite. + * + * 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. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[out] cipher_suite The cipher suite structure to write to. + * \param hash The hash involved in the cipher suite. + * (`PSA_ALG_XXX` values of type ::psa_algorithm_t + * such that #PSA_ALG_IS_HASH(\c alg) is true.) + * If this is 0, the hash algorithm in + * \p cipher_suite becomes unspecified. + */ +static void psa_pake_cs_set_hash( + psa_pake_cipher_suite_t* cipher_suite, + psa_algorithm_t hash + ); + +/** The type of the state data structure for PAKE operations. + * + * Before calling any function on a PAKE operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_pake_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_pake_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_PAKE_OPERATION_INIT, + * for example: + * \code + * psa_pake_operation_t operation = PSA_PAKE_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_pake_operation_init() + * to the structure, for example: + * \code + * psa_pake_operation_t operation; + * operation = psa_pake_operation_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_pake_operation_s psa_pake_operation_t; + +/** Return an initial value for an PAKE operation object. + */ +static psa_pake_operation_t psa_pake_operation_init(void); + +/** Set the session information for a password-authenticated key exchange. + * + * The sequence of operations to set up a password-authenticated key exchange + * 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_pake_operation_t, e.g. + * #PSA_PAKE_OPERATION_INIT. + * -# Call psa_pake_setup() to specify the cipher suite. + * -# Call \c psa_pake_set_xxx() functions on the operation to complete the + * setup. The exact sequence of \c psa_pake_set_xxx() functions that needs + * to be called depends on the algorithm in use. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * A typical sequence of calls to perform a password-authenticated key + * exchange: + * -# Call psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to get the + * key share that needs to be sent to the peer. + * -# Call psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to provide + * the key share that was received from the peer. + * -# Depending on the algorithm additional calls to psa_pake_output() and + * psa_pake_input() might be necessary. + * -# Call psa_pake_get_implicit_key() for accessing the shared secret. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * If an error occurs at any step after a call to psa_pake_setup(), + * the operation will need to be reset by a call to psa_pake_abort(). The + * application may call psa_pake_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_pake_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A call to psa_pake_abort(). + * - A successful call to psa_pake_get_implicit_key(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_pake_operation_t and not yet in use (no + * other function has been called on it since the + * last initialization). + * \param cipher_suite The cipher suite to use. (A cipher suite fully + * characterizes a PAKE algorithm and determines + * the algorithm as well.) + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The \p cipher_suite is not supported or is not valid. + * \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_pake_setup(psa_pake_operation_t *operation, + psa_pake_cipher_suite_t cipher_suite); + +/** Set the password for a password-authenticated key exchange from key ID. + * + * Call this function when the password, or a value derived from the password, + * is already present in the key store. To calculate the password-derived value + * from a password input, use the key derivation interface and + * psa_pake_set_password_stretch() instead. + * + * \param[in,out] operation The operation object to set the password for. It + * must have been set up by psa_pake_setup() and + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the password hasn't + * been set yet (neither + * psa_pake_set_password_stretch() nor + * psa_pake_set_password_key() has been called + * yet). + * \param password Identifier of the key holding the password or a + * value derived from the password (eg. by a + * memory-hard function). It must remain valid + * until the operation terminates. It must be of + * type #PSA_KEY_TYPE_PASSWORD or + * #PSA_KEY_TYPE_PASSWORD_HASH. It has to allow + * the usage #PSA_KEY_USAGE_DERIVE. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must have been set up.) + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with the algorithm or the cipher suite. + * \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_pake_set_password_key(psa_pake_operation_t *operation, + mbedtls_svc_key_id_t password); + +/** Set the password for a password-authenticated key exchange via a key + * stretching function. + * + * Some protocols use values derived from passwords via key stretching + * functions to mitigate dictionary attacks. Key stretching functions can be + * accessed through the key derivation interface and the result can be supplied + * to the PAKE operation in the form of a key derivation object. + * + * This function draws bytes from a key derivation algorithm and sets those + * bytes as a password for the password-authenticated key exchange. 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 key derivation operation's capacity decreases by the number of bytes read. + * + * If this function returns anything other than #PSA_SUCCESS, both \p operation + * and \p key_derivation operations enter an error state and must be aborted by + * calling psa_pake_abort() and psa_key_derivation_abort() respectively. + * + * \param[in,out] operation The operation object to set the password for. + * It must have been set up by psa_pake_setup() + * and not yet in use (neither psa_pake_output() + * nor psa_pake_input() has been called yet). It + * must be on operation for which the password + * hasn't been set yet (neither + * psa_pake_set_password_stretch() nor + * psa_pake_set_password_key() has been called + * yet). + * \param[in,out] key_derivation An ongoing key derivation operation set up + * from the password and in a state suitable for + * calling psa_key_derivation_output_bytes(). + * \param input_length Number of bytes to input from the + * \p key_derivation operation. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The state of \p operation or \p key_derivation is not valid. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The \p key_derivation operation's capacity was less than + * \p input_length bytes. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_NOT_PERMITTED + * One of the inputs to \p key_derivation was a key whose policy didn't + * allow #PSA_KEY_USAGE_DERIVE. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with the algorithm or the cipher suite. + * \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_pake_set_password_stretch( + psa_pake_operation_t *operation, + psa_key_derivation_operation_t *key_derivation, + size_t input_length + ); + +/** Set the user ID for a password-authenticated key exchange. + * + * Call this function to set the user ID. For PAKE algorithms that associate a + * user identifier with each side of the session you need to call + * psa_pake_set_peer() as well. For PAKE algorithms that associate a single + * user identifier with the session, call psa_pake_set_user() only. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[in,out] operation The operation object to set the user ID for. It + * must have been set up by psa_pake_setup() and + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the user ID hasn't + * been set (psa_pake_set_user() hasn't been + * called yet). + * \param[in] user_id The user ID to authenticate with. + * \param user_id_len Size of the \p user_id buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p user_id is NULL. + * \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_pake_set_user(psa_pake_operation_t *operation, + const uint8_t *user_id, + size_t user_id_len); + +/** Set the peer ID for a password-authenticated key exchange. + * + * Call this function in addition to psa_pake_set_user() for PAKE algorithms + * that associate a user identifier with each side of the session. For PAKE + * algorithms that associate a single user identifier with the session, call + * psa_pake_set_user() only. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[in,out] operation The operation object to set the peer ID for. It + * must have been set up by psa_pake_setup() and + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the peer ID hasn't + * been set (psa_pake_set_peer() hasn't been + * called yet). + * \param[in] peer_id The peer's ID to authenticate. + * \param peer_id_len Size of the \p peer_id buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The algorithm doesn't associate a second identity with the session. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p user_id is NULL. + * \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_pake_set_peer(psa_pake_operation_t *operation, + const uint8_t *peer_id, + size_t peer_id_len); + +/** Set the side for a password-authenticated key exchange. + * + * Not all PAKE algorithms need to differentiate the communicating entities. + * It is optional to call this function for PAKEs that don't require a side + * parameter. For such PAKEs the side parameter is ignored. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[in,out] operation The operation object to set the side for. It + * must have been set up by psa_pake_setup() and + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the side hasn't been + * set (psa_pake_set_side() hasn't been called + * yet). + * \param side A value of type ::psa_pake_side_t signaling the + * side of the algorithm that is being set up. For + * more information see the documentation of \c + * PSA_PAKE_SIDE_XXX constants. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The \p side for this algorithm is not supported or is not valid. + * \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_pake_set_side(psa_pake_operation_t *operation, + psa_pake_side_t side); + +/** Get output for a step of a password-authenticated key exchange. + * + * Depending on the algorithm being executed, you might need to call this + * function several times or you might not need to call this at all. + * + * The exact sequence of calls to perform a password-authenticated key + * exchange depends on the algorithm in use. Refer to the documentation of + * individual PAKE algorithm types (`PSA_ALG_XXX` values of type + * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more + * information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_pake_abort(). + * + * \param[in,out] operation Active PAKE operation. + * \param step The step of the algorithm for which the output is + * requested. + * \param[out] output Buffer where the output is to be written in the + * format appropriate for this \p step. Refer to + * the documentation of the individual + * \c PSA_PAKE_STEP_XXX constants for more + * information. + * \param output_size Size of the \p output buffer in bytes. This must + * be at least #PSA_PAKE_OUTPUT_SIZE(\p alg, \c + * cipher_suite, \p type). + * + * \param[out] output_length On success, the number of bytes of the returned + * output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, but beyond that + * validity is specific to 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_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_pake_output(psa_pake_operation_t *operation, + psa_pake_step_t step, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Provide input for a step of a password-authenticated key exchange. + * + * Depending on the algorithm being executed, you might need to call this + * function several times or you might not need to call this at all. + * + * The exact sequence of calls to perform a password-authenticated key + * exchange depends on the algorithm in use. Refer to the documentation of + * individual PAKE algorithm types (`PSA_ALG_XXX` values of type + * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more + * information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_pake_abort(). + * + * \param[in,out] operation Active PAKE operation. + * \param step The step for which the input is provided. + * \param[out] input Buffer containing the input in the format + * appropriate for this \p step. Refer to the + * documentation of the individual + * \c PSA_PAKE_STEP_XXX constants for more + * information. + * \param[out] 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, but beyond that + * validity is specific to the 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_INVALID_ARGUMENT + * The input is not valid for the algorithm, ciphersuite or \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_pake_input(psa_pake_operation_t *operation, + psa_pake_step_t step, + uint8_t *input, + size_t input_length); + +/** Get implicitly confirmed shared secret from a PAKE. + * + * At this point there is a cryptographic guarantee that only the authenticated + * party who used the same password is able to compute the key. But there is no + * guarantee that the peer is the party he claims to be and was able to do so. + * + * That is, the authentication is only implicit (the peer is not authenticated + * at this point, and no action should be taken that assume that they are - like + * for example accessing restricted files). + * + * This function can be called after the key exchange phase of the operation + * has completed. It imports the shared secret output of the PAKE into the + * provided derivation operation. The input step + * #PSA_KEY_DERIVATION_INPUT_SECRET is used when placing the shared key + * material in the key derivation operation. + * + * The exact sequence of calls to perform a password-authenticated key + * exchange depends on the algorithm in use. Refer to the documentation of + * individual PAKE algorithm types (`PSA_ALG_XXX` values of type + * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more + * information. + * + * When this function returns successfully, \p operation becomes inactive. + * If this function returns an error status, both \p operation + * and \p key_derivation operations enter an error state and must be aborted by + * calling psa_pake_abort() and psa_key_derivation_abort() respectively. + * + * \param[in,out] operation Active PAKE operation. + * \param[out] output A key derivation operation that is ready + * for an input step of type + * #PSA_KEY_DERIVATION_INPUT_SECRET. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, but beyond that + * validity is specific to the algorithm). + * \retval #PSA_ERROR_BAD_STATE + * The state of \p output is not valid for + * the #PSA_KEY_DERIVATION_INPUT_SECRET step. This can happen if the + * step is out of order or the application has done this step already + * and it may not be repeated. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * #PSA_KEY_DERIVATION_INPUT_SECRET is not compatible with the output’s + * 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_pake_get_implicit_key(psa_pake_operation_t *operation, + psa_key_derivation_operation_t *output); + +/**@}*/ + +/** A sufficient output buffer size for psa_pake_output(). + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_pake_output() will not fail due to an insufficient output buffer + * size. The actual size of the output might be smaller in any given call. + * + * See also #PSA_PAKE_OUTPUT_MAX_SIZE + * + * \param alg A PAKE algorithm (PSA_ALG_XXX value such that + * #PSA_ALG_IS_PAKE(\p alg) is true). + * \param primitive A primitive of type ::psa_pake_primitive_t that is + * compatible with algorithm \p alg. + * \param output_step A value of type ::psa_pake_step_t that is valid for the + * algorithm \p alg. + * \return A sufficient output buffer size for the specified + * output, cipher suite and algorithm. If the cipher suite, + * the output type or PAKE algorithm is not recognized, or + * the parameters are incompatible, return 0. + */ +#define PSA_PAKE_OUTPUT_SIZE(alg, primitive, output_step) 0 + +/** A sufficient input buffer size for psa_pake_input(). + * + * If the size of the input is larger than this, it is guaranteed + * that psa_pake_input() will fail with #PSA_ERROR_INVALID_ARGUMENT. + * + * See also #PSA_PAKE_INPUT_MAX_SIZE + * + * \param alg A PAKE algorithm (PSA_ALG_XXX value such that + * #PSA_ALG_IS_PAKE(\p alg) is true). + * \param primitive A primitive of type ::psa_pake_primitive_t that is + * compatible with algorithm \p alg. + * \param output_step A value of type ::psa_pake_step_t that is valid for the + * algorithm \p alg. + * \return A sufficient output buffer size for the specified + * output, cipher suite and algorithm. If the cipher suite, + * the output type or PAKE algorithm is not recognized, or + * the parameters are incompatible, return 0. + */ +#define PSA_PAKE_INPUT_SIZE(alg, primitive, input_step) 0 + +/** Output buffer size for psa_pake_output() for any of the supported cipher + * suites and PAKE algorithms. + * + * This macro must expand to a compile-time constant integer. + * + * See also #PSA_PAKE_OUTPUT_SIZE(\p alg, \p cipher_suite, \p output). + */ +#define PSA_PAKE_OUTPUT_MAX_SIZE 0 + +/** Input buffer size for psa_pake_input() for any of the supported cipher + * suites and PAKE algorithms. + * + * This macro must expand to a compile-time constant integer. + * + * See also #PSA_PAKE_INPUT_SIZE(\p alg, \p cipher_suite, \p output). + */ +#define PSA_PAKE_INPUT_MAX_SIZE 0 + +struct psa_pake_cipher_suite_s +{ + psa_algorithm_t algorithm; + psa_pake_primitive_type_t type; + psa_pake_family_t family; + uint16_t bits; + psa_algorithm_t hash; +}; + +static inline psa_algorithm_t psa_pake_cs_get_algorithm( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return(cipher_suite->algorithm); +} + +static inline void psa_pake_cs_set_algorithm( + psa_pake_cipher_suite_t *cipher_suite, + psa_algorithm_t algorithm) +{ + if(!PSA_ALG_IS_PAKE(algorithm)) + cipher_suite->algorithm = 0; + else + cipher_suite->algorithm = algorithm; +} + +static inline psa_pake_primitive_t psa_pake_cs_get_primitive( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return(PSA_PAKE_PRIMITIVE(cipher_suite->type, cipher_suite->family, + cipher_suite->bits)); +} + +static inline void psa_pake_cs_set_primitive( + psa_pake_cipher_suite_t *cipher_suite, + psa_pake_primitive_t primitive) +{ + cipher_suite->type = (psa_pake_primitive_type_t) (primitive >> 24); + cipher_suite->family = (psa_pake_family_t) (0xFF & (primitive >> 16)); + cipher_suite->bits = (uint16_t) (0xFFFF & primitive); +} + +static inline psa_algorithm_t psa_pake_cs_get_hash( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return(cipher_suite->hash); +} + +static inline void psa_pake_cs_set_hash( + psa_pake_cipher_suite_t *cipher_suite, + psa_algorithm_t hash) +{ + if(!PSA_ALG_IS_HASH(hash)) + cipher_suite->hash = 0; + else + cipher_suite->hash = hash; +} + +struct psa_pake_operation_s +{ + psa_algorithm_t alg; + union + { + /* Make the union non-empty even with no supported algorithms. */ + uint8_t dummy; + } ctx; +}; + +/* This only zeroes out the first byte in the union, the rest is unspecified. */ +#define PSA_PAKE_OPERATION_INIT {0, {0}} +static inline struct psa_pake_operation_s psa_pake_operation_init(void) +{ + const struct psa_pake_operation_s v = PSA_PAKE_OPERATION_INIT; + return(v); +} + #ifdef __cplusplus } #endif diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index 62254fab5..79f96739b 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -1132,63 +1132,4 @@ #define PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE \ (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE) -/** A sufficient output buffer size for psa_pake_output(). - * - * If the size of the output buffer is at least this large, it is guaranteed - * that psa_pake_output() will not fail due to an insufficient output buffer - * size. The actual size of the output might be smaller in any given call. - * - * See also #PSA_PAKE_OUTPUT_MAX_SIZE - * - * \param alg A PAKE algorithm (PSA_ALG_XXX value such that - * #PSA_ALG_IS_PAKE(\p alg) is true). - * \param primitive A primitive of type ::psa_pake_primitive_t that is - * compatible with algorithm \p alg. - * \param output_step A value of type ::psa_pake_step_t that is valid for the - * algorithm \p alg. - * \return A sufficient output buffer size for the specified - * output, cipher suite and algorithm. If the cipher suite, - * the output type or PAKE algorithm is not recognized, or - * the parameters are incompatible, return 0. - */ -#define PSA_PAKE_OUTPUT_SIZE(alg, primitive, output_step) 0 - -/** A sufficient input buffer size for psa_pake_input(). - * - * If the size of the input is larger than this, it is guaranteed - * that psa_pake_input() will fail with #PSA_ERROR_INVALID_ARGUMENT. - * - * See also #PSA_PAKE_INPUT_MAX_SIZE - * - * \param alg A PAKE algorithm (PSA_ALG_XXX value such that - * #PSA_ALG_IS_PAKE(\p alg) is true). - * \param primitive A primitive of type ::psa_pake_primitive_t that is - * compatible with algorithm \p alg. - * \param output_step A value of type ::psa_pake_step_t that is valid for the - * algorithm \p alg. - * \return A sufficient output buffer size for the specified - * output, cipher suite and algorithm. If the cipher suite, - * the output type or PAKE algorithm is not recognized, or - * the parameters are incompatible, return 0. - */ -#define PSA_PAKE_INPUT_SIZE(alg, primitive, input_step) 0 - -/** Output buffer size for psa_pake_output() for any of the supported cipher - * suites and PAKE algorithms. - * - * This macro must expand to a compile-time constant integer. - * - * See also #PSA_PAKE_OUTPUT_SIZE(\p alg, \p cipher_suite, \p output). - */ -#define PSA_PAKE_OUTPUT_MAX_SIZE 0 - -/** Input buffer size for psa_pake_input() for any of the supported cipher - * suites and PAKE algorithms. - * - * This macro must expand to a compile-time constant integer. - * - * See also #PSA_PAKE_INPUT_SIZE(\p alg, \p cipher_suite, \p output). - */ -#define PSA_PAKE_INPUT_MAX_SIZE 0 - #endif /* PSA_CRYPTO_SIZES_H */ diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index b20a17972..47012fdd0 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -461,81 +461,6 @@ static inline size_t psa_get_key_bits( return( attributes->core.bits ); } -struct psa_pake_cipher_suite_s -{ - psa_algorithm_t algorithm; - psa_pake_primitive_type_t type; - psa_pake_family_t family; - uint16_t bits; - psa_algorithm_t hash; -}; - -static inline psa_algorithm_t psa_pake_cs_get_algorithm( - const psa_pake_cipher_suite_t *cipher_suite) -{ - return( cipher_suite->algorithm ); -} - -static inline void psa_pake_cs_set_algorithm( - psa_pake_cipher_suite_t *cipher_suite, - psa_algorithm_t algorithm) -{ - if( !PSA_ALG_IS_PAKE(algorithm) ) - cipher_suite->algorithm = 0; - else - cipher_suite->algorithm = algorithm; -} - -static inline psa_pake_primitive_t psa_pake_cs_get_primitive( - const psa_pake_cipher_suite_t *cipher_suite) -{ - return( PSA_PAKE_PRIMITIVE( cipher_suite->type, cipher_suite->family, - cipher_suite->bits) ); -} - -static inline void psa_pake_cs_set_primitive( - psa_pake_cipher_suite_t *cipher_suite, - psa_pake_primitive_t primitive) -{ - cipher_suite->type = (psa_pake_primitive_type_t) (primitive >> 24); - cipher_suite->family = (psa_pake_family_t) ( 0xFF & (primitive >> 16) ); - cipher_suite->bits = (uint16_t) ( 0xFFFF & primitive ); -} - -static inline psa_algorithm_t psa_pake_cs_get_hash( - const psa_pake_cipher_suite_t *cipher_suite) -{ - return( cipher_suite->hash ); -} - -static inline void psa_pake_cs_set_hash( - psa_pake_cipher_suite_t *cipher_suite, - psa_algorithm_t hash) -{ - if( !PSA_ALG_IS_HASH(hash) ) - cipher_suite->hash = 0; - else - cipher_suite->hash = hash; -} - -struct psa_pake_operation_s -{ - psa_algorithm_t alg; - union - { - /* Make the union non-empty even with no supported algorithms. */ - uint8_t dummy; - } ctx; -}; - -/* This only zeroes out the first byte in the union, the rest is unspecified. */ -#define PSA_PAKE_OPERATION_INIT {0, {0}} -static inline struct psa_pake_operation_s psa_pake_operation_init( void ) -{ - const struct psa_pake_operation_s v = PSA_PAKE_OPERATION_INIT; - return( v ); -} - #ifdef __cplusplus } #endif diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h index 5a66a8709..386c7d794 100644 --- a/include/psa/crypto_types.h +++ b/include/psa/crypto_types.h @@ -380,46 +380,4 @@ typedef uint16_t psa_key_derivation_step_t; /**@}*/ -/** \defgroup pake Password-authenticated key exchange (PAKE) - * @{ - */ - -/** \brief Encoding of the side of PAKE - * - * Encodes which side of the algorithm is being executed. For more information - * see the documentation of individual \c PSA_PAKE_SIDE_XXX constants. - */ -typedef uint8_t psa_pake_side_t; - -/** Encoding of input and output indicators for PAKE. - * - * Some PAKE algorithms need to exchange more data than just a single key share. - * This type is for encoding additional input and output data for such - * algorithms. - */ -typedef uint8_t psa_pake_step_t; - -/** Encoding of the type of the PAKE's primitive. - * - * Values defined by this standard will never be in the range 0x80-0xff. - * Vendors who define additional types must use an encoding in this range. - * - * For more information see the documentation of individual - * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. - */ -typedef uint8_t psa_pake_primitive_type_t; - -/** \brief Encoding of the family of the primitive associated with the PAKE. - * - * For more information see the documentation of individual - * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. - */ -typedef uint8_t psa_pake_family_t; - -/** \brief Encoding of the primitive associated with the PAKE. - * - * For more information see the documentation of the #PSA_PAKE_PRIMITIVE macro. - */ -typedef uint32_t psa_pake_primitive_t; -/**@}*/ #endif /* PSA_CRYPTO_TYPES_H */ diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 37cd03024..497bd8f01 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -731,7 +731,6 @@ #define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x07000000) #define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x08000000) #define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x09000000) -#define PSA_ALG_CATEGORY_PAKE ((psa_algorithm_t)0x0a000000) /** Whether an algorithm is vendor-defined. * @@ -849,18 +848,6 @@ (PSA_ALG_IS_KEY_DERIVATION(alg) && \ (alg) & PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG) -/** Whether the specified algorithm is a password-authenticated key exchange. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a password-authenticated key exchange (PAKE) - * algorithm, 0 otherwise. - * This macro may return either 0 or 1 if \p alg is not a supported - * algorithm identifier. - */ -#define PSA_ALG_IS_PAKE(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_PAKE) - #define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) /** MD2 */ #define PSA_ALG_MD2 ((psa_algorithm_t)0x02000001) @@ -1966,109 +1953,6 @@ #define PSA_ALG_GET_HASH(alg) \ (((alg) & 0x000000ff) == 0 ? ((psa_algorithm_t)0) : 0x02000000 | ((alg) & 0x000000ff)) -/** The Password-authenticated key exchange by juggling (J-PAKE) algorithm. - * - * This is J-PAKE as defined by RFC 8236, instantiated with the following - * parameters: - * - * - The group can be either an elliptic curve or defined over a finite field. - * - Schnorr NIZK proof as defined by RFC 8235 and using the same group as the - * J-PAKE algorithm. - * - A secure cryptographic hash function. - * - * To select these parameters and set up the cipher suite, call - * psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_JPAKE); - * psa_pake_cs_set_primitive(cipher_suite, - * PSA_PAKE_PRIMITIVE(type, family, bits)); - * psa_pake_cs_set_hash(cipher_suite, hash); - * - * For more information on how to set a specific curve or field, refer to the - * documentation of the individual \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. - * - * After initializing a J-PAKE operation, call - * psa_pake_setup(operation, cipher_suite); - * psa_pake_set_user(operation, ...); - * psa_pake_set_peer(operation, ...); - * and either - * psa_pake_set_password_stretch(operation, ...); - * or - * psa_pake_set_password_key(operation, ...); - * - * Either way the password is read as a byte array and must be non-empty. This - * can be the password itself (in some pre-defined character encoding) or some - * value derived from the password as mandated by some higher level protocol. - * - * (The implementation converts this byte array to a number as described in - * Section 2.3.8 of _SEC 1: Elliptic Curve Cryptography_ - * (https://www.secg.org/sec1-v2.pdf), before reducing it modulo \c q. Here - * \c q is order of the group defined by the primitive set in the cipher suite. - * The \c psa_pake_set_password_xxx() functions return an error if the result - * of the reduction is 0.) - * - * The key exchange flow for J-PAKE is as follows: - * -# To get the first round data that needs to be sent to the peer, call - * // Get g1 - * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); - * // Get the ZKP public key for x1 - * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); - * // Get the ZKP proof for x1 - * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); - * // Get g2 - * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); - * // Get the ZKP public key for x2 - * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); - * // Get the ZKP proof for x2 - * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); - * -# To provide the first round data received from the peer to the operation, - * call - * // Set g3 - * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); - * // Set the ZKP public key for x3 - * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); - * // Set the ZKP proof for x3 - * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); - * // Set g4 - * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); - * // Set the ZKP public key for x4 - * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); - * // Set the ZKP proof for x4 - * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); - * -# To get the second round data that needs to be sent to the peer, call - * // Get A - * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); - * // Get ZKP public key for x2*s - * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); - * // Get ZKP proof for x2*s - * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); - * -# To provide the second round data received from the peer to the operation, - * call - * // Set B - * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); - * // Set ZKP public key for x4*s - * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); - * // Set ZKP proof for x4*s - * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); - * -# To access the shared secret call - * // Get Ka=Kb=K - * psa_pake_get_implicit_key() - * - * For more information consult the documentation of the individual - * \c PSA_PAKE_STEP_XXX constants. - * - * At this point there is a cryptographic guarantee that only the authenticated - * party who used the same password is able to compute the key. But there is no - * guarantee that the peer is the party he claims to be and was able to do so. - * - * That is, the authentication is only implicit (the peer is not authenticated - * at this point, and no action should be taken that assume that they are - like - * for example accessing restricted files). - * - * To make the authentication explicit there are various methods, see Section 5 - * of RFC 8236 for two examples. - * - */ -#define PSA_ALG_JPAKE ((psa_algorithm_t)0x0a000100) - /**@}*/ /** \defgroup key_lifetimes Key lifetimes @@ -2497,149 +2381,4 @@ static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) /**@}*/ -/** \defgroup pake Password-authenticated key exchange (PAKE) - * @{ - */ - -/** The first peer in a balanced PAKE. - * - * Although balanced PAKE algorithms are symmetric, some of them needs an - * ordering of peers for the transcript calculations. If the algorithm does not - * need this, both #PSA_PAKE_SIDE_FIRST and #PSA_PAKE_SIDE_SECOND are - * accepted. - */ -#define PSA_PAKE_SIDE_FIRST ((psa_pake_side_t)0x01) - -/** The second peer in a balanced PAKE. - * - * Although balanced PAKE algorithms are symmetric, some of them needs an - * ordering of peers for the transcript calculations. If the algorithm does not - * need this, either #PSA_PAKE_SIDE_FIRST or #PSA_PAKE_SIDE_SECOND are - * accepted. - */ -#define PSA_PAKE_SIDE_SECOND ((psa_pake_side_t)0x02) - -/** The client in an augmented PAKE. - * - * Augmented PAKE algorithms need to differentiate between client and server. - */ -#define PSA_PAKE_SIDE_CLIENT ((psa_pake_side_t)0x11) - -/** The server in an augmented PAKE. - * - * Augmented PAKE algorithms need to differentiate between client and server. - */ -#define PSA_PAKE_SIDE_SERVER ((psa_pake_side_t)0x12) - -/** The PAKE primitive type indicating the use of elliptic curves. - * - * The values of the \c family and \c bits fields of the cipher suite identify a - * specific elliptic curve, using the same mapping that is used for ECC - * (::psa_ecc_family_t) keys. - * - * (Here \c family means the value returned by psa_pake_cs_get_family() and - * \c bits means the value returned by psa_pake_cs_get_bits().) - * - * Input and output during the operation can involve group elements and scalar - * values: - * -# The format for group elements is the same as for public keys on the - * specific curve would be. For more information, consult the documentation of - * psa_export_public_key(). - * -# The format for scalars is the same as for private keys on the specific - * curve would be. For more information, consult the documentation of - * psa_export_key(). - */ -#define PSA_PAKE_PRIMITIVE_TYPE_ECC ((psa_pake_primitive_type_t)0x01) - -/** The PAKE primitive type indicating the use of Diffie-Hellman groups. - * - * The values of the \c family and \c bits fields of the cipher suite identify - * a specific Diffie-Hellman group, using the same mapping that is used for - * Diffie-Hellman (::psa_dh_family_t) keys. - * - * (Here \c family means the value returned by psa_pake_cs_get_family() and - * \c bits means the value returned by psa_pake_cs_get_bits().) - * - * Input and output during the operation can involve group elements and scalar - * values: - * -# The format for group elements is the same as for public keys on the - * specific group would be. For more information, consult the documentation of - * psa_export_public_key(). - * -# The format for scalars is the same as for private keys on the specific - * group would be. For more information, consult the documentation of - * psa_export_key(). - */ -#define PSA_PAKE_PRIMITIVE_TYPE_DH ((psa_pake_primitive_type_t)0x02) - -/** Construct a PAKE primitive from type, family and bit-size. - * - * \param pake_type The type of the primitive - * (value of type ::psa_pake_primitive_type_t). - * \param pake_family The family of the primitive - * (the type and interpretation of this parameter depends - * on \p type, for more information consult the - * documentation of individual ::psa_pake_primitive_type_t - * constants). - * \param pake_bits The bit-size of the primitive - * (Value of type \c size_t. The interpretation - * of this parameter depends on \p family, for more - * information consult the documentation of individual - * ::psa_pake_primitive_type_t constants). - * - * \return The constructed primitive value of type ::psa_pake_primitive_t. - * Return 0 if the requested primitive can't be encoded as - * ::psa_pake_primitive_t. - */ -#define PSA_PAKE_PRIMITIVE(pake_type, pake_family, pake_bits) \ - ((pake_bits & 0xFFFF) != pake_bits) ? 0 : \ - ((psa_pake_primitive_t) (((pake_type) << 24 | \ - (pake_family) << 16) | (pake_bits))) - -/** The key share being sent to or received from the peer. - * - * The format for both input and output at this step is the same as for public - * keys on the group determined by the primitive (::psa_pake_primitive_t) would - * be. - * - * For more information on the format, consult the documentation of - * psa_export_public_key(). - * - * For information regarding how the group is determined, consult the - * documentation #PSA_PAKE_PRIMITIVE. - */ -#define PSA_PAKE_STEP_KEY_SHARE ((psa_pake_step_t)0x01) - -/** A Schnorr NIZKP public key. - * - * The format for both input and output at this step is the same as for public - * keys on the group determined by the primitive (::psa_pake_primitive_t) would - * be. - * - * For more information on the format, consult the documentation of - * psa_export_public_key(). - * - * For information regarding how the group is determined, consult the - * documentation #PSA_PAKE_PRIMITIVE. - */ -#define PSA_PAKE_STEP_ZK_PUBLIC ((psa_pake_step_t)0x02) - -/** A Schnorr NIZKP proof. - * - * The format for both input and output at this step is the same as for private - * keys on the group determined by the primitive (::psa_pake_primitive_t) would - * be. - * - * Some public key algorithms mask the private keys and this might be reflected - * in the export format. Even if this is the case the masking is omitted at - * this step. - * - * For more information on the format, consult the documentation of - * psa_export_key(). - * - * For information regarding how the group is determined, consult the - * documentation #PSA_PAKE_PRIMITIVE. - */ -#define PSA_PAKE_STEP_ZK_PROOF ((psa_pake_step_t)0x03) - -/**@}*/ #endif /* PSA_CRYPTO_VALUES_H */ From 7d69b3a993d2785bc75299d8c5dfe7b7c20bf3e4 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 26 May 2021 13:10:56 +0100 Subject: [PATCH 54/69] PSA PAKE: add warning about stability We are not confident about the stability of the PAKE interface (it is just a proposal, not part of the standard yet). So we should explicitly document it as experimental, subject to change. Signed-off-by: Janos Follath --- include/psa/crypto_extra.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index 615b6511c..4478f3a43 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -937,6 +937,14 @@ psa_status_t mbedtls_psa_platform_get_builtin_key( /** @} */ /** \defgroup pake Password-authenticated key exchange (PAKE) + * + * This is a proposed PAKE interface for the PSA Crypto API. It is not part of + * the official PSA Crypto API yet. + * + * \note The content of this section is not part of the stable API and ABI + * of Mbed Crypto and may change arbitrarily from version to version. + * Same holds for the corresponding macros #PSA_ALG_CATEGORY_PAKE and + * #PSA_ALG_JPAKE. * @{ */ From 559f05eefc002dfc8f89e532d04e727bf91ed256 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 26 May 2021 15:44:30 +0100 Subject: [PATCH 55/69] PSA PAKE: remove psa_pake_set_password_stretch() The password stretching (using slow and/or memory hard hashes) in PAKEs usually serves two purposes: - Defending against server compromise impersonation attacks. J-PAKE is an augmented PAKE and as such, stores a password-equivalent and defending against this class of attacks is out of scope. - Preventing offline dictionary attacks. J-PAKE is proven to be zero knowledge and leaks no information beyond the fact if the passwords matched and offline dictionary attack is not possible. In summary: J-PAKE does not benefit from pasword stretching and is unlikely to be an input. This part of the API is not necessary at this point and can be added later. Signed-off-by: Janos Follath --- include/psa/crypto_extra.h | 80 +++----------------------------------- 1 file changed, 6 insertions(+), 74 deletions(-) diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index 4478f3a43..dcaf75568 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -854,14 +854,11 @@ psa_status_t mbedtls_psa_platform_get_builtin_key( * psa_pake_setup(operation, cipher_suite); * psa_pake_set_user(operation, ...); * psa_pake_set_peer(operation, ...); - * and either - * psa_pake_set_password_stretch(operation, ...); - * or * psa_pake_set_password_key(operation, ...); * - * Either way the password is read as a byte array and must be non-empty. This - * can be the password itself (in some pre-defined character encoding) or some - * value derived from the password as mandated by some higher level protocol. + * The password is read as a byte array and must be non-empty. This can be the + * password itself (in some pre-defined character encoding) or some value + * derived from the password as mandated by some higher level protocol. * * (The implementation converts this byte array to a number as described in * Section 2.3.8 of _SEC 1: Elliptic Curve Cryptography_ @@ -1348,19 +1345,15 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, /** Set the password for a password-authenticated key exchange from key ID. * * Call this function when the password, or a value derived from the password, - * is already present in the key store. To calculate the password-derived value - * from a password input, use the key derivation interface and - * psa_pake_set_password_stretch() instead. + * is already present in the key store. * * \param[in,out] operation The operation object to set the password for. It * must have been set up by psa_pake_setup() and * not yet in use (neither psa_pake_output() nor * psa_pake_input() has been called yet). It must * be on operation for which the password hasn't - * been set yet (neither - * psa_pake_set_password_stretch() nor - * psa_pake_set_password_key() has been called - * yet). + * been set yet (psa_pake_set_password_key() + * hasn't been called yet). * \param password Identifier of the key holding the password or a * value derived from the password (eg. by a * memory-hard function). It must remain valid @@ -1389,67 +1382,6 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, mbedtls_svc_key_id_t password); -/** Set the password for a password-authenticated key exchange via a key - * stretching function. - * - * Some protocols use values derived from passwords via key stretching - * functions to mitigate dictionary attacks. Key stretching functions can be - * accessed through the key derivation interface and the result can be supplied - * to the PAKE operation in the form of a key derivation object. - * - * This function draws bytes from a key derivation algorithm and sets those - * bytes as a password for the password-authenticated key exchange. 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 key derivation operation's capacity decreases by the number of bytes read. - * - * If this function returns anything other than #PSA_SUCCESS, both \p operation - * and \p key_derivation operations enter an error state and must be aborted by - * calling psa_pake_abort() and psa_key_derivation_abort() respectively. - * - * \param[in,out] operation The operation object to set the password for. - * It must have been set up by psa_pake_setup() - * and not yet in use (neither psa_pake_output() - * nor psa_pake_input() has been called yet). It - * must be on operation for which the password - * hasn't been set yet (neither - * psa_pake_set_password_stretch() nor - * psa_pake_set_password_key() has been called - * yet). - * \param[in,out] key_derivation An ongoing key derivation operation set up - * from the password and in a state suitable for - * calling psa_key_derivation_output_bytes(). - * \param input_length Number of bytes to input from the - * \p key_derivation operation. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_BAD_STATE - * The state of \p operation or \p key_derivation is not valid. - * \retval #PSA_ERROR_INSUFFICIENT_DATA - * The \p key_derivation operation's capacity was less than - * \p input_length bytes. - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_NOT_PERMITTED - * One of the inputs to \p key_derivation was a key whose policy didn't - * allow #PSA_KEY_USAGE_DERIVE. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p key is not compatible with the algorithm or the cipher suite. - * \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_pake_set_password_stretch( - psa_pake_operation_t *operation, - psa_key_derivation_operation_t *key_derivation, - size_t input_length - ); - /** Set the user ID for a password-authenticated key exchange. * * Call this function to set the user ID. For PAKE algorithms that associate a From 89ee05a80589e719bfde97c5d1b0cdcc55a3443c Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 26 May 2021 15:57:53 +0100 Subject: [PATCH 56/69] Rename psa_pake_set_password() Technically this function takes a low entropy secret as an input which might or might not be the password. Using the term "secret" in the function name is less misleading. Signed-off-by: Janos Follath --- include/psa/crypto_extra.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index dcaf75568..43d37b912 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -854,7 +854,7 @@ psa_status_t mbedtls_psa_platform_get_builtin_key( * psa_pake_setup(operation, cipher_suite); * psa_pake_set_user(operation, ...); * psa_pake_set_peer(operation, ...); - * psa_pake_set_password_key(operation, ...); + * psa_pake_set_secret_from_key(operation, ...); * * The password is read as a byte array and must be non-empty. This can be the * password itself (in some pre-defined character encoding) or some value @@ -1345,14 +1345,15 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, /** Set the password for a password-authenticated key exchange from key ID. * * Call this function when the password, or a value derived from the password, - * is already present in the key store. + * (for example a hash of the password or a key derived from the password) is + * already present in the key store. * * \param[in,out] operation The operation object to set the password for. It * must have been set up by psa_pake_setup() and * not yet in use (neither psa_pake_output() nor * psa_pake_input() has been called yet). It must * be on operation for which the password hasn't - * been set yet (psa_pake_set_password_key() + * been set yet (psa_pake_set_secret_from_key() * hasn't been called yet). * \param password Identifier of the key holding the password or a * value derived from the password (eg. by a @@ -1379,8 +1380,8 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, - mbedtls_svc_key_id_t password); +psa_status_t psa_pake_set_secret_from_key(psa_pake_operation_t *operation, + mbedtls_svc_key_id_t password); /** Set the user ID for a password-authenticated key exchange. * From 1f9e9e95c975b61297eee2c00f97daa21d93a55e Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 26 May 2021 16:10:25 +0100 Subject: [PATCH 57/69] PSA PAKE: fix old constant name in test Signed-off-by: Janos Follath --- tests/suites/test_suite_psa_crypto_metadata.data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_psa_crypto_metadata.data b/tests/suites/test_suite_psa_crypto_metadata.data index 0845b55d7..22056b0a8 100644 --- a/tests/suites/test_suite_psa_crypto_metadata.data +++ b/tests/suites/test_suite_psa_crypto_metadata.data @@ -295,7 +295,7 @@ depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_384 key_agreement_algorithm:PSA_ALG_KEY_AGREEMENT( PSA_ALG_ECDH, PSA_ALG_HKDF( PSA_ALG_SHA_384 ) ):ALG_IS_ECDH:PSA_ALG_ECDH:PSA_ALG_HKDF( PSA_ALG_SHA_384 ) PAKE: J-PAKE -pake_algorithm:PSA_ALG_PAKE_JPAKE +pake_algorithm:PSA_ALG_JPAKE Key type: raw data key_type:PSA_KEY_TYPE_RAW_DATA:KEY_TYPE_IS_UNSTRUCTURED From 52f9efad22a3c1dbeea5abd33479188ae2978e85 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 27 May 2021 08:40:16 +0100 Subject: [PATCH 58/69] Revert "Rename psa_pake_set_password()" This reverts commit 03a5fd7780026b2ca0b4728352ded930f5a7cff9. We're already calling the output of a PAKE a "shared secret". The password is a shared secret (for PAKE where the verifier knows a password-equivalent secret), but calling it "shared secret" or even just "secret" would be confusing. Signed-off-by: Janos Follath --- include/psa/crypto_extra.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index 43d37b912..dcaf75568 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -854,7 +854,7 @@ psa_status_t mbedtls_psa_platform_get_builtin_key( * psa_pake_setup(operation, cipher_suite); * psa_pake_set_user(operation, ...); * psa_pake_set_peer(operation, ...); - * psa_pake_set_secret_from_key(operation, ...); + * psa_pake_set_password_key(operation, ...); * * The password is read as a byte array and must be non-empty. This can be the * password itself (in some pre-defined character encoding) or some value @@ -1345,15 +1345,14 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, /** Set the password for a password-authenticated key exchange from key ID. * * Call this function when the password, or a value derived from the password, - * (for example a hash of the password or a key derived from the password) is - * already present in the key store. + * is already present in the key store. * * \param[in,out] operation The operation object to set the password for. It * must have been set up by psa_pake_setup() and * not yet in use (neither psa_pake_output() nor * psa_pake_input() has been called yet). It must * be on operation for which the password hasn't - * been set yet (psa_pake_set_secret_from_key() + * been set yet (psa_pake_set_password_key() * hasn't been called yet). * \param password Identifier of the key holding the password or a * value derived from the password (eg. by a @@ -1380,8 +1379,8 @@ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_pake_set_secret_from_key(psa_pake_operation_t *operation, - mbedtls_svc_key_id_t password); +psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, + mbedtls_svc_key_id_t password); /** Set the user ID for a password-authenticated key exchange. * From ec83eb605e0744e4975446d0e7e6c7b5c7329bb7 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 27 May 2021 08:41:59 +0100 Subject: [PATCH 59/69] Fix copy+paste mistake Signed-off-by: Janos Follath --- include/psa/crypto_extra.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index dcaf75568..997fec0b8 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -1692,7 +1692,7 @@ psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation, * #PSA_ALG_IS_PAKE(\p alg) is true). * \param primitive A primitive of type ::psa_pake_primitive_t that is * compatible with algorithm \p alg. - * \param output_step A value of type ::psa_pake_step_t that is valid for the + * \param input_step A value of type ::psa_pake_step_t that is valid for the * algorithm \p alg. * \return A sufficient output buffer size for the specified * output, cipher suite and algorithm. If the cipher suite, From a46e28f7861203b983e904f5040ae512ec5dc36a Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 3 Jun 2021 13:07:03 +0100 Subject: [PATCH 60/69] PSA PAKE: use neutral pronouns Signed-off-by: Janos Follath --- include/psa/crypto_extra.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index 997fec0b8..02e87ffa2 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -919,7 +919,7 @@ psa_status_t mbedtls_psa_platform_get_builtin_key( * * At this point there is a cryptographic guarantee that only the authenticated * party who used the same password is able to compute the key. But there is no - * guarantee that the peer is the party he claims to be and was able to do so. + * guarantee that the peer is the party it claims to be and was able to do so. * * That is, the authentication is only implicit (the peer is not authenticated * at this point, and no action should be taken that assume that they are - like @@ -1604,7 +1604,7 @@ psa_status_t psa_pake_input(psa_pake_operation_t *operation, * * At this point there is a cryptographic guarantee that only the authenticated * party who used the same password is able to compute the key. But there is no - * guarantee that the peer is the party he claims to be and was able to do so. + * guarantee that the peer is the party it claims to be and was able to do so. * * That is, the authentication is only implicit (the peer is not authenticated * at this point, and no action should be taken that assume that they are - like From 38d29db75fd2c06a899341895fbeec989c1d1fb6 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 3 Jun 2021 13:14:42 +0100 Subject: [PATCH 61/69] Fix copy+paste mistake Signed-off-by: Janos Follath --- include/psa/crypto_extra.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index 02e87ffa2..dd99839cc 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -1694,9 +1694,9 @@ psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation, * compatible with algorithm \p alg. * \param input_step A value of type ::psa_pake_step_t that is valid for the * algorithm \p alg. - * \return A sufficient output buffer size for the specified - * output, cipher suite and algorithm. If the cipher suite, - * the output type or PAKE algorithm is not recognized, or + * \return A sufficient input buffer size for the specified + * input, cipher suite and algorithm. If the cipher suite, + * the input type or PAKE algorithm is not recognized, or * the parameters are incompatible, return 0. */ #define PSA_PAKE_INPUT_SIZE(alg, primitive, input_step) 0 @@ -1715,7 +1715,7 @@ psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation, * * This macro must expand to a compile-time constant integer. * - * See also #PSA_PAKE_INPUT_SIZE(\p alg, \p cipher_suite, \p output). + * See also #PSA_PAKE_INPUT_SIZE(\p alg, \p cipher_suite, \p input). */ #define PSA_PAKE_INPUT_MAX_SIZE 0 From b4db90fb27008932fe5735f7572885c22243e52d Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 3 Jun 2021 13:17:09 +0100 Subject: [PATCH 62/69] PSA PAKE: improve documentation Signed-off-by: Janos Follath --- include/psa/crypto_extra.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index dd99839cc..66c9f9c20 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -1606,9 +1606,10 @@ psa_status_t psa_pake_input(psa_pake_operation_t *operation, * party who used the same password is able to compute the key. But there is no * guarantee that the peer is the party it claims to be and was able to do so. * - * That is, the authentication is only implicit (the peer is not authenticated - * at this point, and no action should be taken that assume that they are - like - * for example accessing restricted files). + * That is, the authentication is only implicit. Since the peer is not + * authenticated yet, no action should be taken yet that assumes that the peer + * is who it claims to be. For example, do not access restricted files on the + * peer's behalf until an explicit authentication has succeeded. * * This function can be called after the key exchange phase of the operation * has completed. It imports the shared secret output of the PAKE into the @@ -1683,8 +1684,9 @@ psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation, /** A sufficient input buffer size for psa_pake_input(). * - * If the size of the input is larger than this, it is guaranteed - * that psa_pake_input() will fail with #PSA_ERROR_INVALID_ARGUMENT. + * The value returned by this macro is guaranteed to be large enough for any + * valid input to psa_pake_input() in an operation with the specified + * parameters. * * See also #PSA_PAKE_INPUT_MAX_SIZE * From 3293dae00eaf300bd6f180181c253551b7506d3e Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 3 Jun 2021 13:21:33 +0100 Subject: [PATCH 63/69] psa_pake_setup(): simplify documentation This level of detail can be confusing and could require even more detail to clear it up. Simplifying it instead in alignment wiht the documentation of existing setup functions. Signed-off-by: Janos Follath --- include/psa/crypto_extra.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index 66c9f9c20..a7425deb2 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -1317,10 +1317,7 @@ static psa_pake_operation_t psa_pake_operation_init(void); * - A successful call to psa_pake_get_implicit_key(). * * \param[in,out] operation The operation object to set up. It must have - * been initialized as per the documentation for - * #psa_pake_operation_t and not yet in use (no - * other function has been called on it since the - * last initialization). + * been initialized but not set up yet. * \param cipher_suite The cipher suite to use. (A cipher suite fully * characterizes a PAKE algorithm and determines * the algorithm as well.) From b384ec19d188eb58056367d481d4091e8dba6390 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 3 Jun 2021 14:48:51 +0100 Subject: [PATCH 64/69] PSA PAKE: fix J-PAKE documentation code rendering 4-space indent is only guaranteed to result in a code block if there's a blank line just before (details vary depending on the markdown implementation, and doxygen isn't exactly markdown anyway). In a bullet list, you need 8 spaces since the list itself is a nested construct which takes a 4-space indent (even though you don't have to indent continuation lines inside a bullet point by 4 spaces, 1 is enough). Using \code...\encode which is rendering as intended. Signed-off-by: Janos Follath --- include/psa/crypto_extra.h | 108 +++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 46 deletions(-) diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index a7425deb2..717db2bc9 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -842,19 +842,25 @@ psa_status_t mbedtls_psa_platform_get_builtin_key( * - A secure cryptographic hash function. * * To select these parameters and set up the cipher suite, call - * psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_JPAKE); - * psa_pake_cs_set_primitive(cipher_suite, - * PSA_PAKE_PRIMITIVE(type, family, bits)); - * psa_pake_cs_set_hash(cipher_suite, hash); + * + * \code + * psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_JPAKE); + * psa_pake_cs_set_primitive(cipher_suite, + * PSA_PAKE_PRIMITIVE(type, family, bits)); + * psa_pake_cs_set_hash(cipher_suite, hash); + * \endcode * * For more information on how to set a specific curve or field, refer to the * documentation of the individual \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. * * After initializing a J-PAKE operation, call - * psa_pake_setup(operation, cipher_suite); - * psa_pake_set_user(operation, ...); - * psa_pake_set_peer(operation, ...); - * psa_pake_set_password_key(operation, ...); + * + * \code + * psa_pake_setup(operation, cipher_suite); + * psa_pake_set_user(operation, ...); + * psa_pake_set_peer(operation, ...); + * psa_pake_set_password_key(operation, ...); + * \endcode * * The password is read as a byte array and must be non-empty. This can be the * password itself (in some pre-defined character encoding) or some value @@ -869,50 +875,60 @@ psa_status_t mbedtls_psa_platform_get_builtin_key( * * The key exchange flow for J-PAKE is as follows: * -# To get the first round data that needs to be sent to the peer, call - * // Get g1 - * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); - * // Get the ZKP public key for x1 - * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); - * // Get the ZKP proof for x1 - * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); - * // Get g2 - * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); - * // Get the ZKP public key for x2 - * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); - * // Get the ZKP proof for x2 - * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \code + * // Get g1 + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Get the ZKP public key for x1 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Get the ZKP proof for x1 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * // Get g2 + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Get the ZKP public key for x2 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Get the ZKP proof for x2 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \endcode * -# To provide the first round data received from the peer to the operation, * call - * // Set g3 - * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); - * // Set the ZKP public key for x3 - * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); - * // Set the ZKP proof for x3 - * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); - * // Set g4 - * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); - * // Set the ZKP public key for x4 - * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); - * // Set the ZKP proof for x4 - * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \code + * // Set g3 + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Set the ZKP public key for x3 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Set the ZKP proof for x3 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * // Set g4 + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Set the ZKP public key for x4 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Set the ZKP proof for x4 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \endcode * -# To get the second round data that needs to be sent to the peer, call - * // Get A - * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); - * // Get ZKP public key for x2*s - * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); - * // Get ZKP proof for x2*s - * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \code + * // Get A + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Get ZKP public key for x2*s + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Get ZKP proof for x2*s + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \endcode * -# To provide the second round data received from the peer to the operation, * call - * // Set B - * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); - * // Set ZKP public key for x4*s - * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); - * // Set ZKP proof for x4*s - * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \code + * // Set B + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Set ZKP public key for x4*s + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Set ZKP proof for x4*s + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \endcode * -# To access the shared secret call - * // Get Ka=Kb=K - * psa_pake_get_implicit_key() + * \code + * // Get Ka=Kb=K + * psa_pake_get_implicit_key() + * \endcode * * For more information consult the documentation of the individual * \c PSA_PAKE_STEP_XXX constants. From 55dd5dc3556be0eeccf943cc29fd0077be553003 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Thu, 3 Jun 2021 15:51:09 +0100 Subject: [PATCH 65/69] PSA PAKE: Clarify the documentation of NIZKP steps The expression "the masking is omitted" assumes familiarity with Montgomery curve private key format and even then can be confusing and ambiguous or confusing. Describe directly what format we mean and add some more background information and reference to the standard as well. Signed-off-by: Janos Follath --- include/psa/crypto_extra.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index 717db2bc9..e4a21d44b 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -1108,6 +1108,9 @@ typedef uint32_t psa_pake_primitive_t; #define PSA_PAKE_STEP_KEY_SHARE ((psa_pake_step_t)0x01) /** A Schnorr NIZKP public key. + * + * This is the ephemeral public key in the Schnorr Non-Interactive + * Zero-Knowledge Proof (the value denoted by the letter 'V' in RFC 8235). * * The format for both input and output at this step is the same as for public * keys on the group determined by the primitive (::psa_pake_primitive_t) would @@ -1123,16 +1126,16 @@ typedef uint32_t psa_pake_primitive_t; /** A Schnorr NIZKP proof. * - * The format for both input and output at this step is the same as for private - * keys on the group determined by the primitive (::psa_pake_primitive_t) would - * be. + * This is the proof in the Schnorr Non-Interactive Zero-Knowledge Proof (the + * value denoted by the letter 'r' in RFC 8235). * - * Some public key algorithms mask the private keys and this might be reflected - * in the export format. Even if this is the case the masking is omitted at - * this step. + * Both input and output at this step is an integer less than the group + * selected in the cipher suite. The format depends on the group as well: * - * For more information on the format, consult the documentation of - * psa_export_key(). + * - For Montgomery curves, the encoding is little endian (see decoding of + * scalars in Section 5 of RFC 7748). + * - For everything else the encoding is big endian (see Section 2.3.8 of + * _SEC 1: Elliptic Curve Cryptography_ at https://www.secg.org/sec1-v2.pdf). * * For information regarding how the group is determined, consult the * documentation #PSA_PAKE_PRIMITIVE. From 33434a9f60f18894953eb64ffd699d5774cd1a37 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Wed, 26 May 2021 09:25:33 +0100 Subject: [PATCH 66/69] Fix parenthesis spacing in crypto_struct.h crypto_struct.h is implementation-specific so it was intended to have Mbed TLS whitespace style. Signed-off-by: Janos Follath --- include/psa/crypto_struct.h | 64 ++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index 47012fdd0..406007445 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -92,7 +92,7 @@ struct psa_hash_operation_s psa_driver_hash_context_t ctx; }; -#define PSA_HASH_OPERATION_INIT {0, {0}} +#define PSA_HASH_OPERATION_INIT { 0, { 0 } } static inline struct psa_hash_operation_s psa_hash_operation_init( void ) { const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT; @@ -117,7 +117,7 @@ struct psa_cipher_operation_s psa_driver_cipher_context_t ctx; }; -#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, 0, {0}} +#define PSA_CIPHER_OPERATION_INIT { 0, 0, 0, 0, { 0 } } static inline struct psa_cipher_operation_s psa_cipher_operation_init( void ) { const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT; @@ -142,7 +142,7 @@ struct psa_mac_operation_s psa_driver_mac_context_t ctx; }; -#define PSA_MAC_OPERATION_INIT {0, 0, 0, {0}} +#define PSA_MAC_OPERATION_INIT { 0, 0, 0, { 0 } } static inline struct psa_mac_operation_s psa_mac_operation_init( void ) { const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT; @@ -163,7 +163,7 @@ struct psa_aead_operation_s } ctx; }; -#define PSA_AEAD_OPERATION_INIT {0, 0, 0, 0, 0, {0}} +#define PSA_AEAD_OPERATION_INIT { 0, 0, 0, 0, 0, { 0 } } static inline struct psa_aead_operation_s psa_aead_operation_init( void ) { const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT; @@ -223,7 +223,7 @@ typedef struct psa_tls12_prf_key_derivation_s uint8_t Ai[PSA_HASH_MAX_SIZE]; - /* `HMAC_hash( prk, A(i) + seed )` in the notation of RFC 5246, Sect. 5. */ + /* `HMAC_hash( prk, A( i ) + seed )` in the notation of RFC 5246, Sect. 5. */ uint8_t output_block[PSA_HASH_MAX_SIZE]; } psa_tls12_prf_key_derivation_t; #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || @@ -249,8 +249,9 @@ struct psa_key_derivation_s }; /* This only zeroes out the first byte in the union, the rest is unspecified. */ -#define PSA_KEY_DERIVATION_OPERATION_INIT {0, 0, 0, {0}} -static inline struct psa_key_derivation_s psa_key_derivation_operation_init( void ) +#define PSA_KEY_DERIVATION_OPERATION_INIT { 0, 0, 0, { 0 } } +static inline +struct psa_key_derivation_s psa_key_derivation_operation_init( void ) { const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT; return( v ); @@ -264,7 +265,7 @@ struct psa_key_policy_s }; typedef struct psa_key_policy_s psa_key_policy_t; -#define PSA_KEY_POLICY_INIT {0, 0, 0} +#define PSA_KEY_POLICY_INIT { 0, 0, 0 } static inline struct psa_key_policy_s psa_key_policy_init( void ) { const struct psa_key_policy_s v = PSA_KEY_POLICY_INIT; @@ -276,7 +277,7 @@ static inline struct psa_key_policy_s psa_key_policy_init( void ) 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 ) ) +#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. @@ -317,7 +318,10 @@ typedef struct psa_key_attributes_flag_t flags; } psa_core_key_attributes_t; -#define PSA_CORE_KEY_ATTRIBUTES_INIT {PSA_KEY_TYPE_NONE, 0, PSA_KEY_LIFETIME_VOLATILE, MBEDTLS_SVC_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0} +#define PSA_CORE_KEY_ATTRIBUTES_INIT { PSA_KEY_TYPE_NONE, 0, \ + PSA_KEY_LIFETIME_VOLATILE, \ + MBEDTLS_SVC_KEY_ID_INIT, \ + PSA_KEY_POLICY_INIT, 0 } struct psa_key_attributes_s { @@ -330,9 +334,9 @@ struct psa_key_attributes_s }; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) -#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0} +#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} +#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 ) @@ -358,7 +362,7 @@ static inline void psa_set_key_id( psa_key_attributes_t *attributes, } static inline mbedtls_svc_key_id_t psa_get_key_id( - const psa_key_attributes_t *attributes) + const psa_key_attributes_t *attributes ) { return( attributes->core.id ); } @@ -371,8 +375,8 @@ static inline void mbedtls_set_key_owner_id( psa_key_attributes_t *attributes, } #endif -static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, - psa_key_lifetime_t lifetime) +static inline void psa_set_key_lifetime( psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime ) { attributes->core.lifetime = lifetime; if( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) ) @@ -386,44 +390,44 @@ static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, } static inline psa_key_lifetime_t psa_get_key_lifetime( - const psa_key_attributes_t *attributes) + 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) +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) + 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) +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) + 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_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); + size_t data_length ); -static inline void psa_set_key_type(psa_key_attributes_t *attributes, - psa_key_type_t type) +static inline void psa_set_key_type( psa_key_attributes_t *attributes, + psa_key_type_t type ) { if( attributes->domain_parameters == NULL ) { @@ -441,13 +445,13 @@ static inline void psa_set_key_type(psa_key_attributes_t *attributes, } static inline psa_key_type_t psa_get_key_type( - const psa_key_attributes_t *attributes) + 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) +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; @@ -456,7 +460,7 @@ static inline void psa_set_key_bits(psa_key_attributes_t *attributes, } static inline size_t psa_get_key_bits( - const psa_key_attributes_t *attributes) + const psa_key_attributes_t *attributes ) { return( attributes->core.bits ); } From 0dcda95ac04162c0b328ef95622d3886cfa3184a Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 7 Jun 2021 14:52:13 +0100 Subject: [PATCH 67/69] Make check-names.sh happy Signed-off-by: Janos Follath --- include/psa/crypto_struct.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index 406007445..1be9949f4 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -250,8 +250,8 @@ struct psa_key_derivation_s /* This only zeroes out the first byte in the union, the rest is unspecified. */ #define PSA_KEY_DERIVATION_OPERATION_INIT { 0, 0, 0, { 0 } } -static inline -struct psa_key_derivation_s psa_key_derivation_operation_init( void ) +static inline struct psa_key_derivation_s psa_key_derivation_operation_init( + void ) { const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT; return( v ); From 46c02375b730b53f2bfbfd9c49396018a8511711 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 8 Jun 2021 15:22:51 +0100 Subject: [PATCH 68/69] PSA PAKE: improve documentation Signed-off-by: Janos Follath --- include/psa/crypto_extra.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index e4a21d44b..c5ae09959 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -839,9 +839,10 @@ psa_status_t mbedtls_psa_platform_get_builtin_key( * - The group can be either an elliptic curve or defined over a finite field. * - Schnorr NIZK proof as defined by RFC 8235 and using the same group as the * J-PAKE algorithm. - * - A secure cryptographic hash function. + * - A cryptographic hash function. * - * To select these parameters and set up the cipher suite, call + * To select these parameters and set up the cipher suite, call these functions + * in any order: * * \code * psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_JPAKE); @@ -1499,8 +1500,8 @@ psa_status_t psa_pake_set_peer(psa_pake_operation_t *operation, * yet). * \param side A value of type ::psa_pake_side_t signaling the * side of the algorithm that is being set up. For - * more information see the documentation of \c - * PSA_PAKE_SIDE_XXX constants. + * more information see the documentation of + * \c PSA_PAKE_SIDE_XXX constants. * * \retval #PSA_SUCCESS * Success. @@ -1652,8 +1653,8 @@ psa_status_t psa_pake_input(psa_pake_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (it must be active, but beyond that - * validity is specific to the algorithm). + * The PAKE operation state is not valid (it must be active, but beyond + * that validity is specific to the algorithm). * \retval #PSA_ERROR_BAD_STATE * The state of \p output is not valid for * the #PSA_KEY_DERIVATION_INPUT_SECRET step. This can happen if the @@ -1685,7 +1686,7 @@ psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation, * * See also #PSA_PAKE_OUTPUT_MAX_SIZE * - * \param alg A PAKE algorithm (PSA_ALG_XXX value such that + * \param alg A PAKE algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_PAKE(\p alg) is true). * \param primitive A primitive of type ::psa_pake_primitive_t that is * compatible with algorithm \p alg. @@ -1706,7 +1707,7 @@ psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation, * * See also #PSA_PAKE_INPUT_MAX_SIZE * - * \param alg A PAKE algorithm (PSA_ALG_XXX value such that + * \param alg A PAKE algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_PAKE(\p alg) is true). * \param primitive A primitive of type ::psa_pake_primitive_t that is * compatible with algorithm \p alg. From 1f0131844ce98a50aab4e4c3b4ea70268aa8e72a Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Tue, 8 Jun 2021 15:30:48 +0100 Subject: [PATCH 69/69] Clarify PSA_PAKE_STEP_ZK_PROOF format Removing reference to RFC 7748 as it is more confusing than helpful. (It decodes the scalars after masking which is not part of the encoding we want to specify. Also, it has the explanation what it means by little endian in a preceding section that is not trivial to find.) We also explicitly specify constraint on leading zeroes. Signed-off-by: Janos Follath --- include/psa/crypto_extra.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index c5ae09959..0567e8a73 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -1130,14 +1130,17 @@ typedef uint32_t psa_pake_primitive_t; * This is the proof in the Schnorr Non-Interactive Zero-Knowledge Proof (the * value denoted by the letter 'r' in RFC 8235). * - * Both input and output at this step is an integer less than the group - * selected in the cipher suite. The format depends on the group as well: + * Both for input and output, the value at this step is an integer less than + * the order of the group selected in the cipher suite. The format depends on + * the group as well: * - * - For Montgomery curves, the encoding is little endian (see decoding of - * scalars in Section 5 of RFC 7748). + * - For Montgomery curves, the encoding is little endian. * - For everything else the encoding is big endian (see Section 2.3.8 of * _SEC 1: Elliptic Curve Cryptography_ at https://www.secg.org/sec1-v2.pdf). * + * In both cases leading zeroes are allowed as long as the length in bytes does + * not exceed the byte length of the group order. + * * For information regarding how the group is determined, consult the * documentation #PSA_PAKE_PRIMITIVE. */