diff --git a/doc/ext-pake/api.db/psa/crypto-pake.h b/doc/ext-pake/api.db/psa/crypto-pake.h index 7e0a3c7e..5023b79a 100644 --- a/doc/ext-pake/api.db/psa/crypto-pake.h +++ b/doc/ext-pake/api.db/psa/crypto-pake.h @@ -8,9 +8,26 @@ typedef uint32_t psa_pake_primitive_t; typedef uint8_t psa_pake_primitive_type_t; typedef uint8_t psa_pake_role_t; typedef uint8_t psa_pake_step_t; +#define PSA_ALG_IS_JPAKE(alg) /* specification-defined value */ #define PSA_ALG_IS_PAKE(alg) /* specification-defined value */ -#define PSA_ALG_JPAKE ((psa_algorithm_t)0x0a000100) +#define PSA_ALG_IS_SPAKE2P(alg) /* specification-defined value */ +#define PSA_ALG_IS_SPAKE2P_CMAC(alg) /* specification-defined value */ +#define PSA_ALG_IS_SPAKE2P_HMAC(alg) /* specification-defined value */ +#define PSA_ALG_JPAKE(hash_alg) /* specification-defined value */ +#define PSA_ALG_SPAKE2P_CMAC(hash_alg) /* specification-defined value */ +#define PSA_ALG_SPAKE2P_HMAC(hash_alg) /* specification-defined value */ +#define PSA_ALG_SPAKE2P_MATTER ((psa_algoirithm_t)0x0A000609) +#define PSA_KEY_TYPE_IS_SPAKE2P(type) /* specification-defined value */ +#define PSA_KEY_TYPE_IS_SPAKE2P_KEY_PAIR(type) \ + /* specification-defined value */ +#define PSA_KEY_TYPE_IS_SPAKE2P_PUBLIC_KEY(type) \ + /* specification-defined value */ +#define PSA_KEY_TYPE_SPAKE2P_GET_FAMILY(type) /* specification-defined value */ +#define PSA_KEY_TYPE_SPAKE2P_KEY_PAIR(curve) /* specification-defined value */ +#define PSA_KEY_TYPE_SPAKE2P_PUBLIC_KEY(curve) \ + /* specification-defined value */ #define PSA_PAKE_CIPHER_SUITE_INIT /* implementation-defined value */ +#define PSA_PAKE_CONFIRMED_KEY 0 #define PSA_PAKE_INPUT_MAX_SIZE /* implementation-defined value */ #define PSA_PAKE_INPUT_SIZE(alg, primitive, input_step) \ /* implementation-defined value */ @@ -27,22 +44,25 @@ typedef uint8_t psa_pake_step_t; #define PSA_PAKE_ROLE_NONE ((psa_pake_role_t)0x00) #define PSA_PAKE_ROLE_SECOND ((psa_pake_role_t)0x02) #define PSA_PAKE_ROLE_SERVER ((psa_pake_role_t)0x12) +#define PSA_PAKE_STEP_CONFIRM ((psa_pake_step_t)0x04) #define PSA_PAKE_STEP_KEY_SHARE ((psa_pake_step_t)0x01) #define PSA_PAKE_STEP_ZK_PROOF ((psa_pake_step_t)0x03) #define PSA_PAKE_STEP_ZK_PUBLIC ((psa_pake_step_t)0x02) +#define PSA_PAKE_UNCONFIRMED_KEY 1 psa_status_t psa_pake_abort(psa_pake_operation_t * operation); psa_pake_cipher_suite_t psa_pake_cipher_suite_init(void); psa_algorithm_t psa_pake_cs_get_algorithm(const psa_pake_cipher_suite_t* cipher_suite); -psa_pake_primitive_t psa_pake_cs_get_hash(const psa_pake_cipher_suite_t* cipher_suite); +uint32_t psa_pake_cs_get_key_confirmation(const psa_pake_cipher_suite_t* cipher_suite); psa_pake_primitive_t psa_pake_cs_get_primitive(const psa_pake_cipher_suite_t* cipher_suite); void psa_pake_cs_set_algorithm(psa_pake_cipher_suite_t* cipher_suite, psa_algorithm_t alg); -void psa_pake_cs_set_hash(psa_pake_cipher_suite_t* cipher_suite, - psa_algorithm_t hash_alg); +void psa_pake_cs_set_key_confirmation(psa_pake_cipher_suite_t* cipher_suite, + uint32_t key_confirmation); void psa_pake_cs_set_primitive(psa_pake_cipher_suite_t* cipher_suite, psa_pake_primitive_t primitive); -psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation, - psa_key_derivation_operation_t *output); +psa_status_t psa_pake_get_shared_key(psa_pake_operation_t *operation, + const psa_key_attributes_t * attributes, + psa_key_id_t * key); psa_status_t psa_pake_input(psa_pake_operation_t *operation, psa_pake_step_t step, const uint8_t *input, @@ -53,6 +73,9 @@ psa_status_t psa_pake_output(psa_pake_operation_t *operation, uint8_t *output, size_t output_size, size_t *output_length); +psa_status_t psa_pake_set_context(psa_pake_operation_t *operation, + const uint8_t *context, + size_t context_len); psa_status_t psa_pake_set_peer(psa_pake_operation_t *operation, const uint8_t *peer_id, size_t peer_id_len); diff --git a/doc/ext-pake/api/pake.rst b/doc/ext-pake/api/pake.rst index ec1c5bbc..4ac49806 100644 --- a/doc/ext-pake/api/pake.rst +++ b/doc/ext-pake/api/pake.rst @@ -39,6 +39,11 @@ The algorithm identifier for PAKE algorithms defined in this specification are e The defined values for PAKE-TYPE are shown in :numref:`table-pake-type`. +The permitted values of HASH-TYPE depend on the specific PAKE algorithm. + +.. + The permitted values of HASH-TYPE (see :numref:`table-hash-type`) depend on the specific PAKE algorithm. + .. csv-table:: PAKE algorithm sub-type values :name: table-pake-type :header-rows: 1 @@ -46,7 +51,106 @@ The defined values for PAKE-TYPE are shown in :numref:`table-pake-type`. :widths: auto PAKE algorithm, PAKE-TYPE, Algorithm identifier, Algorithm value - J-PAKE, ``0x01``, `PSA_ALG_JPAKE`, ``0x0A000100`` + J-PAKE, ``0x01``, :code:`PSA_ALG_JPAKE(hash)`, ``0x0A0001hh`` :sup:`a` + SPAKE2+ wih HMAC, ``0x04``, :code:`PSA_ALG_SPAKE2P_HMAC(hash)`, ``0x0A0004hh`` :sup:`a` + SPAKE2+ wih CMAC, ``0x05``, :code:`PSA_ALG_SPAKE2P_CMAC(hash)`, ``0x0A0005hh`` :sup:`a` + SPAKE2+ for Matter, ``0x06``, :code:`PSA_ALG_SPAKE2P_MATTER`, ``0x0A000609`` :sup:`a` + +a. ``hh`` is the HASH-TYPE for the hash algorithm, ``hash``, used to construct the key derivation algorithm. + +Key encoding +------------ + +A new type of asymmetric key is added for the SPAKE2+ algorithms. The Asymmetric key sub-type values table in `[PSA-CRYPT]` Appendix B is extended with the information in :numref:`table-spake2p-keys`. + +.. csv-table:: New SPAKE2+ asymmetric key sub-type + :name: table-spake2p-keys + :header-rows: 1 + :align: left + :widths: auto + + Asymmetric key type, ASYM-TYPE, Details + SPAKE2+, 4, See :secref:`spakep2-key-encoding` + +.. rationale:: + + The ASYM-TYPE value 4 is selected as this has the same parity as the ECC sub-type, which have the value 1. The enables the same ECC-FAMILY and P values to be used when encoding a SPAKE2+ key type, as is used in the Elliptic Curve key types. + +.. _spakep2-key-encoding: + +SPAKE2+ key encoding +~~~~~~~~~~~~~~~~~~~~ + +The key type for SPAKE2+ keys defined in this specification are encoded as shown in :numref:`fig-spake2p-key-fields`. + +.. figure:: ../figure/spake2p_key.* + :name: fig-spake2p-key-fields + + SPAKE2+ key encoding + +PAIR is either 0 for a public key, or 3 for a key pair. + +The defined values for ECC-FAMILY and P are shown in :numref:`table-spake2p-type`. + +.. csv-table:: SPAKE2+ key family values + :name: table-spake2p-type + :header-rows: 1 + :align: left + :widths: auto + + SPAKE2+ group, ECC-FAMILY, P, ECC family :sup:`a`, Public key value, Key pair value + SECP R1, 0x09, 0, :code:`PSA_ECC_FAMILY_SECP_R1`, ``0x4412``, ``0x7412`` + Twisted Edwards, 0x21, 0, :code:`PSA_ECC_FAMILY_TWISTED_EDWARDS`, ``0x4442``, ``0x7442`` + +a. The key type value is constructed from the Elliptic Curve family using either :code:`PSA_KEY_TYPE_SPAKE2P_PUBLIC_KEY(family)` or :code:`PSA_KEY_TYPE_SPAKE2P_KEY_PAIR(family)` as required. + +Key formats +----------- + +A SPAKE2+ public key can be exported and imported, to enable use cases that require offline registration. + +The public key consists of the two values w0 and L, which result from the SPAKE2+ registration phase. w0 is a scalar in the same range as a private Elliptic curve key from the group used as the SPAKE2+ primitive group. L is a point on the curve, similar to a public key from the same group. + +The default format for the SPAKE2+ public key is the concatenation of the formatted values for w0 and L, using the the standard formats for Elliptic curve keys. For example, for SPAKE2+ over P-256 (secp256r1), the output from :code:`psa_export_public_key()` would be: + + [ w0 ]\ :sub:`32` || ``0x04`` || [ x\ :sub:`L` ]\ :sub:`32` || [ y\ :sub:`L` ]\ :sub:`32` + +Where [ v ]\ :sub:`n` is an n-byte, big-endian encoding of the integer value v. + +.. todo:: + In this example, how does using a 'concatenation of elements' depiction compare to the 'bullet list of elements' approach used in the Weierstrass public key format in §9.6.4? For example, the above would be described as: + + For example, for SPAKE2+ over P-256 (secp256r1), the output from :code:`psa_export_public_key()` would be the concatenation of: + + * w0, as a big-endian encoded, 32-byte string + * The byte ``0x04`` + * x\ :sub:`L` (the x-coordinate of L), as a big-endian encoded, 32-byte string + * y\ :sub:`L` (the y-coordinate of L), as a big-endian encoded, 32-byte string + +.. todo:: + In this example, how does the short-hand notation --- [ v ]\ :sub:`n` --- compare with the text description approach used in the Weierstrass public key format in §9.6.4, or the function-based (e.g. ``I2OSP()``) approach used in texts such as SEC1? For example, the above would be described as: + + For example, for SPAKE2+ over P-256 (secp256r1), the output from :code:`psa_export_public_key()` would be: + + I2OSP(w0, 32) || ``0x04`` || I2OSP(x\ :sub:`L`, 32) || I2OSP(y\ :sub:`L`, 32) + +.. todo:: + Would it be better to provide an explicit definition for all of the elliptic curves over which SPAKE2+ is defined, rather than just provide a single example? + +.. todo:: + It might also be time to decide on how to style/format pseudo-mathematical content of the specification. Presently there is a arbitrary mixture of ``monospace code/LaTeX-source-style material a^b = 1, F_q`` (as typical in IETF RFCs) and *emphasized* or regular font .rst material a\ :sup:`b` = 1, *F*\ :sub:`q` (seen in NIST publications, and some IETF RFCs). But we also have the ability to use the ``:math:`` role to :math:`\text{render like LaTeX: } a^b=1, \mathbb{F}_q` (used in SECG and some NIST publications). For comparison: + + .. list-table:: + :class: borderless + :widths: auto + :align: left + + * - Monospace + - ``I2OSP(w0, 32) || 0x04 || I2OSP(x_L, 32) || I2OSP(y_L, 32)`` + * - Styled + - [ w0 ]\ :sub:`32` || ``0x04`` || [ x\ :sub:`L` ]\ :sub:`32` || [ y\ :sub:`L` ]\ :sub:`32` + * - ``:math:`` + - :math:`[w0]_{32}\ ||\ \texttt{0x04}\ ||\ [x_L]_{32}\ ||\ [y_L]_{32}` Changes and additions to the Programming API -------------------------------------------- @@ -61,6 +165,146 @@ Changes and additions to the Programming API * These definitions must be embedded in, or included by, psa/crypto.h */ +.. _pake-keys: + +SPAKE2+ keys +~~~~~~~~~~~~ + +The SPAKE2+ protocol consists of three phases: + +1. Registration +2. Authenticated key exchange +3. Key confirmation + +The registration phase can be carried out immediately prior to the other phases, or can be carried out offline, and the result of the registration phase transferred to the participants in the protocol for later online authentication. + +The |API| uses an asymmetric key-pair, and public-key, to store the output of the registration, for input to the authentication protocol. The registration is carried out using a key derivation operation, and the key exchange and confirmation is carried out using a PAKE operation. For a SPAKE2+ PAKE operation, the prover, or client, role requires a SPAKE2+ key-pair, while the verifier, or server, role can use either a SPAKE2+ key-pair or SPAKE2+ public key. + +The SPAKE2+ algorithms are based on Elliptic curve groups, and a SPAKE2+ key is parameterized by a specific Elliptic curve. The Elliptic curve families are used to parameterize the key type, and the key size selects the specific curve. :issue:`Is this overkill? - RFC9383 only specifies cipher-suites that use the SECP R1 curves and the Edwards curves, we could have a custom set of families` + +.. macro:: PSA_KEY_TYPE_SPAKE2P_KEY_PAIR + :definition: /* specification-defined value */ + + .. summary:: + SPAKE2+ key pair: both the prover and verifier key. + + The size of a SPAKE2+ key is the size associated with the Elliptic curve group, that is, ceil(log2(q)) for a curve over a field F\ :sub:`q`. See the documentation of each Elliptic curve family for details. + + .. param:: curve + A value of type :code:`psa_ecc_family_t` that identifies the Elliptic curve family to be used. + + .. subsection:: Compatible algorithms + + | `PSA_ALG_SPAKE2P_HMAC` + | `PSA_ALG_SPAKE2P_CMAC` + | `PSA_ALG_SPAKE2P_MATTER` + +.. macro:: PSA_KEY_TYPE_SPAKE2P_PUBLIC_KEY + :definition: /* specification-defined value */ + + .. summary:: + SPAKE2+ public key: the verifier key. + + .. param:: curve + A value of type :code:`psa_ecc_family_t` that identifies the Elliptic curve family to be used. + + The size of an SPAKE2+ public key is the same as the corresponding private key. See `PSA_KEY_TYPE_SPAKE2P_KEY_PAIR()` and the documentation of each Elliptic curve family for details. + + .. subsection:: Compatible algorithms + + | `PSA_ALG_SPAKE2P_HMAC` (verification only) + | `PSA_ALG_SPAKE2P_CMAC` (verification only) + | `PSA_ALG_SPAKE2P_MATTER` (verification only) + +.. macro:: PSA_KEY_TYPE_IS_SPAKE2P + :definition: /* specification-defined value */ + + .. summary:: + Whether a key type is a SPAKE2+ key, either a key pair or a public key. + + .. param:: type + A key type: a value of type :code:`psa_key_type_t`. + +.. macro:: PSA_KEY_TYPE_IS_SPAKE2P_KEY_PAIR + :definition: /* specification-defined value */ + + .. summary:: + Whether a key type is a SPAKE2+ key pair. + + .. param:: type + A key type: a value of type :code:`psa_key_type_t`. + +.. macro:: PSA_KEY_TYPE_IS_SPAKE2P_PUBLIC_KEY + :definition: /* specification-defined value */ + + .. summary:: + Whether a key type is a SPAKE2+ public key. + + .. param:: type + A key type: a value of type :code:`psa_key_type_t`. + +.. macro:: PSA_KEY_TYPE_SPAKE2P_GET_FAMILY + :definition: /* specification-defined value */ + + .. summary:: + Extract the curve family from a SPAKE2+ key type. + + .. param:: type + A SPAKE2+ key type: a value of type :code:`psa_key_type_t` such that :code:`PSA_KEY_TYPE_IS_SPAKE2P(type)` is true. + + .. return:: psa_ecc_family_t + The elliptic curve family id, if ``type`` is a supported SPAKE2+ key. Unspecified if ``type`` is not a supported SPAKE2+ key. + +.. _spake2p-key-derivation: + +Derivation of SPAKE2+ keys +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The SPAKE2+ key types can be output from a key derivation using :code:`psa_key_derivation_output_key()`. The SPAKE2+ protocol recommends that a key-stretching kdf, such as PBKDF2, is used to hash the SPAKE2+ password. See RFC 9383 for details. + +For example, after setting up the PBKDF2 operation, the following process will derive the SPAKE2+ key pair for use with the P-256 Elliptic curve group :issue:`(This example may be more than necessary in the specification?)`: + +1. Allocate and initialize a key attributes object: + + .. code-block:: xref + + psa_key_attributes_t att = PSA_KEY_ATTRIBUTES_INIT; + +#. Set the key type and size: + + .. code-block:: xref + + psa_set_key_type(&att, PSA_KEY_TYPE_SPAKE2P_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_bits(&att, 256); // for P-256 + +#. Set the key policy: + + .. code-block:: xref + + psa_set_key_usage_flags(&att, PSA_KEY_USAGE_????); + psa_set_key_algorithm(&att, PSA_ALG_SPAKE2P); + + .. todo:: + Do we need a new usage flag for augmented PAKEs? For example PSA_KEY_USAGE_PROVE/VERIFY. Or do we just use PSA_KEY_USAGE_DERIVE as specified by psa_pake_set_password_key()?` + +#. Derive the key: + + .. code-block:: xref + + psa_key_id_t sp2_key; + psa_key_derivation_output_key(&att, &kdf_op, &sp2_key); + +The key derivation process in :code:`psa_key_derivation_output_key()` follows the recommendations for the registration process in RFC 9383, and matches the specification of this process in the Matter specification. + +For the |API|: + +* The derivation of SPAKE2+ keys extracts ceil(log2(p)/8) + 8 bytes from the PBKDF for each of w0s and w1s, where p is the prime factor of the order of the elliptic curve group. +* The calculation of w0, w1, and L then proceeds as described in the RFC. +* A SPAKE2+ key-pair is the pair (w0, w1). +* A SPAKE2+ public key is the pair (w0, L). + +.. todo:: + Would a table of required w0s/w1s lengths for each of the supported SPAKE2+ elliptic curve groups be useful here? .. _pake-algorithms: @@ -81,16 +325,27 @@ PAKE algorithms This macro can return either ``0`` or ``1`` if ``alg`` is not a supported algorithm identifier. .. macro:: PSA_ALG_JPAKE - :definition: ((psa_algorithm_t)0x0a000100) + :definition: /* specification-defined value */ .. summary:: - The Password-authenticated key exchange by juggling (J-PAKE) algorithm. + Macro to build the Password-authenticated key exchange by juggling (J-PAKE) algorithm. + + .. param:: hash_alg + A hash algorithm: a value of type :code:`psa_algorithm_t` such that :code:`PSA_ALG_IS_HASH(hash_alg)` is true. + + .. return:: + A J-PAKE algorithm, parameterized by a specific hash. + + Unspecified if ``hash_alg`` is not a supported hash algorithm. + This is J-PAKE as defined by :RFC-title:`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-title:`8235`, using the same group as the J-PAKE algorithm. - * A cryptographic hash function. + * Schnorr Non-Interactive Zero-Knowledge Proof (NIZKP) as defined by :RFC-title:`8235`, using the same group as the J-PAKE algorithm. + * A cryptographic hash function, ``hash_alg``. + + J-PAKE does not confirm the shared secret key that results from the key exchange. To select these parameters and set up the cipher suite, initialize a `psa_pake_cipher_suite_t` object, and call the following functions in any order: @@ -98,30 +353,40 @@ PAKE algorithms psa_pake_cipher_suite_t cipher_suite = PSA_PAKE_CIPHER_SUITE_INIT; - psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_JPAKE); - psa_pake_cs_set_primitive(cipher_suite, + psa_pake_cs_set_algorithm(&cipher_suite, PSA_ALG_JPAKE(hash)); + psa_pake_cs_set_primitive(&cipher_suite, PSA_PAKE_PRIMITIVE(type, family, bits)); - psa_pake_cs_set_hash(cipher_suite, hash); + psa_pake_cs_set_key_confirmation(&cipher_suite, PSA_PAKE_UNCONFIRMED_KEY); More information on selecting a specific Elliptic curve or Diffie-Hellman field is provided with the `PSA_PAKE_PRIMITIVE_TYPE_ECC` and `PSA_PAKE_PRIMITIVE_TYPE_DH` constants. + The PAKE operation for J-PAKE requires a key of type type :code:`PSA_KEY_TYPE_PASSWORD` or :code:`PSA_KEY_TYPE_PASSWORD_HASH`. + The same key value must be provided to the PAKE operation in both participants. + + The key can be the password text itself, in an agreed character encoding, or some value derived from the password as required by a higher level protocol. + For low-entropy passwords, it is recommended that a key-stretching derivation algorithm, such as PBKDF2, is used, and the resulting password hash is used as the PAKE operation key. + The J-PAKE operation follows the protocol shown in :numref:`fig-jpake`. .. figure:: /figure/j-pake.* :name: fig-jpake - The J-PAKE protocol. + The J-PAKE protocol The variable names *x1*, *g1*, and so on, are taken from the finite field implementation of J-PAKE in :RFC:`8236#2`. Details of the computation for the key shares and zero-knowledge proofs are in :RFC:`8236` and :RFC:`8235`. J-PAKE does not assign roles to the participants, so it is not necessary to call `psa_pake_set_role()`. - J-PAKE requires both an application and a peer identity. If the peer identity provided to `psa_pake_set_peer()` does not match the data received from the peer, then the call to `psa_pake_input()` for the `PSA_PAKE_STEP_ZK_PROOF` step will fail with :code:`PSA_ERROR_INVALID_SIGNATURE`. + J-PAKE requires both an application and a peer identity. + If the peer identity provided to `psa_pake_set_peer()` does not match the data received from the peer, then the call to `psa_pake_input()` for the `PSA_PAKE_STEP_ZK_PROOF` step will fail with :code:`PSA_ERROR_INVALID_SIGNATURE`. + + The shared secret that is produced by J-PAKE is not suitable for use as an encryption key. + It must be used as an input to a key derivation operation to produce additional cryptographic keys. The following steps demonstrate the application code for 'User' in :numref:`fig-jpake`. The input and output steps must be carried out in exactly the same sequence as shown. - 1. To prepare a J-Pake operation, initialize and set up a :code:`psa_pake_operation_t` object by calling the following functions: + 1. To prepare a J-PAKE operation, initialize and set up a :code:`psa_pake_operation_t` object by calling the following functions: .. code-block:: xref @@ -196,18 +461,19 @@ PAKE algorithms // Set r6, the ZKP proof for x4*s psa_pake_input(&jpake, PSA_PAKE_STEP_ZK_PROOF, ...); - #. To use the shared secret, set up a key derivation operation and transfer the computed value: + #. To use the shared secret, extract it as a key-derivation key. For example, to extract a derivation key for HKDF-SHA-256: .. code-block:: xref - // Set up the KDF - psa_key_derivation_operation_t kdf = PSA_KEY_DERIVATION_OPERATION_INIT; - psa_key_derivation_setup(&kdf, ...); - psa_key_derivation_input_bytes(&kdf, PSA_KEY_DERIVATION_INPUT_CONTEXT, ...); - psa_key_derivation_input_bytes(&kdf, PSA_KEY_DERIVATION_INPUT_LABEL, ...); + // Set up the key attributes + psa_key_attributes_t att = PSA_KEY_ATTRIBUTES_INIT; + psa_key_set_type(&att, PSA_KEY_TYPE_DERIVE); + psa_key_set_usage_flags(&att, PSA_KEY_USAGE_DERIVE); + psa_key_set_algorithm(&att, PSA_ALG_HKDF(PSA_ALG_SHA256)); // Get Ka=Kb=K - psa_pake_get_implicit_key(&jpake, &kdf) + psa_key_id_t shared_key; + psa_pake_get_shared_key(&jpake, &att, &shared_key); For more information about the format of the values which are passed for each step, see :secref:`pake-steps`. @@ -228,6 +494,325 @@ PAKE algorithms | :code:`PSA_KEY_TYPE_PASSWORD` | :code:`PSA_KEY_TYPE_PASSWORD_HASH` +.. macro:: PSA_ALG_SPAKE2P_HMAC + :definition: /* specification-defined value */ + + .. summary:: + Macro to build the SPAKE2+ algorithm, using HMAC-based key confirmation. + + .. param:: hash_alg + A hash algorithm: a value of type :code:`psa_algorithm_t` such that :code:`PSA_ALG_IS_HASH(hash_alg)` is true. + + .. return:: + A SPAKE2+ algorithm, using HMAC for key confirmation, parameterized by a specific hash. + + Unspecified if ``hash_alg`` is not a supported hash algorithm. + + This is SPAKE2+, as defined by :RFC-title:`9383`, instantiated with the following parameters: + + * An elliptic curve group. + * A cryptographic hash function, ``hash_alg``. + * Key derivation function HKDF, using the same hash function, ``hash_alg``. + * Keyed MAC function HMAC, using the same hash function, ``hash_alg``. + + For SPAKE2+, valid combinations of elliptic curve PAKE primitives and hash algorithms are described in :rfc:`9383#4`. + + SPAKE2+ includes confirmation of the shared secret key that results from the key exchange. + + To select these parameters and set up the cipher suite, initialize a `psa_pake_cipher_suite_t` object, and call the following functions in any order: + + .. code-block:: xref + + psa_pake_cipher_suite_t cipher_suite = PSA_PAKE_CIPHER_SUITE_INIT; + + psa_pake_cs_set_algorithm(&cipher_suite, PSA_ALG_SPAKE2P_HMAC(hash)); + psa_pake_cs_set_primitive(&cipher_suite, + PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, family, bits)); + + For more information on selecting a specific Elliptic curve, see `PSA_PAKE_PRIMITIVE_TYPE_ECC`. + + .. _spake2p-flow: + + .. subsection:: SPAKE2+ protocol + + There are two particpants in the SPAKE2+ protocol: + + * The *Prover* takes the role of client. It uses the protocol to prove that it knows the secret password, and produce a shared secret. + * The *Verifier* takes the role of server. It uses the protocol to verify the client's proof, and produce a shared secret. + + The PAKE operation for SPAKE2+ only accepts a SPAKE2+ key type: + + * The Prover requires a `PSA_KEY_TYPE_SPAKE2P_KEY_PAIR()`, on the same elliptic curve specified in the PAKE cipher suite. + * The Verifier requires either a `PSA_KEY_TYPE_SPAKE2P_PUBLIC_KEY()`, or a `PSA_KEY_TYPE_SPAKE2P_KEY_PAIR()`, on the same elliptic curve specified in the PAKE cipher suite. + + These keys are derived from the initial SPAKE2+ password prior to starting the PAKE operation. + It is recommended to use a key-stretching derivation algorithm, for example PBKDF2. + This process can take place immediately before the PAKE operation, or derived at some earlier point and persisted in the key store. + Alternatively, the Verifier can be provisioned with the `PSA_KEY_TYPE_SPAKE2P_PUBLIC_KEY()` for the protocol, by the Prover, or some other agent. + :numref:`fig-spake2p-reg` illustrates some example SPAKE2+ key derivation flows. + + It is recommended that the Verifier stores only the public key, because disclosure of the public key does not enable an attacker to impersonate the Prover. + + .. figure:: /figure/spake2plus-reg.* + :name: fig-spake2p-reg + + Examples of SPAKE2+ key derivation procedures + + The variable names *w0*, *w1*, *L* are taken from the description of SPAKE2+ in :RFC:`9383`. + + Details of the computation for the key derivation values are in :RFC:`9383#3.2`. + + Both participants in SPAKE2+ have an optional identity. + If no identity value is provided, then a zero-length string is used for that identity in the protocol. + If the participants do not supply the same identity values to the protocol, the computed secrets will be different, and key confirmation will fail. + + The SPAKE2+ operation follows the protocol shown in :numref:`fig-spake2p`. + + .. figure:: /figure/spake2plus.* + :name: fig-spake2p + + The SPAKE2+ authentication and key confirmation protocol + + The variable names *w0*, *w1*, *L*, and so on, are taken from the description of SPAKE2+ in :RFC:`9383`. + + Details of the computation for the key shares is in :RFC:`9383#3.3` and confirmation values in :RFC:`9383#3.4`. + + The shared secret that is produced by SPAKE2+ is pseudorandom. + Although it can be used directly as an encryption key, it is recommended to use the shared secret as an input to a key derivation operation to produce additional cryptographic keys. + + The following steps demonstrate the application code for both 'Prover' and 'Verifier' in :numref:`fig-spake2p`. + + **Prover** + To prepare a SPAKE2+ operation for the Prover, initialize and set up a :code:`psa_pake_operation_t` object by calling the following functions: + + .. code-block:: xref + + psa_pake_operation_t spake2p_p = PSA_PAKE_OPERATION_INIT; + + psa_pake_setup(&spake2p_p, pake_key_p, &cipher_suite); + psa_pake_set_role(&spake2p_p, PSA_PAKE_ROLE_CLIENT); + + The key ``pake_key_p`` is a SPAKE2+ key pair, `PSA_KEY_TYPE_SPAKE2P_KEY_PAIR()`. + + The key must have the :code:`PSA_KEY_USAGE_??????` usage flag. + + **Prover** + Provide any additional, optional, parameters: + + .. code-block:: xref + + psa_pake_set_user(&spake2p_p, ...); // Prover identity + psa_pake_set_peer(&spake2p_p, ...); // Verifier identity + psa_pake_set_context(&spake2p_p, ...); + + **Verifier** + To prepare a SPAKE2+ operation for the Verifier, initialize and set up a :code:`psa_pake_operation_t` object by calling the following functions: + + .. code-block:: xref + + psa_pake_operation_t spake2p_v = PSA_PAKE_OPERATION_INIT; + + psa_pake_setup(&spake2p_v, pake_key_v, &cipher_suite); + psa_pake_set_role(&spake2p_v, PSA_PAKE_ROLE_SERVER); + + The key ``pake_key_v`` is a SPAKE2+ key pair, `PSA_KEY_TYPE_SPAKE2P_KEY_PAIR()`, or public key, `PSA_KEY_TYPE_SPAKE2P_PUBLIC_KEY()`. + + The key must have the :code:`PSA_KEY_USAGE_??????` usage flag. + + **Verifier** + Provide any additional, optional, parameters: + + .. code-block:: xref + + psa_pake_set_user(&spake2p_v, ...); // Verifier identity + psa_pake_set_peer(&spake2p_v, ...); // Prover identity + psa_pake_set_context(&spake2p_v, ...); + + After setup, the key exchange flow for SPAKE2+ is as follows: + + **Prover** + To get the key share to send to the Verifier, call: + + .. code-block:: xref + + // Get shareP + psa_pake_output(&spake2p_p, PSA_PAKE_STEP_KEY_SHARE, ...); + + **Verifier** + To provide and validate the Prover key share, call: + + .. code-block:: xref + + // Set shareP + psa_pake_input(&spake2p_v, PSA_PAKE_STEP_KEY_SHARE, ...); + + **Verifier** + To get the Verifier key share and confirmation value to send to the Prover, call: + + .. code-block:: xref + + // Get shareV + psa_pake_output(&spake2p_v, PSA_PAKE_STEP_KEY_SHARE, ...); + // Get confirmV + psa_pake_output(&spake2p_v, PSA_PAKE_STEP_CONFIRM, ...); + + **Prover** + To provide and validate the Verifier key share, and confirm the Verifier key, call: + + .. code-block:: xref + + // Set shareV + psa_pake_input(&spake2p_p, PSA_PAKE_STEP_KEY_SHARE, ...); + // Set confirmV + psa_pake_input(&spake2p_p, PSA_PAKE_STEP_KEY_CONFIRM, ...); + + **Prover** + To get the Prover key confirmation value to send to the Verifier, call: + + .. code-block:: xref + + // Get confirmV + psa_pake_output(&spake2p_p, PSA_PAKE_STEP_CONFIRM, ...); + + **Verifier** + To confirm the Prover key, call: + + .. code-block:: xref + + // Set shareP + psa_pake_input(&spake2p_v, PSA_PAKE_STEP_CONFIRM, ...); + + **Prover** + To use the shared secret, extract it as a key-derivation key. + For example, to extract a derivation key for HKDF-SHA-256: + + .. code-block:: xref + + // Set up the key attributes + psa_key_attributes_t att = PSA_KEY_ATTRIBUTES_INIT; + psa_key_set_type(&att, PSA_KEY_TYPE_DERIVE); + psa_key_set_usage_flags(&att, PSA_KEY_USAGE_DERIVE); + psa_key_set_algorithm(&att, PSA_ALG_HKDF(PSA_ALG_SHA256)); + + // Get K_shared + psa_key_id_t shared_key; + psa_pake_get_shared_key(&spake2p_p, &att, &shared_key); + + **Verifier** + To use the shared secret, extract it as a key-derivation key. + The same key attributes can be used as the Prover: + + .. code-block:: xref + + // Get K_shared + psa_key_id_t shared_key; + psa_pake_get_shared_key(&spake2p_v, &att, &shared_key); + + For more information about the format of the values which are passed for each step, see :secref:`pake-steps`. + + If the validation of a key share fails, then the corresponding call to `psa_pake_input()` for the `PSA_PAKE_STEP_KEY_SHARE` step will return :code:`PSA_ERROR_INVALID_ARGUMENT`. + If the verification of a key confirmation value fails, then the corresponding call to `psa_pake_input()` for the `PSA_PAKE_STEP_CONFIRM` step will return :code:`PSA_ERROR_INVALID_SIGNATURE`. + + .. subsection:: Compatible key types + + | :code:`PSA_KEY_TYPE_SPAKE2P_KEY_PAIR` + | :code:`PSA_KEY_TYPE_SPAKE2P_PUBLIC_KEY` (verification only) + + +.. macro:: PSA_ALG_SPAKE2P_CMAC + :definition: /* specification-defined value */ + + .. summary:: + Macro to build the SPAKE2+ algorithm, using CMAC-based key confirmation. + + .. param:: hash_alg + A hash algorithm: a value of type :code:`psa_algorithm_t` such that :code:`PSA_ALG_IS_HASH(hash_alg)` is true. + + .. return:: + A SPAKE2+ algorithm, using CMAC for key confirmation, parameterized by a specific hash. + + Unspecified if ``hash_alg`` is not a supported hash algorithm. + + This is SPAKE2+, as defined by :RFC-title:`9383`, instantiated with the following parameters: + + * An elliptic curve group. + * A cryptographic hash function, ``hash_alg``. + * Key derivation function HKDF, using the same hash function, ``hash_alg``. + * Keyed MAC function CMAC-AES-128. + + For SPAKE2+, valid combinations of elliptic curve PAKE primitives and hash algorithms for use with CMAC-AES-128 are described in :rfc:`9383#4`. + + SPAKE2+ includes confirmation of the shared secret key that results from the key exchange. + + To select these parameters and set up the cipher suite, initialize a `psa_pake_cipher_suite_t` object, and call the following functions in any order: + + .. code-block:: xref + + psa_pake_cipher_suite_t cipher_suite = PSA_PAKE_CIPHER_SUITE_INIT; + + psa_pake_cs_set_algorithm(&cipher_suite, PSA_ALG_SPAKE2P_CMAC(hash)); + psa_pake_cs_set_primitive(&cipher_suite, + PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, family, bits)); + + For more information on selecting a specific Elliptic curve, see `PSA_PAKE_PRIMITIVE_TYPE_ECC`. + + The SPAKE2+ protocol flow and usage for `PSA_ALG_SPAKE2P_CMAC()` is the same as for `PSA_ALG_SPAKE2P_HMAC()`. See :secref:`spake2p-flow`. + + .. subsection:: Compatible key types + + | :code:`PSA_KEY_TYPE_SPAKE2P_KEY_PAIR` + | :code:`PSA_KEY_TYPE_SPAKE2P_PUBLIC_KEY` (verification only) + +.. macro:: PSA_ALG_SPAKE2P_MATTER + :definition: ((psa_algoirithm_t)0x0A000609) + + .. summary:: + The SPAKE2+ algorithm, as used by the Matter v1 specification. + + This is the PAKE algorithm specified as MATTER_PAKE in :cite-title:`MATTER`. This is based on draft-02 of the SPAKE2+ protocol, :cite-title:`SPAKE2P-2`. + + :cite:`MATTER` specifies a single cipher suite, as follows: + + * The NIST P-256 elliptic curve (secp256r1). + * The SHA256 hash function. + * Key derivation function HKDF-SHA256. + * Keyed MAC function HMAC-SHA256. + + SPAKE2+ includes confirmation of the shared secret key that results from the key exchange. + + To set up the cipher suite for `PSA_ALG_SPAKE2P_MATTER`, initialize a `psa_pake_cipher_suite_t` object, and call the following functions in any order: + + .. code-block:: xref + + psa_pake_cipher_suite_t cipher_suite = PSA_PAKE_CIPHER_SUITE_INIT; + + psa_pake_cs_set_algorithm(&cipher_suite, PSA_ALG_SPAKE2P_MATTER); + psa_pake_cs_set_primitive(&cipher_suite, + PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, + PSA_ECC_FAMILY_SECP_R1, 256)); + + This algorithm is compatible with the SPAKE2+ key types, key derivation, protocol flow, and the API usage described in :secref:`pake-keys` and :secref:`spake2p-flow`. However, the following aspects are different: + + * The key schedule is different. This affects the computation of the shared secret and key confirmation values. + * The protocol inputs and outputs have been renamed between draft-02 and the final RFC, as follows: + + .. csv-table:: + :header-rows: 1 + :widths: auto + :align: left + + RFC 9383, Draft-02 + shareP, pA + shareV, pB + confirmP, cA + confirmV, cB + K_shared, Ke + + .. subsection:: Compatible key types + + | :code:`PSA_KEY_TYPE_SPAKE2P_KEY_PAIR` + | :code:`PSA_KEY_TYPE_SPAKE2P_PUBLIC_KEY` (verification only) + .. _pake-primitive: @@ -342,9 +927,13 @@ A PAKE primitive is required when constructing a PAKE cipher-suite object, `psa_ PAKE cipher suites ~~~~~~~~~~~~~~~~~~ -A PAKE algorithm uses a specific cryptographic primitive for key establishment, specified using a `PAKE primitive `. PAKE algorithms also require a cryptographic hash algorithm, which is agreed between the participants. +Most PAKE algorithms have parameters that must be specified by the application. These parameters include the following: + +* The cryptographic primitive used for key establishment, specified using a `PAKE primitive `. +* A cryptographic hash algorithm. +* Whether the application requires the shared secret before, or after, it is confirmed. -The `psa_pake_cipher_suite_t` object is used to fully specify a PAKE operation, combining the PAKE algorithm, the PAKE primitive, the hash or any other algorithm that parametrises the PAKE in question. +The hash algorithm is encoded into the PAKE algorithm identifier. The `psa_pake_cipher_suite_t` object is used to fully specify a PAKE operation, combining the PAKE algorithm with all of the above parameters. A PAKE cipher suite is required when setting up a PAKE operation in `psa_pake_setup()`. @@ -357,13 +946,9 @@ A PAKE cipher suite is required when setting up a PAKE operation in `psa_pake_se This is the object that represents the cipher suite used for a PAKE algorithm. The PAKE cipher suite specifies the PAKE algorithm, and the options selected for that algorithm. The cipher suite includes the following attributes: * The PAKE algorithm itself. + * The hash algorithm, encoded within the PAKE algorithm. * The PAKE primitive, which identifies the prime order group used for the key exchange operation. See :secref:`pake-primitive`. - * The hash algorithm to use in the operation. - - .. note:: - Implementations are recommended to define the cipher-suite object as a simple data structure, with fields corresponding to the individual cipher suite attributes. In such an implementation, each function ``psa_pake_cs_set_xxx()`` sets a field and the corresponding function ``psa_pake_cs_get_xxx()`` retrieves the value of the field. - - An implementations can report attribute values that are equivalent to the original one, but have a different encoding. For example, an implementation can use a more compact representation for attributes where many bit-patterns are invalid or not supported, and store all values that it does not support as a special marker value. In such an implementation, after setting an invalid value, the corresponding get function returns an invalid value which might not be the one that was originally stored. + * Whether to confirm the shared secret. This is an implementation-defined type. Applications that make assumptions about the content of this object will result in implementation-specific behavior, and are non-portable. @@ -395,25 +980,35 @@ A PAKE cipher suite is required when setting up a PAKE operation in `psa_pake_se psa_pake_cipher_suite_t cipher_suite; cipher_suite = psa_pake_cipher_suite_init(); - .. Do we need anything like the following? + Following initialization, the cipher-suite object contains the following values: + + .. list-table:: + :header-rows: 1 + :widths: 1 4 + :align: left - .. rubric:: Usage + * - Attribute + - Value - A typical sequence to create a key is as follows: + * - algorithm + - :code:`PSA_ALG_NONE` --- an invalid algorithm identifier. + * - primitive + - ``0`` --- an invalid PAKE primitive. + * - hash + - :code:`PSA_ALG_NONE` --- an invalid algorithm identifier. + * - key confirmation + - `PSA_PAKE_CONFIRMED_KEY` --- requesting that the secret key is confirmed before it can be returned. - 1. Create and initialize an attribute object. - #. If the key is persistent, call `psa_set_key_id()`. Also call `psa_set_key_lifetime()` to place the key in a non-default location. - #. Set the key policy with `psa_set_key_usage_flags()` and `psa_set_key_algorithm()`. - #. Set the key type with `psa_set_key_type()`. Skip this step if copying an existing key with `psa_copy_key()`. - #. When generating a random key with `psa_generate_key()` or deriving a key with `psa_key_derivation_output_key()`, set the desired key size with `psa_set_key_bits()`. - #. Call a key creation function: `psa_import_key()`, `psa_generate_key()`, `psa_key_derivation_output_key()` or `psa_copy_key()`. This function reads the attribute object, creates a key with these attributes, and outputs an identifier for the newly created key. - #. Optionally call `psa_reset_key_attributes()`, now that the attribute object is no longer needed. Currently this call is not required as the attributes defined in this specification do not require additional resources beyond the object itself. + The algorithm and primitive values must be set for all PAKE algorithms, the hash and key confirmation values are required for some PAKE algorithms. - A typical sequence to query a key's attributes is as follows: + .. admonition:: Implementation note + + Implementations are recommended to define the cipher-suite object as a simple data structure, with fields corresponding to the individual cipher suite attributes. + In such an implementation, each function ``psa_pake_cs_set_xxx()`` sets a field and the corresponding function ``psa_pake_cs_get_xxx()`` retrieves the value of the field. - 1. Call `psa_get_key_attributes()`. - #. Call ``psa_get_key_xxx()`` functions to retrieve the required attribute(s). - #. Call `psa_reset_key_attributes()` to free any resources that can be used by the attribute object. + An implementations can report attribute values that are equivalent to the original one, but have a different encoding. + For example, an implementation can use a more compact representation for attributes where many bit-patterns are invalid or not supported, and store all values that it does not support as a special marker value. + In such an implementation, after setting an invalid value, the corresponding get function returns an invalid value which might not be the one that was originally stored. .. macro:: PSA_PAKE_CIPHER_SUITE_INIT :definition: /* implementation-defined value */ @@ -495,43 +1090,64 @@ A PAKE cipher suite is required when setting up a PAKE operation in `psa_pake_se This is a simple accessor function that is not required to validate its inputs. It can be efficiently implemented as a ``static inline`` function or a function-like macro. -.. function:: psa_pake_cs_get_hash +.. macro:: PSA_PAKE_CONFIRMED_KEY + :definition: 0 + + .. summary:: A key confirmation value that indicates an confirmed key in a PAKE cipher suite. + + This key confirmation value will result in the PAKE algorithm exchanging data to verify that the shared key is identical for both parties. This is the default key confirmation value in an initialized PAKE cipher suite object. + + Some algorithms do not include confirmation of the shared key. + +.. macro:: PSA_PAKE_UNCONFIRMED_KEY + :definition: 1 + + .. summary:: A key confirmation value that indicates an unconfirmed key in a PAKE cipher suite. + + This key confirmation value will result in the PAKE algorithm terminating prior to confirming that the resulting shared key is identical for both parties. + + Some algorithms do not support returning an unconfirmed shared key. + + .. warning:: + + When the shared key is not confirmed as part of the PAKE operation, the application is responsible for mitigating risks that arise from the possible mismatch in the output keys. + +.. function:: psa_pake_cs_get_key_confirmation .. summary:: - Retrieve the hash algorithm from a PAKE cipher suite. + Retrieve the key confirmation from a PAKE cipher suite. .. param:: const psa_pake_cipher_suite_t* cipher_suite The cipher suite object to query. - .. return:: psa_pake_primitive_t - The hash algorithm stored in the cipher suite object. - The return value is :code:`PSA_ALG_NONE` if the PAKE is not parametrized by a hash algorithm, or if the hash algorithm is not set. + .. return:: uint32_t + A key confirmation value: either `PSA_PAKE_CONFIRMED_KEY` or `PSA_PAKE_UNCONFIRMED_KEY`. .. admonition:: Implementation note - This is a simple accessor function that is not required to validate its inputs. It can be efficiently implemented as a ``static inline`` function or a function-like macro. + This is a simple accessor function that is not required to validate its inputs. + It can be efficiently implemented as a ``static inline`` function or a function-like macro. -.. function:: psa_pake_cs_set_hash +.. function:: psa_pake_cs_set_key_confirmation .. summary:: - Declare the hash algorithm for a PAKE cipher suite. + Declare the key confirmation from a PAKE cipher suite. .. param:: psa_pake_cipher_suite_t* cipher_suite The cipher suite object to write to. - .. param:: psa_algorithm_t hash_alg - The hash algorithm to write: a value of type :code:`psa_algorithm_t` such that :code:`PSA_ALG_IS_HASH(hash_alg)` is true. - If this is :code:`PSA_ALG_NONE`, the hash algorithm in ``cipher_suite`` becomes unspecified. + .. param:: uint32_t key_confirmation + The key confirmation value to write: either `PSA_PAKE_CONFIRMED_KEY` or `PSA_PAKE_UNCONFIRMED_KEY`. .. return:: void - This function overwrites any hash algorithm previously set in ``cipher_suite``. + This function overwrites any key confirmation previously set in ``cipher_suite``. - The documentation of individual PAKE algorithms specifies which hash algorithms are compatible, or if no hash algorithm is required. + The documentation of individual PAKE algorithms specifies which key confirmation values are valid for the algorithm. .. admonition:: Implementation note - This is a simple accessor function that is not required to validate its inputs. It can be efficiently implemented as a ``static inline`` function or a function-like macro. - + This is a simple accessor function that is not required to validate its inputs. + It can be efficiently implemented as a ``static inline`` function or a function-like macro. .. _pake-roles: @@ -651,6 +1267,15 @@ PAKE step types For information regarding how the group is determined, consult the documentation `PSA_PAKE_PRIMITIVE()`. +.. macro:: PSA_PAKE_STEP_CONFIRM + :definition: ((psa_pake_step_t)0x04) + + .. summary:: + The key confirmation value. + + This value is used during the key confirmation phase of a PAKE protocol. The format of the value depends on the algorithm and cipher suite: + + * For :code:`PSA_ALG_SPAKE2P`, the format for both input and output at this step is the same as the output of the MAC algorithm specified in the cipher suite. .. _pake-operation: @@ -716,8 +1341,11 @@ Multi-part PAKE operations .. param:: psa_key_id_t password_key Identifier of the key holding the password or a value derived from the password. It must remain valid until the operation terminates. - It must be of type :code:`PSA_KEY_TYPE_PASSWORD` or :code:`PSA_KEY_TYPE_PASSWORD_HASH`. - It must permit the usage :code:`PSA_KEY_USAGE_DERIVE`. + + The valid key types depend on the PAKE algorithm, and participant role. + Refer to the documentation of individual PAKE algorithms for more information, see :secref:`pake-algorithms`. + + The key must permit the usage :code:`PSA_KEY_USAGE_DERIVE`. :issue:`Is this still the appropriate usage flag for SPAKE2+ key-pairs and public keys?` .. param:: const psa_pake_cipher_suite_t *cipher_suite The cipher suite to use. A PAKE cipher suite fully characterizes a PAKE algorithm, including the PAKE algorithm. @@ -739,17 +1367,17 @@ Multi-part PAKE operations .. retval:: PSA_ERROR_INVALID_ARGUMENT The following conditions can result in this error: - * The algorithm in ``cipher_suite`` is not a PAKE algorithm. + * The algorithm in ``cipher_suite`` is not a PAKE algorithm, or encodes an invalid hash algorithm. * The PAKE primitive in ``cipher_suite`` is not compatible with the PAKE algorithm. - * The hash algorithm in ``cipher_suite`` is invalid, or not compatible with the PAKE algorithm and primitive. + * The key confirmation value in ``cipher_suite`` is not compatible with the PAKE algorithm and primitive. * The key type for ``password_key`` is not :code:`PSA_KEY_TYPE_PASSWORD` or :code:`PSA_KEY_TYPE_PASSWORD_HASH`. * ``password_key`` is not compatible with ``cipher_suite``. .. retval:: PSA_ERROR_NOT_SUPPORTED The following conditions can result in this error: - * The algorithm in ``cipher_suite`` is not a supported PAKE algorithm. + * The algorithm in ``cipher_suite`` is not a supported PAKE algorithm, or encodes an unsupported hash algorithm.. * The PAKE primitive in ``cipher_suite`` is not supported or not compatible with the PAKE algorithm. - * The hash algorithm in ``cipher_suite`` is not supported, or not compatible with the PAKE algorithm and primitive. + * The key confirmation value in ``cipher_suite`` is not supported, or not compatible, with the PAKE algorithm and primitive. * The key type or key size of ``password_key`` is not supported with ``cipher suite``. .. retval:: PSA_ERROR_CORRUPTION_DETECTED .. retval:: PSA_ERROR_COMMUNICATION_FAILURE @@ -771,14 +1399,14 @@ Multi-part PAKE operations 1. Call :code:`psa_pake_output(operation, PSA_PAKE_STEP_KEY_SHARE, ...)` to get the key share that needs to be sent to the peer. #. Call :code:`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()` to access the shared secret. + #. Call `psa_pake_get_shared_key()` to access the shared secret. Refer to the documentation of individual PAKE algorithms for details on the required set up and operation for each algorithm, and for constraints on the format and content of valid passwords. See :secref:`pake-algorithms`. After a successful call to `psa_pake_setup()`, the operation is active, and the application must eventually terminate the operation. The following events terminate an operation: - * A successful call to `psa_pake_get_implicit_key()`. + * A successful call to `psa_pake_get_shared_key()`. * A call to `psa_pake_abort()`. If `psa_pake_setup()` returns an error, the operation object is unchanged. If a subsequent function call with an active operation returns an error, the operation enters an error state. @@ -786,7 +1414,7 @@ Multi-part PAKE operations To abandon an active operation, or reset an operation in an error state, call `psa_pake_abort()`. .. - See :secref:`multi-part-operations`. + See :secref:`multi-part-operations`. :issue:`add this when integrated to main specification` .. function:: psa_pake_set_role @@ -894,6 +1522,41 @@ Multi-part PAKE operations Refer to the documentation of individual PAKE algorithms for more information. See :secref:`pake-algorithms`. +.. function:: psa_pake_set_context + + .. summary:: + Set the context data for a password-authenticated key exchange. + + .. param:: psa_pake_operation_t *operation + Active PAKE operation. + .. param:: const uint8_t *context + The peer's ID to authenticate. + .. param:: size_t context_len + Size of the ``context`` buffer in bytes. + + .. return:: psa_status_t + .. retval:: PSA_SUCCESS + Success. + .. retval:: PSA_ERROR_BAD_STATE + The following conditions can result in this error: + + * The operation state is not valid: it must be active, and `psa_pake_input()`, and `psa_pake_output()` must not have been called yet. + * Calling `psa_pake_set_context()` is invalid with the operation's algorithm. + * The library requires initializing by a call to :code:`psa_crypto_init()`. + .. retval:: PSA_ERROR_INVALID_ARGUMENT + ``context`` is not valid for the operation's algorithm and cipher suite. + .. retval:: PSA_ERROR_NOT_SUPPORTED + The value of ``context`` is not supported by the implementation. + .. retval:: PSA_ERROR_NOT_SUPPORTED + .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY + .. retval:: PSA_ERROR_COMMUNICATION_FAILURE + .. retval:: PSA_ERROR_CORRUPTION_DETECTED + + Call this function for PAKE algorithms that accept additional context data as part of the protocol setup. + + Refer to the documentation of individual PAKE algorithms for more information. + See :secref:`pake-algorithms`. + .. function:: psa_pake_output .. summary:: @@ -976,7 +1639,7 @@ Multi-part PAKE operations * ``step`` is not compatible with the operation's algorithm. * The input is not valid for the operation's algorithm, cipher suite or ``step``. .. retval:: PSA_ERROR_INVALID_SIGNATURE - The verification fails for a `PSA_PAKE_STEP_ZK_PROOF` input step. + The verification fails for a `PSA_PAKE_STEP_ZK_PROOF` or `PSA_PAKE_STEP_CONFIRM` input step. .. retval:: PSA_ERROR_NOT_SUPPORTED The following conditions can result in this error: @@ -999,30 +1662,71 @@ Multi-part PAKE operations If this function returns an error status, the operation enters an error state and must be aborted by calling `psa_pake_abort()`. -.. function:: psa_pake_get_implicit_key +.. function:: psa_pake_get_shared_key .. summary:: - Pass the implicitly confirmed shared secret from a PAKE into a key derivation operation. + Extract the shared secret from the PAKE as a key. .. param:: psa_pake_operation_t *operation Active PAKE operation. - .. param:: psa_key_derivation_operation_t *output - A key derivation operation that is ready for an input step of type :code:`PSA_KEY_DERIVATION_INPUT_SECRET`. + .. param:: const psa_key_attributes_t * attributes + The attributes for the new key. + This function uses the attributes as follows: + + * The key type is required. + All PAKE algorithms can output a key of type :code:`PSA_KEY_TYPE_DERIVE` or :code:`PSA_KEY_TYPE_HMAC`. + PAKE algorithms that produce a pseudo-random shared secret, can also output block-cipher key types, for example :code:`PSA_KEY_TYPE_AES`. + + Refer to the documentation of individual PAKE algorithms for more information. + See :secref:`pake-algorithms`. + * The key size in ``attributes`` must be zero. + The returned key size is always determined from the PAKE shared secret. + * The key permitted-algorithm policy is required for keys that will be used for a cryptographic operation. + + .. see :secref:`permitted-algorithms`. + + * The key usage flags define what operations are permitted with the key. + + .. see :secref:`key-usage-flags`. + + * The key lifetime and identifier are required for a persistent key. + + .. note:: + This is an input parameter: it is not updated with the final key attributes. + The final attributes of the new key can be queried by calling :code:`psa_get_key_attributes()` with the key's identifier. + .. param:: psa_key_id_t * key + On success, an identifier for the newly created key. :code:`PSA_KEY_ID_NULL` on failure. + .. return:: psa_status_t .. retval:: PSA_SUCCESS Success. - Use the ``output`` key derivation operation to continue with derivation of keys or data. + If the key is persistent, the key material and the key's metadata have been saved to persistent storage. .. retval:: PSA_ERROR_BAD_STATE The following conditions can result in this error: - * The state of PAKE operation ``operation`` is not valid: it must be active, with all setup, input, and output steps complete. - * The state of key derivation operation ``output`` is not valid for the :code:`PSA_KEY_DERIVATION_INPUT_SECRET` step. + * The state of PAKE operation ``operation`` is not valid: it must be ready to return the shared secret. + + For an unconfirmed key, this will be when the key-exchange output and input steps are complete, but prior to any key-confirmation output and input steps. + + For a confirmed key, this will be when all key-exchange and key-confirmation output and input steps are complete. * The library requires initializing by a call to :code:`psa_crypto_init()`. - .. retval:: PSA_ERROR_INVALID_ARGUMENT - :code:`PSA_KEY_DERIVATION_INPUT_SECRET` is not compatible with the algorithm in the ``output`` key derivation operation. + .. retval:: PSA_ERROR_ALREADY_EXISTS + This is an attempt to create a persistent key, and there is already a persistent key with the given identifier. .. retval:: PSA_ERROR_NOT_SUPPORTED - Input from a PAKE is not supported by the algorithm in the ``output`` key derivation operation. + The key attributes, as a whole, are not supported for creation from a PAKE secret, either by the implementation in general or in the specified storage location. + .. retval:: PSA_ERROR_INVALID_ARGUMENT + The following conditions can result in this error: + + * The key type is not valid for output from this operation's algorithm. + * The key size is nonzero. + * The key lifetime is invalid. + * The key identifier is not valid for the key lifetime. + * The key usage flags include invalid values. + * The key's permitted-usage algorithm is invalid. + * The key attributes, as a whole, are invalid. + .. retval:: PSA_ERROR_NOT_PERMITTED + The implementation does not permit creating a key with the specified attributes due to some implementation-specific policy. .. retval:: PSA_ERROR_INSUFFICIENT_MEMORY .. retval:: PSA_ERROR_COMMUNICATION_FAILURE .. retval:: PSA_ERROR_CORRUPTION_DETECTED @@ -1030,23 +1734,46 @@ Multi-part PAKE operations .. retval:: PSA_ERROR_DATA_CORRUPT .. retval:: PSA_ERROR_DATA_INVALID - At this step in the PAKE operation there is a cryptographic guarantee that only an authenticated participant who used the same password is able to compute the key. - But there is no guarantee that the peer is the participant it claims to be, and was able to compute the same key. + This is the final call in a PAKE operation, which retrieves the shared secret as a key. + It is recommended that this key is used as an input to a key derivation operation to produce additional cryptographic keys. + For some PAKE algorithms, the shared secret is also suitable for use as a key in cryptographic operations such as encryption. + Refer to the documentation of individual PAKE algorithms for more information, see :secref:`pake-algorithms`. + + Depending on the key confirmation requested in the cipher suite, `psa_pake_get_shared_key()` must be called either before or after the key-confirmation output and input steps for the PAKE algorithm. + The key confirmation affects the guarantees that can be made about the shared key: + + .. list-table:: + :class: borderless + :widths: 1 4 + + * - **Unconfirmed key** + - If the cipher suite used to set up the operation requested an unconfirmed key, the application must call `psa_pake_get_shared_key()` after the key-exchange output and input steps are completed. + The PAKE algorithm provides a cryptographic guarantee that only a peer who used the same password, and identity inputs, is able to compute the same key. + However, there is no guarantee that the peer is the participant it claims to be, and was able to compute the same key. - In this situation, the authentication is only implicit. - Since the peer is not authenticated, no action should be taken 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. + Since the peer is not authenticated, no action should be taken 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 injects the shared secret output of the PAKE into the provided key derivation operation. - The input step :code:`PSA_KEY_DERIVATION_INPUT_SECRET` is used to input the shared key material into the key derivation operation. + .. note:: + Some PAKE algorithms do not enable the output of the shared secret until it has been confirmed. + + * - **Confirmed key** + - If the cipher suite used to set up the operation requested a confirmed key, the application must call `psa_pake_get_shared_key()` after the key-exchange and key-confirmation output and input steps are completed. + + Following key confirmation, the PAKE algorithm provides a cryptographic guarantee that the peer used the same password and identity inputs, and has computed the identical shared secret key. + + Since the peer is not authenticated, no action should be taken 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. + + .. note:: + Some PAKE algorithms do not include any key-confirmation steps. 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 algorithms for more information. See :secref:`pake-algorithms`. When this function returns successfully, ``operation`` becomes inactive. - If this function returns an error status, both the ``operation`` and the ``key_derivation`` operations enter an error state and must be aborted by calling `psa_pake_abort()` and :code:`psa_key_derivation_abort()` respectively. + If this function returns an error status, the operation enters an error state and must be aborted by calling `psa_pake_abort()`. .. function:: psa_pake_abort @@ -1070,12 +1797,68 @@ Multi-part PAKE operations This function can be called any time after the operation object has been initialized as described in `psa_pake_operation_t`. - In particular, calling `psa_pake_abort()` after the operation has been terminated by a call to `psa_pake_abort()` or `psa_pake_get_implicit_key()` is safe and has no effect. + In particular, calling `psa_pake_abort()` after the operation has been terminated by a call to `psa_pake_abort()` or `psa_pake_get_shared_key()` is safe and has no effect. Support macros ~~~~~~~~~~~~~~ +.. macro:: PSA_ALG_IS_JPAKE + :definition: /* specification-defined value */ + + .. summary:: + Whether the specified algorithm is a J-PAKE algorithm. + + .. param:: alg + An algorithm identifier: a value of type :code:`psa_algorithm_t`. + + .. return:: + ``1`` if ``alg`` is a J-PAKE algorithm, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported PAKE algorithm identifier. + + J-PAKE algorithms are constructed using :code:`PSA_ALG_JPAKE(hash_alg)`. + +.. macro:: PSA_ALG_IS_SPAKE2P + :definition: /* specification-defined value */ + + .. summary:: + Whether the specified algorithm is a SPAKE2+ algorithm. + + .. param:: alg + An algorithm identifier: a value of type :code:`psa_algorithm_t`. + + .. return:: + ``1`` if ``alg`` is a SPAKE2+ algorithm, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported PAKE algorithm identifier. + + SPAKE2+ algorithms are constructed using :code:`PSA_ALG_SPAKE2P_HMAC(hash_alg)`, :code:`PSA_ALG_SPAKE2P_CMAC(hash_alg)`, or :code:`PSA_ALG_SPAKE2P_MATTER`. + +.. macro:: PSA_ALG_IS_SPAKE2P_HMAC + :definition: /* specification-defined value */ + + .. summary:: + Whether the specified algorithm is a SPAKE2+ algorithm that uses a HMAC-based key confirmation. + + .. param:: alg + An algorithm identifier: a value of type :code:`psa_algorithm_t`. + + .. return:: + ``1`` if ``alg`` is a SPAKE2+ algorithm that uses a HMAC-based key confirmation, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported PAKE algorithm identifier. + + SPAKE2+ algorithms, using HMAC-based key confirmation, are constructed using :code:`PSA_ALG_SPAKE2P_HMAC(hash_alg)`. + +.. macro:: PSA_ALG_IS_SPAKE2P_CMAC + :definition: /* specification-defined value */ + + .. summary:: + Whether the specified algorithm is a SPAKE2+ algorithm that uses a CMAC-based key confirmation. + + .. param:: alg + An algorithm identifier: a value of type :code:`psa_algorithm_t`. + + .. return:: + ``1`` if ``alg`` is a SPAKE2+ algorithm that uses a CMAC-based key confirmation, ``0`` otherwise. This macro can return either ``0`` or ``1`` if ``alg`` is not a supported PAKE algorithm identifier. + + SPAKE2+ algorithms, using CMAC-based key confirmation, are constructed using :code:`PSA_ALG_SPAKE2P_CMAC(hash_alg)`. + .. macro:: PSA_PAKE_OUTPUT_SIZE :definition: /* implementation-defined value */ @@ -1133,7 +1916,6 @@ Support macros See also `PSA_PAKE_INPUT_MAX_SIZE` - .. macro:: PSA_PAKE_INPUT_MAX_SIZE :definition: /* implementation-defined value */ diff --git a/doc/ext-pake/appendix/history.rst b/doc/ext-pake/appendix/history.rst index 8b22b27e..90cfad58 100644 --- a/doc/ext-pake/appendix/history.rst +++ b/doc/ext-pake/appendix/history.rst @@ -14,10 +14,36 @@ This section provides the detailed changes made between published version of the Changes between *Beta 1* and *Beta 2* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -API changes -~~~~~~~~~~~ +Changes to the API +~~~~~~~~~~~~~~~~~~ + +* Combined :code:`psa_pake_set_password_key()` with :code:`psa_pake_setup()`. This aligns the API better with other multi-part operations, and also enables an implementation to identify the key location when setting up the operation. This affects the following APIs: + + - Removed :code:`psa_pake_set_password_key()` + - Changed :code:`psa_pake_setup()`: it now takes an additional parameter + +* Replaced :code:`psa_pake_get_implicit_key()` with :code:`psa_pake_get_shared_key()`. This returns a new key containing the shared secret, instead of injecting the shared secret into a key derivation operation. +* Added a key confirmation attribute to the PAKE cipher suite. This indicates whether the application wants to extract the shared secret before, or after, key confirmation. See :secref:`pake-cipher-suite`. This adds the APIs `PSA_PAKE_CONFIRMED_KEY`, `PSA_PAKE_UNCONFIRMED_KEY`, `psa_pake_cs_set_key_confirmation()`, and `psa_pake_cs_get_key_confirmation()`. + +* Moved the hash algorithm parameter to the PAKE cipher suite into the PAKE algorithm identifier, instead of a separate attribute of the cipher suite. This also makes the hash algorithm value available to the `PSA_PAKE_OUTPUT_SIZE()` and `PSA_PAKE_INPUT_SIZE()` macros. This affects the following APIs: + + - Removed :code:`psa_pake_cs_get_hash()` and :code:`psa_pake_cs_set_hash()` + - Changed `PSA_ALG_JPAKE()`: it now requires a ``hash_alg`` parameter + - Added `PSA_ALG_IS_JPAKE()` + +* Add the `PSA_PAKE_STEP_CONFIRM` PAKE step for input and output of key confirmation values. +* Add `psa_pake_set_context()` to set context data for a PAKE operation. + +* Added asymmetric key types for SPAKE2+ registration, `PSA_KEY_TYPE_SPAKE2P_KEY_PAIR()` and `PSA_KEY_TYPE_SPAKE2P_PUBLIC_KEY()`. Documented the import/export public key format and key derivation process for these keys. + +* Added SPAKE2+ algorithms, supporting both :rfc-title:`9383` and :cite-title:`MATTER`. Added the following APIs: -* Combined :code:`psa_pake_set_password_key()` with :code:`psa_pake_setup()`. This aligns the API better with other multi-part operations, and also enables an implementation to identify the key location when setting up the operation. + - `PSA_ALG_SPAKE2P_HMAC()` + - `PSA_ALG_SPAKE2P_CMAC()` + - `PSA_ALG_SPAKE2P_MATTER` + - `PSA_ALG_IS_SPAKE2P()` + - `PSA_ALG_IS_SPAKE2P_HMAC()` + - `PSA_ALG_IS_SPAKE2P_CMAC()` Clarifications ~~~~~~~~~~~~~~ diff --git a/doc/ext-pake/appendix/specdef_values.rst b/doc/ext-pake/appendix/specdef_values.rst index d13eb041..66d7f0d0 100644 --- a/doc/ext-pake/appendix/specdef_values.rst +++ b/doc/ext-pake/appendix/specdef_values.rst @@ -15,10 +15,49 @@ The examples here provide correct results for the valid inputs defined by each A .. code-block:: xref + #define PSA_ALG_IS_JPAKE(alg) \ + (((alg) & ~0x000000ff) == 0x0a000100) + #define PSA_ALG_IS_PAKE(alg) \ (((alg) & 0x7f000000) == 0x0a000000) + #define PSA_ALG_IS_SPAKE2P(alg) \ + (((alg) & ~0x000003ff) == 0x0a000400) + + #define PSA_ALG_IS_SPAKE2P_CMAC(alg) \ + (((alg) & ~0x000000ff) == 0x0a000500) + + #define PSA_ALG_IS_SPAKE2P_HMAC(alg) \ + (((alg) & ~0x000000ff) == 0x0a000400) + + #define PSA_ALG_JPAKE(hash_alg) \ + ((psa_algorithm_t) (0x0a000100 | ((hash_alg) & 0x000000ff))) + + #define PSA_ALG_SPAKE2P_CMAC(hash_alg) \ + ((psa_algorithm_t) (0x0a000500 | ((hash_alg) & 0x000000ff))) + + #define PSA_ALG_SPAKE2P_HMAC(hash_alg) \ + ((psa_algorithm_t) (0x0a000400 | ((hash_alg) & 0x000000ff))) + #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))) + + #define PSA_KEY_TYPE_SPAKE2P_GET_FAMILY(type) \ + ((psa_ecc_family_t) ((type) & 0x00ff)) + + #define PSA_KEY_TYPE_SPAKE2P_KEY_PAIR(curve) \ + ((psa_key_type_t) (0x7400 | (curve))) + + #define PSA_KEY_TYPE_SPAKE2P_PUBLIC_KEY(curve) \ + ((psa_key_type_t) (0x4400 | (curve))) + + #define PSA_KEY_TYPE_IS_SPAKE2P(type) \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & 0xff00) == 0x4400) + + #define PSA_KEY_TYPE_IS_SPAKE2P_KEY_PAIR(type) \ + (((type) & 0xff00) == 0x7400) + + #define PSA_KEY_TYPE_IS_SPAKE2P_PUBLIC_KEY(type) \ + (((type) & 0xff00) == 0x4400) diff --git a/doc/ext-pake/figure/j-pake.pdf b/doc/ext-pake/figure/j-pake.pdf index 96a090f5..ab7a94f5 100644 Binary files a/doc/ext-pake/figure/j-pake.pdf and b/doc/ext-pake/figure/j-pake.pdf differ diff --git a/doc/ext-pake/figure/j-pake.pdf.license b/doc/ext-pake/figure/j-pake.pdf.license index 70c4b2a6..a2d0bf3f 100644 --- a/doc/ext-pake/figure/j-pake.pdf.license +++ b/doc/ext-pake/figure/j-pake.pdf.license @@ -1,2 +1,2 @@ -SPDX-FileCopyrightText: Copyright 2022 Arm Limited and/or its affiliates +SPDX-FileCopyrightText: Copyright 2022-2023 Arm Limited and/or its affiliates SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license diff --git a/doc/ext-pake/figure/j-pake.puml b/doc/ext-pake/figure/j-pake.puml index 0f3de674..2cea977a 100644 --- a/doc/ext-pake/figure/j-pake.puml +++ b/doc/ext-pake/figure/j-pake.puml @@ -1,4 +1,4 @@ -' SPDX-FileCopyrightText: Copyright 2022 Arm Limited and/or its affiliates +' SPDX-FileCopyrightText: Copyright 2022-2023 Arm Limited and/or its affiliates ' SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license @startuml @@ -39,6 +39,6 @@ note over User, Peer: If both sides used the same secret //s//, then //Ka// = //Kb// - User -> User: ""psa_pake_get_implicit_key()"" to extract //Ka// + User -> User: ""psa_pake_get_shared_key()"" to extract //Ka// @enduml diff --git a/doc/ext-pake/figure/j-pake.svg b/doc/ext-pake/figure/j-pake.svg index ba33637f..1f13635b 100644 --- a/doc/ext-pake/figure/j-pake.svg +++ b/doc/ext-pake/figure/j-pake.svg @@ -1 +1 @@ -UserPeerShared information: cipher suite, secrets,UserId, andPeerIdpsa_pake_setup()psa_pake_set_user()psa_pake_set_peer()Generatex1andx2Compute public keysg1andg2Compute ZKP(V1, r1)forg1and(V2, r2)forg2Generatex3andx4Compute public keysg3andg4Compute ZKPs(V3, r3)forg3and(V4, r4)forg4psa_pake_output()forg1, V1, r1, g2, V2, andr2(g1, V1, r1, g2, V2, r2)(g3, V3, r3, g4, V4, r4)psa_pake_input()forg3, V3, r3, g4, V4, andr4Verify ZKPs and computeAand ZKP(V5, r5)forx2*sVerify ZKPs and computeBand ZKP(V6, r6)forx4*spsa_pake_output()forA, V5, andr5(A, V5, r5)(B, V6, r6)psa_pake_input()forB, V6, andr6Verify ZKP and computeKaVerify ZKP and computeKbIf both sides used the same secrets, thenKa=Kbpsa_pake_get_implicit_key()to extractKa \ No newline at end of file +UserPeerShared information: cipher suite, secrets,UserId, andPeerIdpsa_pake_setup()psa_pake_set_user()psa_pake_set_peer()Generatex1andx2Compute public keysg1andg2Compute ZKP(V1, r1)forg1and(V2, r2)forg2Generatex3andx4Compute public keysg3andg4Compute ZKPs(V3, r3)forg3and(V4, r4)forg4psa_pake_output()forg1, V1, r1, g2, V2, andr2(g1, V1, r1, g2, V2, r2)(g3, V3, r3, g4, V4, r4)psa_pake_input()forg3, V3, r3, g4, V4, andr4Verify ZKPs and computeAand ZKP(V5, r5)forx2*sVerify ZKPs and computeBand ZKP(V6, r6)forx4*spsa_pake_output()forA, V5, andr5(A, V5, r5)(B, V6, r6)psa_pake_input()forB, V6, andr6Verify ZKP and computeKaVerify ZKP and computeKbIf both sides used the same secrets, thenKa=Kbpsa_pake_get_shared_key()to extractKa \ No newline at end of file diff --git a/doc/ext-pake/figure/j-pake.svg.license b/doc/ext-pake/figure/j-pake.svg.license index 70c4b2a6..a2d0bf3f 100644 --- a/doc/ext-pake/figure/j-pake.svg.license +++ b/doc/ext-pake/figure/j-pake.svg.license @@ -1,2 +1,2 @@ -SPDX-FileCopyrightText: Copyright 2022 Arm Limited and/or its affiliates +SPDX-FileCopyrightText: Copyright 2022-2023 Arm Limited and/or its affiliates SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license diff --git a/doc/ext-pake/figure/pake_encoding.json b/doc/ext-pake/figure/pake_encoding.json index 1032c146..6c40cb13 100644 --- a/doc/ext-pake/figure/pake_encoding.json +++ b/doc/ext-pake/figure/pake_encoding.json @@ -1,6 +1,6 @@ { "reg": [ - { "name": "0", "bits": 8 }, + { "name": "HASH-TYPE", "bits": 8 }, { "name": "PAKE-TYPE", "bits": 8 }, { "name": "0", "bits": 6 }, { "name": "0", "bits": 1 }, @@ -15,4 +15,4 @@ "vspace": 52, "hspace": 600 } -} \ No newline at end of file +} diff --git a/doc/ext-pake/figure/pake_encoding.json.license b/doc/ext-pake/figure/pake_encoding.json.license index 70c4b2a6..9a9052df 100644 --- a/doc/ext-pake/figure/pake_encoding.json.license +++ b/doc/ext-pake/figure/pake_encoding.json.license @@ -1,2 +1,2 @@ -SPDX-FileCopyrightText: Copyright 2022 Arm Limited and/or its affiliates +SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license diff --git a/doc/ext-pake/figure/pake_encoding.pdf b/doc/ext-pake/figure/pake_encoding.pdf index 11f2c480..33add152 100644 Binary files a/doc/ext-pake/figure/pake_encoding.pdf and b/doc/ext-pake/figure/pake_encoding.pdf differ diff --git a/doc/ext-pake/figure/pake_encoding.pdf.license b/doc/ext-pake/figure/pake_encoding.pdf.license index 70c4b2a6..9a9052df 100644 --- a/doc/ext-pake/figure/pake_encoding.pdf.license +++ b/doc/ext-pake/figure/pake_encoding.pdf.license @@ -1,2 +1,2 @@ -SPDX-FileCopyrightText: Copyright 2022 Arm Limited and/or its affiliates +SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license diff --git a/doc/ext-pake/figure/pake_encoding.svg b/doc/ext-pake/figure/pake_encoding.svg index 9ba39b3c..0cfe596b 100644 --- a/doc/ext-pake/figure/pake_encoding.svg +++ b/doc/ext-pake/figure/pake_encoding.svg @@ -1,2 +1,2 @@ -07815162122232430310PAKE-TYPE0000x0A0 \ No newline at end of file +0781516212223243031HASH-TYPEPAKE-TYPE0000x0A0 \ No newline at end of file diff --git a/doc/ext-pake/figure/pake_encoding.svg.license b/doc/ext-pake/figure/pake_encoding.svg.license index 70c4b2a6..9a9052df 100644 --- a/doc/ext-pake/figure/pake_encoding.svg.license +++ b/doc/ext-pake/figure/pake_encoding.svg.license @@ -1,2 +1,2 @@ -SPDX-FileCopyrightText: Copyright 2022 Arm Limited and/or its affiliates +SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license diff --git a/doc/ext-pake/figure/spake2p_key.json b/doc/ext-pake/figure/spake2p_key.json new file mode 100644 index 00000000..c9c6716f --- /dev/null +++ b/doc/ext-pake/figure/spake2p_key.json @@ -0,0 +1,18 @@ +{ + "reg": [ + { "name": "P", "bits": 1 }, + { "name": "ECC-FAMILY", "bits": 7 }, + { "name": "4", "bits": 4 }, + { "name": "PAIR", "bits": 2 }, + { "name": "1", "bits": 1 }, + { "name": "0", "bits": 1 } + ], + "options": { + "lanes": 1, + "fontfamily": "lato", + "fontsize": 11, + "bits": 16, + "vspace": 52, + "hspace": 300 + } +} diff --git a/doc/ext-pake/figure/spake2p_key.json.license b/doc/ext-pake/figure/spake2p_key.json.license new file mode 100644 index 00000000..9a9052df --- /dev/null +++ b/doc/ext-pake/figure/spake2p_key.json.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates +SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license diff --git a/doc/ext-pake/figure/spake2p_key.pdf b/doc/ext-pake/figure/spake2p_key.pdf new file mode 100644 index 00000000..550b7a21 Binary files /dev/null and b/doc/ext-pake/figure/spake2p_key.pdf differ diff --git a/doc/ext-pake/figure/spake2p_key.pdf.license b/doc/ext-pake/figure/spake2p_key.pdf.license new file mode 100644 index 00000000..9a9052df --- /dev/null +++ b/doc/ext-pake/figure/spake2p_key.pdf.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates +SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license diff --git a/doc/ext-pake/figure/spake2p_key.svg b/doc/ext-pake/figure/spake2p_key.svg new file mode 100644 index 00000000..1dfac6a6 --- /dev/null +++ b/doc/ext-pake/figure/spake2p_key.svg @@ -0,0 +1,2 @@ + +01781112131415PECC-FAMILY4PAIR10 \ No newline at end of file diff --git a/doc/ext-pake/figure/spake2p_key.svg.license b/doc/ext-pake/figure/spake2p_key.svg.license new file mode 100644 index 00000000..9a9052df --- /dev/null +++ b/doc/ext-pake/figure/spake2p_key.svg.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates +SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license diff --git a/doc/ext-pake/figure/spake2plus-reg.pdf b/doc/ext-pake/figure/spake2plus-reg.pdf new file mode 100644 index 00000000..7140f560 Binary files /dev/null and b/doc/ext-pake/figure/spake2plus-reg.pdf differ diff --git a/doc/ext-pake/figure/spake2plus-reg.pdf.license b/doc/ext-pake/figure/spake2plus-reg.pdf.license new file mode 100644 index 00000000..9a9052df --- /dev/null +++ b/doc/ext-pake/figure/spake2plus-reg.pdf.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates +SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license diff --git a/doc/ext-pake/figure/spake2plus-reg.puml b/doc/ext-pake/figure/spake2plus-reg.puml new file mode 100644 index 00000000..a9f1929f --- /dev/null +++ b/doc/ext-pake/figure/spake2plus-reg.puml @@ -0,0 +1,41 @@ +' SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates +' SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license + +@startuml + + !include atg-spec.pumh + + participant "Prover //(Client role)//" as Prover + participant "Verifier //(Server role)//" as Verifier + + note over Prover, Verifier: Initial information : cipher suite, //PBKDF-params//, //password// + + Prover -> Prover: ""psa_key_derivation_setup(PBKDF)""\n""psa_key_derivation_input_key(password)""\n""psa_key_derivation_input_xxx()"" for //PBKDF-params// + + Prover -> Prover: ""psa_key_derivation_output_key(SPAKE2P_KEY_PAIR)"" + note left: Compute key-pair (//w0//, //w1//) + + alt Independent registration + + Verifier -> Verifier: ""psa_key_derivation_setup(PBKDF)""\n""psa_key_derivation_input_key(password)""\n""psa_key_derivation_input_xxx()"" for //PBKDF-params// + + Verifier -> Verifier: ""psa_key_derivation_output_key(SPAKE2P_PUBLIC_KEY)"" + note left: Compute public-key (//w0//, //L//) + + else Connected registration + + Prover -> Prover: ""psa_export_public_key()"" + note left: Compute //L// and output //w0// || //L// + + Prover ->> Verifier: Registration record ( //w0// || //L// ) + + Verifier -> Verifier: ""psa_import_key(SPAKE2P_PUBLIC_KEY)"" from //w0// || //L// + note left: Import public-key (//w0//, //L//) + + end + + note over Prover: Use key-pair for authentication flow + / note over Verifier: Use public-key for authentication flow + + +@enduml diff --git a/doc/ext-pake/figure/spake2plus-reg.svg b/doc/ext-pake/figure/spake2plus-reg.svg new file mode 100644 index 00000000..43a0c947 --- /dev/null +++ b/doc/ext-pake/figure/spake2plus-reg.svg @@ -0,0 +1 @@ +Prover(Client role)Verifier(Server role)Initial information : cipher suite,PBKDF-params,passwordpsa_key_derivation_setup(PBKDF)psa_key_derivation_input_key(password)psa_key_derivation_input_xxx()forPBKDF-paramspsa_key_derivation_output_key(SPAKE2P_KEY_PAIR)Compute key-pair (w0,w1)alt[Independent registration]psa_key_derivation_setup(PBKDF)psa_key_derivation_input_key(password)psa_key_derivation_input_xxx()forPBKDF-paramspsa_key_derivation_output_key(SPAKE2P_PUBLIC_KEY)Compute public-key (w0,L)[Connected registration]psa_export_public_key()ComputeLand outputw0||LRegistration record (w0||L)psa_import_key(SPAKE2P_PUBLIC_KEY)fromw0||LImport public-key (w0,L)Use key-pair for authentication flowUse public-key for authentication flow \ No newline at end of file diff --git a/doc/ext-pake/figure/spake2plus-reg.svg.license b/doc/ext-pake/figure/spake2plus-reg.svg.license new file mode 100644 index 00000000..9a9052df --- /dev/null +++ b/doc/ext-pake/figure/spake2plus-reg.svg.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates +SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license diff --git a/doc/ext-pake/figure/spake2plus.pdf b/doc/ext-pake/figure/spake2plus.pdf new file mode 100644 index 00000000..aba6461a Binary files /dev/null and b/doc/ext-pake/figure/spake2plus.pdf differ diff --git a/doc/ext-pake/figure/spake2plus.pdf.license b/doc/ext-pake/figure/spake2plus.pdf.license new file mode 100644 index 00000000..9a9052df --- /dev/null +++ b/doc/ext-pake/figure/spake2plus.pdf.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates +SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license diff --git a/doc/ext-pake/figure/spake2plus.puml b/doc/ext-pake/figure/spake2plus.puml new file mode 100644 index 00000000..a226d58f --- /dev/null +++ b/doc/ext-pake/figure/spake2plus.puml @@ -0,0 +1,54 @@ +' SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates +' SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license + +@startuml + + !include atg-spec.pumh + + participant "Prover //(Client role)//" as Prover + participant "Verifier //(Server role)//" as Verifier + + note over Prover, Verifier: Shared information : cipher suite, //ProverId//, //VerifierId//, and //Context// + note over Verifier: Registration record (//w0//, //L//) derived from password + / note over Prover: Prover 'key pair' (//w0//, //w1//) derived from password + + ... + + Prover -> Prover: ""psa_pake_setup()"" with key (//w0//, //w1//)\n""psa_pake_set_role(PSA_PAKE_ROLE_CLIENT)""\n""psa_pake_set_user(ProverId)""\n""psa_pake_set_peer(VerifierId)""\n""psa_pake_set_context(Context)"" + + note over Prover: Generate key share //X// + + Prover -> Prover: ""psa_pake_output()"" for //shareP// = //X// + Prover ->> Verifier: (//shareP//) + + Verifier -> Verifier: ""psa_pake_setup()"" with key (//w0//, //L//)\n""psa_pake_set_role(PSA_PAKE_ROLE_SERVER)""\n""psa_pake_set_user(VerifierId)""\n""psa_pake_set_peer(ProverId)""\n""psa_pake_set_context(Context)"" + + note over Verifier: Generate key share //Y// + Verifier -> Verifier: ""psa_pake_input()"" for //shareP// + note over Verifier + Validate //shareP// + Compute //K_shared//, //confirmP'// and //confirmV// + end note + + Verifier -> Verifier: ""psa_pake_output()"" for //shareV// = //Y// and //confirmV// + Verifier ->> Prover: (//shareV//, //confirmV//) + + Prover -> Prover: ""psa_pake_input()"" for //shareV// + + note over Prover + Validate //shareV// + Compute //K_shared//, //confirmP// and //confirmV'// + end note + + Prover -> Prover: ""psa_pake_output()"" for //confirmP// + Prover ->> Verifier: (//confirmP//) + + Prover -> Prover: ""psa_pake_input()"" for //confirmV// + note over Prover: Verify that //confirmV'// = //confirmV// + Prover -> Prover: ""psa_pake_get_shared_key()"" to extract //K_shared// + + Verifier -> Verifier: ""psa_pake_input()"" for //confirmP// + note over Verifier: Verify that //confirmP'// = //confirmP// + Verifier -> Verifier: ""psa_pake_get_shared_key()"" to extract //K_shared// + +@enduml diff --git a/doc/ext-pake/figure/spake2plus.svg b/doc/ext-pake/figure/spake2plus.svg new file mode 100644 index 00000000..11051de7 --- /dev/null +++ b/doc/ext-pake/figure/spake2plus.svg @@ -0,0 +1 @@ +Prover(Client role)Verifier(Server role)Shared information : cipher suite,ProverId,VerifierId, andContextRegistration record (w0,L) derived from passwordProver 'key pair' (w0,w1) derived from passwordpsa_pake_setup()with key (w0,w1)psa_pake_set_role(PSA_PAKE_ROLE_CLIENT)psa_pake_set_user(ProverId)psa_pake_set_peer(VerifierId)psa_pake_set_context(Context)Generate key shareXpsa_pake_output()forshareP=X(shareP)psa_pake_setup()with key (w0,L)psa_pake_set_role(PSA_PAKE_ROLE_SERVER)psa_pake_set_user(VerifierId)psa_pake_set_peer(ProverId)psa_pake_set_context(Context)Generate key shareYpsa_pake_input()forsharePValidatesharePComputeK_shared,confirmP'andconfirmVpsa_pake_output()forshareV=YandconfirmV(shareV,confirmV)psa_pake_input()forshareVValidateshareVComputeK_shared,confirmPandconfirmV'psa_pake_output()forconfirmP(confirmP)psa_pake_input()forconfirmVVerify thatconfirmV'=confirmVpsa_pake_get_shared_key()to extractK_sharedpsa_pake_input()forconfirmPVerify thatconfirmP'=confirmPpsa_pake_get_shared_key()to extractK_shared \ No newline at end of file diff --git a/doc/ext-pake/figure/spake2plus.svg.license b/doc/ext-pake/figure/spake2plus.svg.license new file mode 100644 index 00000000..9a9052df --- /dev/null +++ b/doc/ext-pake/figure/spake2plus.svg.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates +SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license diff --git a/doc/ext-pake/references b/doc/ext-pake/references index 5b81c743..b476f202 100644 --- a/doc/ext-pake/references +++ b/doc/ext-pake/references @@ -1,4 +1,4 @@ -.. SPDX-FileCopyrightText: Copyright 2022 Arm Limited and/or its affiliates +.. SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates .. SPDX-License-Identifier: CC-BY-SA-4.0 AND LicenseRef-Patent-license .. reference:: PSA-CRYPT @@ -28,3 +28,21 @@ :author: IETF :publication: September 2017 :url: tools.ietf.org/html/rfc8236.html + +.. reference:: RFC9383 + :title: SPAKE2+, an Augmented Password-Authenticated Key Exchange (PAKE) Protocol + :author: IETF + :publication: September 2023 + :url: tools.ietf.org/html/rfc9383.html + +.. reference:: SPAKE2P-2 + :title: SPAKE2+, an Augmented PAKE + :author: IETF + :publication: December 2020 (Draft) + :url: datatracker.ietf.org/doc/draft-bar-cfrg-spake2plus-02 + +.. reference:: MATTER + :title: Matter Specification, Version 1.2 + :author: CSA + :publication: October 2023 + :url: csa-iot.org/all-solutions/matter/