From 5f255b48e03ac3e26a1b01c0ac2ad44a5bc22e63 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Fri, 3 Nov 2023 12:14:12 +0000 Subject: [PATCH 1/4] Add new asymmetric key types for SPAKE2+ * Add key encodings * Define public key format * Define key derivation procedure --- doc/ext-pake/api/pake.rst | 204 +++++++++++++++++++ doc/ext-pake/appendix/history.rst | 2 + doc/ext-pake/appendix/specdef_values.rst | 18 ++ doc/ext-pake/figure/spake2p_key.json | 18 ++ doc/ext-pake/figure/spake2p_key.json.license | 2 + doc/ext-pake/figure/spake2p_key.pdf | Bin 0 -> 7438 bytes doc/ext-pake/figure/spake2p_key.pdf.license | 2 + doc/ext-pake/figure/spake2p_key.svg | 2 + doc/ext-pake/figure/spake2p_key.svg.license | 2 + 9 files changed, 250 insertions(+) create mode 100644 doc/ext-pake/figure/spake2p_key.json create mode 100644 doc/ext-pake/figure/spake2p_key.json.license create mode 100644 doc/ext-pake/figure/spake2p_key.pdf create mode 100644 doc/ext-pake/figure/spake2p_key.pdf.license create mode 100644 doc/ext-pake/figure/spake2p_key.svg create mode 100644 doc/ext-pake/figure/spake2p_key.svg.license diff --git a/doc/ext-pake/api/pake.rst b/doc/ext-pake/api/pake.rst index 99886c7b..27e77912 100644 --- a/doc/ext-pake/api/pake.rst +++ b/doc/ext-pake/api/pake.rst @@ -55,6 +55,77 @@ The permitted values of HASH-TYPE depend on the specific KDF algorithm. 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? + +.. 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? + +.. 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). + Changes and additions to the Programming API -------------------------------------------- @@ -68,6 +139,139 @@ 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 + + SPAEK2+ key pairs can be used in SPAKE2+ PAKE algorithms. + +.. 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 + + SPAEK2+ key pairs can be used in SPAKE2+ PAKE algorithms. + +.. 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. + +Key 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); + + :issue:`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: diff --git a/doc/ext-pake/appendix/history.rst b/doc/ext-pake/appendix/history.rst index b2166175..cce8bbaa 100644 --- a/doc/ext-pake/appendix/history.rst +++ b/doc/ext-pake/appendix/history.rst @@ -27,6 +27,8 @@ API changes * 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`. +* 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. + Clarifications ~~~~~~~~~~~~~~ diff --git a/doc/ext-pake/appendix/specdef_values.rst b/doc/ext-pake/appendix/specdef_values.rst index 470d9e41..23c75b74 100644 --- a/doc/ext-pake/appendix/specdef_values.rst +++ b/doc/ext-pake/appendix/specdef_values.rst @@ -28,3 +28,21 @@ The examples here provide correct results for the valid inputs defined by each A ((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/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 0000000000000000000000000000000000000000..550b7a21054cc83b21ec47fb275ede8dddbf90a3 GIT binary patch literal 7438 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 WL10MKnRi7omrB6KrgT%8;Qs*+A%xZd literal 0 HcmV?d00001 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 From 4a6f0af7cc0f52699422443eb779a52366afe2f5 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Fri, 24 Nov 2023 18:00:39 +0000 Subject: [PATCH 2/4] Resolve some open issues * Add macros to crack a PAKE primitive value * Decide on using USAGE_DERIVE for SPAKE2+ keys * Fix typos * Update header file --- doc/ext-pake/api.db/psa/crypto-pake.h | 15 ++++++ doc/ext-pake/api/pake.rst | 69 +++++++++++++++++++----- doc/ext-pake/appendix/specdef_values.rst | 9 ++++ 3 files changed, 80 insertions(+), 13 deletions(-) diff --git a/doc/ext-pake/api.db/psa/crypto-pake.h b/doc/ext-pake/api.db/psa/crypto-pake.h index 21a84e9c..83f10ca7 100644 --- a/doc/ext-pake/api.db/psa/crypto-pake.h +++ b/doc/ext-pake/api.db/psa/crypto-pake.h @@ -11,6 +11,15 @@ 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(hash_alg) /* specification-defined value */ +#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 */ @@ -22,6 +31,12 @@ typedef uint8_t psa_pake_step_t; /* implementation-defined value */ #define PSA_PAKE_PRIMITIVE(pake_type, pake_family, pake_bits) \ /* specification-defined value */ +#define PSA_PAKE_PRIMITIVE_GET_BITS(pake_primitive) \ + /* specification-defined value */ +#define PSA_PAKE_PRIMITIVE_GET_FAMILY(pake_primitive) \ + /* specification-defined value */ +#define PSA_PAKE_PRIMITIVE_GET_TYPE(pake_primitive) \ + /* specification-defined value */ #define PSA_PAKE_PRIMITIVE_TYPE_DH ((psa_pake_primitive_type_t)0x02) #define PSA_PAKE_PRIMITIVE_TYPE_ECC ((psa_pake_primitive_type_t)0x01) #define PSA_PAKE_ROLE_CLIENT ((psa_pake_role_t)0x11) diff --git a/doc/ext-pake/api/pake.rst b/doc/ext-pake/api/pake.rst index 27e77912..00f8d413 100644 --- a/doc/ext-pake/api/pake.rst +++ b/doc/ext-pake/api/pake.rst @@ -150,11 +150,11 @@ The SPAKE2+ protocol consists of three phases: 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 registration phase can be carried out immediately before 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 |API| uses an asymmetric key-pair, and a 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` +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. .. macro:: PSA_KEY_TYPE_SPAKE2P_KEY_PAIR :definition: /* specification-defined value */ @@ -169,7 +169,7 @@ The SPAKE2+ algorithms are based on Elliptic curve groups, and a SPAKE2+ key is .. subsection:: Compatible algorithms - SPAEK2+ key pairs can be used in SPAKE2+ PAKE algorithms. + SPAKE2+ key pairs can be used in SPAKE2+ PAKE algorithms. .. macro:: PSA_KEY_TYPE_SPAKE2P_PUBLIC_KEY :definition: /* specification-defined value */ @@ -184,7 +184,7 @@ The SPAKE2+ algorithms are based on Elliptic curve groups, and a SPAKE2+ key is .. subsection:: Compatible algorithms - SPAEK2+ key pairs can be used in SPAKE2+ PAKE algorithms. + SPAKE2+ key pairs can be used in SPAKE2+ PAKE algorithms. .. macro:: PSA_KEY_TYPE_IS_SPAKE2P :definition: /* specification-defined value */ @@ -249,11 +249,9 @@ For example, after setting up the PBKDF2 operation, the following process will d .. code-block:: xref - psa_set_key_usage_flags(&att, PSA_KEY_USAGE_????); + psa_set_key_usage_flags(&att, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&att, PSA_ALG_SPAKE2P); - :issue:`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 @@ -466,6 +464,8 @@ Many PAKE algorithms are designed to allow different cryptographic primitives to The cryptographic primitive for a PAKE operation is specified using a `psa_pake_primitive_t` value, which can be constructed using the `PSA_PAKE_PRIMITIVE()` macro, or can be provided as a numerical constant value. +The components of a PAKE primitive value can be extracted using the `PSA_PAKE_PRIMITIVE_GET_TYPE()`, `PSA_PAKE_PRIMITIVE_GET_FAMILY()`, and `PSA_PAKE_PRIMITIVE_GET_BITS()`. These can be used to set key attributes for keys used in PAKE algorithms. + A PAKE primitive is required when constructing a PAKE cipher-suite object, `psa_pake_cipher_suite_t`, which fully specifies the PAKE operation to be carried out. @@ -486,7 +486,7 @@ A PAKE primitive is required when constructing a PAKE cipher-suite object, `psa_ Implementation-defined primitive type. Implementations that define additional primitive types must use an encoding with bit 7 set. - For specification-defined primitive types, see the documentation of individual ``PSA_PAKE_PRIMITIVE_TYPE_XXX`` constants. + For specification-defined primitive types, see `PSA_PAKE_PRIMITIVE_TYPE_ECC` and `PSA_PAKE_PRIMITIVE_TYPE_DH`. .. macro:: PSA_PAKE_PRIMITIVE_TYPE_ECC :definition: ((psa_pake_primitive_type_t)0x01) @@ -529,7 +529,7 @@ A PAKE primitive is required when constructing a PAKE cipher-suite object, `psa_ .. summary:: Encoding of the family of the primitive associated with the PAKE. - For more information see the documentation of individual ``PSA_PAKE_PRIMITIVE_TYPE_XXX`` constants. + For more information on the family values, see `PSA_PAKE_PRIMITIVE_TYPE_ECC` and `PSA_PAKE_PRIMITIVE_TYPE_DH`. .. typedef:: uint32_t psa_pake_primitive_t @@ -553,16 +553,59 @@ A PAKE primitive is required when constructing a PAKE cipher-suite object, `psa_ .. param:: pake_family The family of the primitive. The type and interpretation of this parameter depends on ``pake_type``. - For more information, consult the documentation of individual `psa_pake_primitive_type_t` constants. + For more information, see `PSA_PAKE_PRIMITIVE_TYPE_ECC` and `PSA_PAKE_PRIMITIVE_TYPE_DH`. .. param:: pake_bits The bit-size of the primitive: a value of type ``size_t``. - The interpretation of this parameter depends on ``family``. - For more information, consult the documentation of individual `psa_pake_primitive_type_t` constants. + The interpretation of this parameter depends on ``pake_type`` and ``family``. + For more information, see `PSA_PAKE_PRIMITIVE_TYPE_ECC` and `PSA_PAKE_PRIMITIVE_TYPE_DH`. .. return:: psa_pake_primitive_t The constructed primitive value. Return ``0`` if the requested primitive can't be encoded as `psa_pake_primitive_t`. + A PAKE primitive value is used to specify a PAKE operation, as part of a PAKE cipher suite. + + The components of a PAKE primitive value can be extracted using the `PSA_PAKE_PRIMITIVE_GET_TYPE()`, `PSA_PAKE_PRIMITIVE_GET_FAMILY()`, and `PSA_PAKE_PRIMITIVE_GET_BITS()`. + +.. macro:: PSA_PAKE_PRIMITIVE_GET_TYPE + :definition: /* specification-defined value */ + + .. summary:: + Extract the PAKE primitive type from a PAKE primitive. + + .. param:: pake_primitive + A PAKE primitive: a value of type `psa_pake_primitive_t`. + + .. return:: psa_pake_primitive_type_t + The PAKE primitive type, if ``pake_primitive`` is a supported PAKE primitive. Unspecified if ``pake_primitive`` is not a supported PAKE primitive. + +.. macro:: PSA_PAKE_PRIMITIVE_GET_FAMILY + :definition: /* specification-defined value */ + + .. summary:: + Extract the family from a PAKE primitive. + + .. param:: pake_primitive + A PAKE primitive: a value of type `psa_pake_primitive_t`. + + .. return:: psa_pake_family_t + The PAKE primitive family, if ``pake_primitive`` is a supported PAKE primitive. Unspecified if ``pake_primitive`` is not a supported PAKE primitive. + + For more information on the family values, see `PSA_PAKE_PRIMITIVE_TYPE_ECC` and `PSA_PAKE_PRIMITIVE_TYPE_DH`. + +.. macro:: PSA_PAKE_PRIMITIVE_GET_BITS + :definition: /* specification-defined value */ + + .. summary:: + Extract the bit-size from a PAKE primitive. + + .. param:: pake_primitive + A PAKE primitive: a value of type `psa_pake_primitive_t`. + + .. return:: size_t + The PAKE primitive bit-size, if ``pake_primitive`` is a supported PAKE primitive. Unspecified if ``pake_primitive`` is not a supported PAKE primitive. + + For more information on the bit-size values, see `PSA_PAKE_PRIMITIVE_TYPE_ECC` and `PSA_PAKE_PRIMITIVE_TYPE_DH`. .. _pake-cipher-suite: diff --git a/doc/ext-pake/appendix/specdef_values.rst b/doc/ext-pake/appendix/specdef_values.rst index 23c75b74..689077ee 100644 --- a/doc/ext-pake/appendix/specdef_values.rst +++ b/doc/ext-pake/appendix/specdef_values.rst @@ -29,6 +29,15 @@ The examples here provide correct results for the valid inputs defined by each A ((psa_pake_primitive_t) (((pake_type) << 24 | \ (pake_family) << 16) | (pake_bits))) + #define PSA_PAKE_PRIMITIVE_GET_BITS(pake_primitive) \ + ((size_t)(pake_primitive & 0xFFFF)) + + #define PSA_PAKE_PRIMITIVE_GET_FAMILY(pake_primitive) \ + ((psa_pake_family_t)((pake_primitive >> 16) & 0xFF)) + + #define PSA_PAKE_PRIMITIVE_GET_TYPE(pake_primitive) \ + ((psa_pake_primitive_type_t)((pake_primitive >> 24) & 0xFF)) + #define PSA_KEY_TYPE_SPAKE2P_GET_FAMILY(type) \ ((psa_ecc_family_t) ((type) & 0x00ff)) From 999f3b2afcdc97ac9da3ae7cdebcaad72fc2ae6b Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Wed, 29 Nov 2023 16:32:00 +0000 Subject: [PATCH 3/4] Clarify SPAKE2+ key formats and derivation * Constrain key derivation to SPAKE2+ key pairs * Specify the length of data extracted from the KDF during derivation * Use a list format to define the exported key format --- doc/ext-pake/api/pake.rst | 68 +++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/doc/ext-pake/api/pake.rst b/doc/ext-pake/api/pake.rst index 00f8d413..730b696e 100644 --- a/doc/ext-pake/api/pake.rst +++ b/doc/ext-pake/api/pake.rst @@ -106,22 +106,16 @@ 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 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, corresponding to the w1 value in the key pair. -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: +For the |API|, the default format for a SPAKE2+ public key is the concatenation of the formatted values for w0 and L, using the standard formats for Elliptic curve keys used by the |API|. For example, for SPAKE2+ over P-256 (secp256r1), the output from :code:`psa_export_public_key()` would be the concatenation of: - [ w0 ]\ :sub:`32` || 0x04 || [ x\ :sub:`L` ]\ :sub:`32` || [ y\ :sub:`L` ]\ :sub:`32` +* The 32-byte formatted value of the P-256 private key w0. This is a big-endian encoding of the integer w0. +* The 65-byte formatted value of the P-256 public key L. This is itself a concatenation of: -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? - -.. 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? - -.. 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? + - The byte ``0x04``. + - The 32-byte big-endian encoding of the x-coordinate of L. + - The 32-byte big-endian encoding of the y-coordinate of L. .. 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). @@ -162,11 +156,16 @@ The SPAKE2+ algorithms are based on Elliptic curve groups, and a SPAKE2+ key is .. 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. + 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. + + To construct a SPAKE2+ key pair, it must be output from a key derivation operation. See :secref:`spake2p-key-derivation`. + + The corresponding public key can be exported using :code:`psa_export_public_key()`. See also `PSA_KEY_TYPE_SPAKE2P_PUBLIC_KEY()`. + + .. subsection:: Compatible algorithms SPAKE2+ key pairs can be used in SPAKE2+ PAKE algorithms. @@ -182,9 +181,11 @@ The SPAKE2+ algorithms are based on Elliptic curve groups, and a SPAKE2+ key is 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. + To construct a SPAKE2+ public key, it must be imported. + .. subsection:: Compatible algorithms - SPAKE2+ key pairs can be used in SPAKE2+ PAKE algorithms. + SPAKE2+ public keys can be used in SPAKE2+ PAKE algorithms. .. macro:: PSA_KEY_TYPE_IS_SPAKE2P :definition: /* specification-defined value */ @@ -225,12 +226,14 @@ The SPAKE2+ algorithms are based on Elliptic curve groups, and a SPAKE2+ key is .. 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: + Key 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. +A SPAKE2+ key pair can be output from a key derivation using :code:`psa_key_derivation_output_key()`. The SPAKE2+ protocol recommends that a key-stretching key-derivation function, 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?)`: +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 can be combined with an illustration of the registration flow in the final specification)`: 1. Allocate and initialize a key attributes object: @@ -256,20 +259,37 @@ For example, after setting up the PBKDF2 operation, the following process will d .. code-block:: xref - psa_key_id_t sp2_key; - psa_key_derivation_output_key(&att, &kdf_op, &sp2_key); + psa_key_id_t sp2p_key; + psa_key_derivation_output_key(&att, &kdf_op, &sp2p_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 following sizes are used for extracting w0s and w1s, depending on the elliptic curve: + + .. csv-table:: + :header-rows: 1 + :widths: auto + :align: left + + Elliptic curve, "Size of w0s and w1s, in bytes" + P-256, 40 + P-384, 56 + P-521, 74 + edwards25519, 40 + edwards448, 64 + + :issue:`I think these values are correct?` + * 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? + .. admonition:: Implementation note + + The values of w0 and w1 are required as part of the SPAKE2+ key pair. + + It is :scterm:`implementation defined` whether L is computed during key derivation, and stored as part of the key pair; or only computed when required from the key pair. .. _pake-algorithms: From 37902048dee00eda564dac8550c8a8d9d1ad718d Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Wed, 29 Nov 2023 16:40:18 +0000 Subject: [PATCH 4/4] Use :math: role and directive for formulae --- doc/ext-pake/api/pake.rst | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/doc/ext-pake/api/pake.rst b/doc/ext-pake/api/pake.rst index 730b696e..66781879 100644 --- a/doc/ext-pake/api/pake.rst +++ b/doc/ext-pake/api/pake.rst @@ -106,19 +106,16 @@ 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, corresponding to the w1 value in the key pair. +The public key consists of the two values :math:`w0` and :math:`L`, which result from the SPAKE2+ registration phase. :math:`w0` is a scalar in the same range as a private Elliptic curve key from the group used as the SPAKE2+ primitive group. :math:`L` is a point on the curve, similar to a public key from the same group, corresponding to the :math:`w1` value in the key pair. -For the |API|, the default format for a SPAKE2+ public key is the concatenation of the formatted values for w0 and L, using the standard formats for Elliptic curve keys used by the |API|. For example, for SPAKE2+ over P-256 (secp256r1), the output from :code:`psa_export_public_key()` would be the concatenation of: +For the |API|, the default format for a SPAKE2+ public key is the concatenation of the formatted values for :math:`w0` and :math:`L`, using the standard formats for Elliptic curve keys used by the |API|. For example, for SPAKE2+ over P-256 (secp256r1), the output from :code:`psa_export_public_key()` would be the concatenation of: -* The 32-byte formatted value of the P-256 private key w0. This is a big-endian encoding of the integer w0. -* The 65-byte formatted value of the P-256 public key L. This is itself a concatenation of: +* The 32-byte formatted value of the P-256 private key :math:`w0`. This is a big-endian encoding of the integer :math:`w0`. +* The 65-byte formatted value of the P-256 public key :math:`L`. This is itself a concatenation of: - The byte ``0x04``. - - The 32-byte big-endian encoding of the x-coordinate of L. - - The 32-byte big-endian encoding of the y-coordinate of L. - -.. 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). + - The 32-byte big-endian encoding of the x-coordinate of :math:`L`. + - The 32-byte big-endian encoding of the y-coordinate of :math:`L`. Changes and additions to the Programming API -------------------------------------------- @@ -159,7 +156,7 @@ The SPAKE2+ algorithms are based on Elliptic curve groups, and a SPAKE2+ key is .. param:: curve A value of type :code:`psa_ecc_family_t` that identifies the Elliptic curve family to be used. - 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. + The size of a SPAKE2+ key is the size associated with the Elliptic curve group, that is, :math:`\lceil{log_2(q)}\rceil` for a curve over a field :math:`\mathbb{F}_q`. See the documentation of each Elliptic curve family for details. To construct a SPAKE2+ key pair, it must be output from a key derivation operation. See :secref:`spake2p-key-derivation`. @@ -266,15 +263,15 @@ The key derivation process in :code:`psa_key_derivation_output_key()` follows th 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 following sizes are used for extracting w0s and w1s, depending on the elliptic curve: +* The derivation of SPAKE2+ keys extracts :math:`\lceil{log_2(p)/8}\rceil+8` bytes from the PBKDF for each of :math:`w0s` and :math:`w1s`, where :math:`p` is the prime factor of the order of the elliptic curve group. + The following sizes are used for extracting :math:`w0s` and :math:`w1s`, depending on the elliptic curve: .. csv-table:: :header-rows: 1 :widths: auto :align: left - Elliptic curve, "Size of w0s and w1s, in bytes" + Elliptic curve, "Size of :math:`w0s` and :math:`w1s`, in bytes" P-256, 40 P-384, 56 P-521, 74 @@ -283,13 +280,13 @@ For the |API|: :issue:`I think these values are correct?` -* The calculation of w0, w1, and L then proceeds as described in the RFC. +* The calculation of :math:`w0`, :math:`w1`, and :math:`L` then proceeds as described in the RFC. .. admonition:: Implementation note - The values of w0 and w1 are required as part of the SPAKE2+ key pair. + The values of :math:`w0` and :math:`w1` are required as part of the SPAKE2+ key pair. - It is :scterm:`implementation defined` whether L is computed during key derivation, and stored as part of the key pair; or only computed when required from the key pair. + It is :scterm:`implementation defined` whether :math:`L` is computed during key derivation, and stored as part of the key pair; or only computed when required from the key pair. .. _pake-algorithms: