From 9c6b147d98fac6a12ea0be7337fb4c679432d2ae Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Sun, 21 Mar 2021 15:11:01 +0000 Subject: [PATCH] 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 ) {