From b59344948c1c834a1bc1478993c4d21b2a26914c Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Fri, 3 Nov 2023 12:14:12 +0000 Subject: [PATCH 01/14] 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 | 5 + 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, 253 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 479b58a9..4b3f017c 100644 --- a/doc/ext-pake/api/pake.rst +++ b/doc/ext-pake/api/pake.rst @@ -48,6 +48,77 @@ The defined values for PAKE-TYPE are shown in :numref:`table-pake-type`. PAKE algorithm, PAKE-TYPE, Algorithm identifier, Algorithm value J-PAKE, ``0x01``, `PSA_ALG_JPAKE`, ``0x0A000100`` +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 -------------------------------------------- @@ -61,6 +132,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 d90e278b..07a527d8 100644 --- a/doc/ext-pake/appendix/history.rst +++ b/doc/ext-pake/appendix/history.rst @@ -14,6 +14,11 @@ This section provides the detailed changes made between published version of the Changes between *Beta 1* and *Beta 2* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +API changes +~~~~~~~~~~~ + +* 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 d13eb041..68581c43 100644 --- a/doc/ext-pake/appendix/specdef_values.rst +++ b/doc/ext-pake/appendix/specdef_values.rst @@ -22,3 +22,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 zcma)h1z40_&^CgiQqqXj14!5IQcE||QW8onurw?zOG>9KDI$V|pwdW#ASor?DM%^; z5-OmS@b99&<@aCT_bg}6GxwP}F=u8ku6x+D6_xqG{K5om)teAjeW< zRKifg<-<3|ja;+JjM8h-+xh0FoMEeb=1PajkpYEoIAVhijm7-)=7pTMesnKhN`6NM zv6XPN@_QDzR(fbgEbrODR;Lr@&7H%v+mw77$AYU~qa3w$LnqFHTkX2ryVoR^F`?6|NCpy1Q z+mL6GxBC{>C9SM+F>jT>>*A&U0MhArH+;X!Vx@1<6r(yO!#^JI$hl9wu&lb+QeA|4 zv~BqZbj4_ z6WbQWYv)~Go$u>Rk7oQH5Wromf89Ff4I3}mAi?&SFcA_1W5=n7C%bfs2h4H zOzZ%Xl2`!q2*5xX0T57-1HgcQ6%6x@i73p#&u;-`gbV5)+BSS3J`f=CJ0dYkn7?0( zLH=3{5YYE=g#!ZGFk3jl27u2N*M=eCn7P2eZ3Q&p*7h)Ygg0;p1AzbtM3`Sx7=VcK zLqQNQL?Vv zkRI^gk^)9c5$`8G>t(UpD7HYy|A3PA3l5&=3mf}lK&#clM zeei(#`K@LNL5bVbxN3(8!_3Cg?EtT)?IZvAdgZIk)^cx1L)*V7SdGf4OYZ4~H4w;K zAMMlFDxSO?9|ZKB@e14D?=~sisA1}EfrgWwzHTa*Vc&-CT$zuorm?tEAGkf$e*B<0 znT$ZV#RMs%0X16*Hnii2q5H=4xXvT8P4fJ*6^JoaTv9qY;Q9CSF@Z$O$qH64wU!AM zn_-eytlSQ}=GJV(OK-`&r0#6Hr{orv5?`m6Pv((rR)tR`*d$!gG~Ounu6y8HvWkL# z{=nvvaWpA|foFV-4e}C2Sm-_G6i_V#EZL%lDuoQ6ET*+3QLvnTGqqo`fpy8p@lvV= z?j~V~CTV{#3{GJ5;!Y}6eBV7$R*N!nz0ms#q?*Bf5%W=zKniIhv02sqzJrDl3Xi5xsSKMZQM9YG>Pd6)r~%V?eczrS=2$k z`BAyh*ijMBretrj)B77?7DS1#4I<_UxvKaC!l>esLx&Vx{{mm|M5Br|E^UF|<(6PM z9X9f}D#eAI8_b@(lN_M6byN#op0s@?7oQ&Y-6iJ7}c4 z(&&lo<#{(bpV>dxR9SzQ!?|>uJ#f$Ai@EtV2LH?T=KfT7o20}KHUNXWmjJUCM~*|4@vY;_1UxHc_>i#!u!5I^TlVa91L~_L8!Tos^r zZc?BBWlcJDYt&USEpf4t(X7Rjz5^OtpL6*6T3;@GZn#W=iVy?a3=i(Wg?Pc1jB5q) zV$yRf2e*7UxSIS{ebrU zJzO>ZnHzVa469#{bF`dGe0On_d+<3EBExWNmfxG+w7xQ)vbjCtI#X&?vD1a zvChv5dakJW+8oYBM#N>xK)t>7+-GVEnwkono%_>Bu8_p#Ip%m+rS?sU7l=riP2X)> zuD1~gyOWtVEh$mwyZ3%$CH3R&RvH^GsQ`s-!?cJ_JvtI=h3t)B;({;P>`xUVJ!`7t zZQ2$$?C#DCWOG)34QSEAn|g}Zm|oD%IWeNW?Ph3@MKb&PQ5BPUxN#>zCx_hm9vp`1 zPuVz0VL+ALXI#TdGKGU-9#I_!SKM*mPU?%v z$c4{q39>N|zB13DO`LZ-Tygp|5n8b1fByySc<0sOK|mx$^JqQKBq{CeLyawZhsqR1 z8C$B7m+`Y-G`CEU^H%lBTC+aAkCz@5Q|$#82yfk^ICb57UC`z@xuq4^K38NoegH0+ z-PyOM8UILWA#v_-R#uQxxz5AC(fLIY`C^1@>`au%0x^EBd#KR@U&@CmxpA-8>n)d5*L5=2~Q8$_L**3>Id@or$v}N8#Qk7Giw%7fXqm#K!vD2|usZ8++ zB{QFIToHHn`JmTCjn{bQA`wN%EsIRhEjlah{Gm@Sgbd+AFn&;E`j9=7 zOnIAW3jB@fwmDhqU*M*GV z$_Dg#1eDYrP|_GyM%m5ASd~3(%;)B9Y}w-=&Cq?@?OE_6n#Z%`?giB^QwFrQGfyTo z=DU8BGTxRDbjwIWU3kY}82cdt(I_%pbr7BQKyYo1_A9+8y$erf{=h(b(@B@t7Gtr! zD!%BU!lJh0$#>BYxgs^SlH_8sW8&K^3!gbx-^Mu%{YX^{b0`F4-s)Vq_+g8jTu!=7 z;u%$4@z!jPpSipxUl-9igPl1xU*R2v@kzzOPuzLTir-zIcHWi06E#Yy0M;K-dypFg z8pHEy4t^r>B~+l4u3`JdGE+e9=Bh`z`}|>ozQA#aM78J2#$1#wqF;(^#?R^-&rQ3% z-e};-`LD*qsWF5$#a#~B0iETpDZ#nQjlg)J56LiPpPRuoGGlZ$ygGx(vE>@$cu$T$ zK39^L6F_lvo;w+yz+I`VnU>gP7Da8l-lj&#dcEm0#nV2SmJD%Ir+ww}b)kFNJyrf+ z4AW`9%HsY2Ew|n~yiq;4MhZ=8xvY?@CHh=k76_@jnAcLiDfvR0bn;c0&80)-7t5^? zj#Ys@X1EHi{6&dCPw36vAKN0Zb;^qJR1r2?yDN)1Au`jlc(1O#q;T@-p3krz)HiUV z|KYuLWo2+%?6d8Z-^%XAgX)l8V;ve*m#GJJ2i4P>XK zU-Cw>i?jznXZDz%><%u=?yX{GU+dJPNB3~fXQ(G7bp^-pQgX4f=sz@-jTpb)rt3Q- z;JoU=p)(LaLSBnx&Sy8A&6@YT-t|>8rak{rB#DaDBD(~2?VkDf=-j(BTMdT!r3d21 zJC8bUsEo@THW-w4Y`>m~9(?6cr?=ykko`V+O$1UqfL}cSV%^`asxT`b^4t;#6?jT zMg)m@7C&6&V}o;|7p`3pc4CSx6k=6~D?x<#2*eaTf~}Ojb1dKA*bhbDJ`EkD(A}MA zcU%@$B5ad9&1$Z}J(XB2s>iKn2w2JG?!9p|C5~|HKQ8x9ubY|Q`mz6{Rxi2mpw!{Z z8o8eo{wu2?>b7{H7t=iz_`}uKlgCA`Ynct0HIdUsS+VV_-#k1Q-te38cF31e?C=vo zh3|LJEs|u%Rk0zDmmW3^lIP;3Fl3xco*Yqt$I_yi82OTV5kHo!Sf5YykmHE#UOZrs1|t)3=; zB`-7^B^6~j@z5dUifpFC(CZ^1#~$4*eC1m%94~nt-kXGzb1AP&JEkQxKOG>IML_nIaLodcQ?9@~MaH=P1ZQw!ge zshj3Cw5z`duPpv>jDHuN5TUOeUQS&2x+t4i{==Ybh6g3zlCw9_Ji0lIi5ZdT)loLZ zT|#Z1uuem>wq3AFG>0ZE3&?BQir6!=`td;K>VP+mOz@NTyv6O9lke=ujp6f$V;Lg; zGS_kPZ7-k^dy%=lGM?3$Pn#7D^Ox23W-jL{I($>;YK)oNE66)J{djtKK=O)-@z6gJ zpM9&o4?)VExjZ1(xNn+#=h)*5IE<2#f`hUg#KmK0jY3G5Sfr3XoV-CP(qIa^=ozE7 zuwD7=DFg!H=1TRG)%Ue4<#<9vwbL>cMxL#(6O>;yqQ#Tr?QgB0PHAiVMzI3|xgA7% zzr@&1K=p37d=?HrjkdPXlgYt|HdPI>_r6e%@Ywd0B51)+H)rDU07jenS~^bI|!YFY`~zF zTGimQQ32D?_qJzoJFau2=@5PGxJ~0kIEkdvmZ7Vb+}ch8$3lKBOM8M5ju}m{K}r;G# z+P0LT(GMc~(%9?PeeDKRLu(7wwXbP z87cHy-dT`{WB$?Mi8Ff2O=ZY!Xmp|bO>ir18f(`iCwn_H7149I9~&D9lGo!mb;{DE z%rA=)U!h;Xt=yMg`+U>%mMd!8NuIi6jMvpo;05}!hp9evA>!Fn-K^vRC)!4woSLh( zEn&ui(rFjeA0sUw4~-akIZa6V^s;J4Nc-OtP*k+8bh5Y1X}Iv>{J`xXPl$b8w;=Wv z$k)b~4jp69P46KzvMaWxdIsXu&Tyk7LJ4f(ZQ+3>TDH4id()0- zilf1#fh4!f^3-x*7u{2EybMdzPL~SS{oFu282g!WVfxA-r6gIkKZU8a?Qrz0XH`Z+ z4Eq$)n#>$r&FC>zKaSpTvhbhS4s* z$=%F7g>dwZt~6K9=JbA$^O7^Ii9C^xUe}@DYn@d%zPL+rfWEw5?M8-cBeS5IX&{M5 zD#;SAdTsYng9$V8^g?Ag^DyCr+TrHzYp)YYy2Xn%-`eQapRNYt1ePLJ|77W~WYKSy zPFNKBn>iEvlU4#_DY5?>>uY*n6A_AGeYX#&q&*|i@eu(km+aU1>Az){|G-hvptBF- ze17rd$5QS3bB30iW=F!E-20tv_*j^~#BlZQT{)ePK6raj5!@Fik9f44 zXq7!S8}q&NAAbZZ@~03k;q3(PclllCPgP%H*oiZOs4t=G&?auD=tK1hwzb5@#D*L# zdWEs?#oJLnjH){-CHD(f+WlAz`p``szDm9w?wzvgwWoY9Lbo={Z9R6ROQ5DMZ~2_Z zjr?Yt(-`VTb_n;+r55~oF=y`nbu)sXzb*!hWh;LZem`kOEFr20ceg^?yP^E1t`@N+s3OVkJTu?{*z%TuD5V4<^iQ%Uaw_NP8B^&^o{{Qs%pFxKu z(%sL_r*3bJJsp;7*Zqqj_rUV%|DdVC|D@uzkqB!KD@@sl(+XyfL;zrZun0d0;Iu=b zT;0V5Fq}UIwMD{Q?d+}G`4LE4uAkAVfGH|rA{>xZR#H|5frP|BAQ2@@lLvuB1u;Fg zfidqOOfL)qK`^}_MuuQ?Fhf6ktc-n!VstP~ROna3VAweX;f14k>Hbzer zGoc7(QHa=CnL^-foAwA7MQmAvQ&AiOf(U}ams|HeRKLYP?jHzq6s{=-&SL=Y3G|JD-$K`>GBUrgwa zy@+5g?Z0}WATTCof7_yvFwD;e@~mX3XYUKg`U?BAsEa^g!t!Sc1uLt%*kGdXEOLLA 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 09f5f55fd4bbe49cd8d3bc6b8ca90d9e1b8130d1 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Fri, 3 Nov 2023 16:11:32 +0000 Subject: [PATCH 02/14] Add a PAKE step for input and output of key confirmation --- doc/ext-pake/api.db/psa/crypto-pake.h | 3 ++- doc/ext-pake/api/pake.rst | 9 +++++++++ doc/ext-pake/appendix/history.rst | 5 +++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/doc/ext-pake/api.db/psa/crypto-pake.h b/doc/ext-pake/api.db/psa/crypto-pake.h index d27bce00..eadb43a3 100644 --- a/doc/ext-pake/api.db/psa/crypto-pake.h +++ b/doc/ext-pake/api.db/psa/crypto-pake.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2018-2022 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: Copyright 2018-2023 Arm Limited and/or its affiliates // SPDX-License-Identifier: Apache-2.0 typedef /* implementation-defined type */ psa_pake_cipher_suite_t; @@ -27,6 +27,7 @@ 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) diff --git a/doc/ext-pake/api/pake.rst b/doc/ext-pake/api/pake.rst index 479b58a9..6801cc91 100644 --- a/doc/ext-pake/api/pake.rst +++ b/doc/ext-pake/api/pake.rst @@ -652,6 +652,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: diff --git a/doc/ext-pake/appendix/history.rst b/doc/ext-pake/appendix/history.rst index d90e278b..1134a4fd 100644 --- a/doc/ext-pake/appendix/history.rst +++ b/doc/ext-pake/appendix/history.rst @@ -14,6 +14,11 @@ This section provides the detailed changes made between published version of the Changes between *Beta 1* and *Beta 2* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +API changes +~~~~~~~~~~~ + +* Add the `PSA_PAKE_STEP_CONFIRM` PAKE step for input and output of key confirmation values. + Clarifications ~~~~~~~~~~~~~~ From 3390fc85f1ac79a43650c6241010a7886ede2065 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Fri, 3 Nov 2023 16:21:28 +0000 Subject: [PATCH 03/14] Add psa_pake_set_context() --- doc/ext-pake/api.db/psa/crypto-pake.h | 3 +++ doc/ext-pake/api/pake.rst | 35 +++++++++++++++++++++++++++ doc/ext-pake/appendix/history.rst | 1 + 3 files changed, 39 insertions(+) diff --git a/doc/ext-pake/api.db/psa/crypto-pake.h b/doc/ext-pake/api.db/psa/crypto-pake.h index eadb43a3..32a52e5b 100644 --- a/doc/ext-pake/api.db/psa/crypto-pake.h +++ b/doc/ext-pake/api.db/psa/crypto-pake.h @@ -54,6 +54,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_password_key(psa_pake_operation_t *operation, psa_key_id_t password); psa_status_t psa_pake_set_peer(psa_pake_operation_t *operation, diff --git a/doc/ext-pake/api/pake.rst b/doc/ext-pake/api/pake.rst index 6801cc91..a2d07e0a 100644 --- a/doc/ext-pake/api/pake.rst +++ b/doc/ext-pake/api/pake.rst @@ -928,6 +928,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:: diff --git a/doc/ext-pake/appendix/history.rst b/doc/ext-pake/appendix/history.rst index 1134a4fd..12f34b58 100644 --- a/doc/ext-pake/appendix/history.rst +++ b/doc/ext-pake/appendix/history.rst @@ -18,6 +18,7 @@ API changes ~~~~~~~~~~~ * 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. Clarifications ~~~~~~~~~~~~~~ From 9d442835ed012a99ea469f3c7233fafb3fde50a1 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Mon, 13 Nov 2023 17:57:20 +0000 Subject: [PATCH 04/14] Parameterized the PAKE algorithm by a hash algorithm * 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. --- doc/ext-pake/api.db/psa/crypto-pake.h | 8 +- doc/ext-pake/api/pake.rst | 105 ++++++++--------------- doc/ext-pake/appendix/history.rst | 5 ++ doc/ext-pake/appendix/specdef_values.rst | 6 ++ doc/ext-pake/figure/pake_encoding.json | 4 +- doc/ext-pake/figure/pake_encoding.pdf | Bin 7568 -> 7894 bytes doc/ext-pake/figure/pake_encoding.svg | 2 +- 7 files changed, 54 insertions(+), 76 deletions(-) diff --git a/doc/ext-pake/api.db/psa/crypto-pake.h b/doc/ext-pake/api.db/psa/crypto-pake.h index d27bce00..f1248c84 100644 --- a/doc/ext-pake/api.db/psa/crypto-pake.h +++ b/doc/ext-pake/api.db/psa/crypto-pake.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2018-2022 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: Copyright 2018-2023 Arm Limited and/or its affiliates // SPDX-License-Identifier: Apache-2.0 typedef /* implementation-defined type */ psa_pake_cipher_suite_t; @@ -8,8 +8,9 @@ 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_JPAKE(hash_alg) /* specification-defined value */ #define PSA_PAKE_CIPHER_SUITE_INIT /* implementation-defined value */ #define PSA_PAKE_INPUT_MAX_SIZE /* implementation-defined value */ #define PSA_PAKE_INPUT_SIZE(alg, primitive, input_step) \ @@ -33,12 +34,9 @@ typedef uint8_t psa_pake_step_t; 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); 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_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, diff --git a/doc/ext-pake/api/pake.rst b/doc/ext-pake/api/pake.rst index 479b58a9..558daecf 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 KDF algorithm. + +.. + The permitted values of HASH-TYPE (see :numref:`table-hash-type`) depend on the specific KDF algorithm. + .. csv-table:: PAKE algorithm sub-type values :name: table-pake-type :header-rows: 1 @@ -46,7 +51,9 @@ 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` + +a. ``hh`` is the HASH-TYPE for the hash algorithm, ``hash``, used to construct the key derivation algorithm. Changes and additions to the Programming API -------------------------------------------- @@ -81,16 +88,25 @@ 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. + * A cryptographic hash function, ``hash_alg``. 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,10 +114,9 @@ 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_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); 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. @@ -345,7 +360,7 @@ 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. -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 and hash algorithm, and the PAKE primitive. A PAKE cipher suite is required when setting up a PAKE operation in `psa_pake_setup()`. @@ -358,8 +373,8 @@ 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. @@ -396,25 +411,6 @@ 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? - - .. rubric:: Usage - - A typical sequence to create a key is as follows: - - 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. - - A typical sequence to query a key's attributes is as follows: - - 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. .. macro:: PSA_PAKE_CIPHER_SUITE_INIT :definition: /* implementation-defined value */ @@ -496,43 +492,6 @@ 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 - - .. summary:: - Retrieve the hash algorithm 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. - - .. 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. - -.. function:: psa_pake_cs_set_hash - - .. summary:: - Declare the hash algorithm for 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. - - .. return:: void - - This function overwrites any hash algorithm previously set in ``cipher_suite``. - - The documentation of individual PAKE algorithms specifies which hash algorithms are compatible, or if no hash algorithm is required. - - .. 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. - .. _pake-roles: @@ -729,15 +688,13 @@ 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. .. 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. .. retval:: PSA_ERROR_COMMUNICATION_FAILURE .. retval:: PSA_ERROR_CORRUPTION_DETECTED @@ -1101,6 +1058,18 @@ Multi-part PAKE operations Support macros ~~~~~~~~~~~~~~ +.. macro:: PSA_ALG_IS_JPAKE + :definition: /* specification-defined value */ + + .. summary:: + Whether the specified algorithm is a J-PAKE algorithm (:code:`PSA_ALG_JPAKE(hash_alg)`). + + .. 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. + .. macro:: PSA_PAKE_OUTPUT_SIZE :definition: /* implementation-defined value */ diff --git a/doc/ext-pake/appendix/history.rst b/doc/ext-pake/appendix/history.rst index d90e278b..8d8f449f 100644 --- a/doc/ext-pake/appendix/history.rst +++ b/doc/ext-pake/appendix/history.rst @@ -14,6 +14,11 @@ This section provides the detailed changes made between published version of the Changes between *Beta 1* and *Beta 2* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Changes to the API +~~~~~~~~~~~~~~~~~~ + +* 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. + Clarifications ~~~~~~~~~~~~~~ diff --git a/doc/ext-pake/appendix/specdef_values.rst b/doc/ext-pake/appendix/specdef_values.rst index d13eb041..e204e8ad 100644 --- a/doc/ext-pake/appendix/specdef_values.rst +++ b/doc/ext-pake/appendix/specdef_values.rst @@ -15,9 +15,15 @@ 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_JPAKE(hash_alg) \ + ((psa_algorithm_t) (0x0a000100 | ((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 | \ 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.pdf b/doc/ext-pake/figure/pake_encoding.pdf index 11f2c48059da7690ae0c2b7df6eef1a49b87f3b2..33add152c634eeaf761c9e22be41e838c6630548 100644 GIT binary patch delta 6163 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 delta 5814 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 Ds|E)t 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 From 8982329f6169dbda75b09a2c71ceb30f1f550668 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Mon, 30 Oct 2023 19:40:10 +0000 Subject: [PATCH 05/14] pake: change the key output function * Replace psa_pake_get_implicit_key() with psa_pake_get_shared_key() * Add key confirmation attribute to the PAKE cipher suite --- doc/ext-pake/api.db/psa/crypto-pake.h | 12 +- doc/ext-pake/api/pake.rst | 269 +++++++++++++++++++++----- doc/ext-pake/appendix/history.rst | 3 + 3 files changed, 233 insertions(+), 51 deletions(-) diff --git a/doc/ext-pake/api.db/psa/crypto-pake.h b/doc/ext-pake/api.db/psa/crypto-pake.h index 7e0a3c7e..3fed8b94 100644 --- a/doc/ext-pake/api.db/psa/crypto-pake.h +++ b/doc/ext-pake/api.db/psa/crypto-pake.h @@ -11,6 +11,7 @@ typedef uint8_t psa_pake_step_t; #define PSA_ALG_IS_PAKE(alg) /* specification-defined value */ #define PSA_ALG_JPAKE ((psa_algorithm_t)0x0a000100) #define PSA_PAKE_CIPHER_SUITE_INIT /* implementation-defined value */ +#define PSA_PAKE_CONFIRMED_KEY 1 #define PSA_PAKE_INPUT_MAX_SIZE /* implementation-defined value */ #define PSA_PAKE_INPUT_SIZE(alg, primitive, input_step) \ /* implementation-defined value */ @@ -27,22 +28,29 @@ 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_SECRET_KEY_BITS(alg, primitive, hash_alg) \ + /* implementation-defined value */ #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 0 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, diff --git a/doc/ext-pake/api/pake.rst b/doc/ext-pake/api/pake.rst index ec1c5bbc..b2248d83 100644 --- a/doc/ext-pake/api/pake.rst +++ b/doc/ext-pake/api/pake.rst @@ -89,9 +89,11 @@ PAKE algorithms 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. + * 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. + 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: .. code-block:: xref @@ -196,18 +198,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. 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`. @@ -342,9 +345,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 cryptographic primitive used for 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 `psa_pake_cipher_suite_t` object is used to fully specify a PAKE operation, combining the PAKE algorithm, and the above parameters. A PAKE cipher suite is required when setting up a PAKE operation in `psa_pake_setup()`. @@ -359,11 +366,7 @@ A PAKE cipher suite is required when setting up a PAKE operation in `psa_pake_se * The PAKE algorithm itself. * 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 +398,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: auto + :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_UNCONFIRMED_KEY` --- requesting that the unconfirmed secret key is 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 - 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. + 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. .. macro:: PSA_PAKE_CIPHER_SUITE_INIT :definition: /* implementation-defined value */ @@ -532,6 +545,62 @@ 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. +.. macro:: PSA_PAKE_UNCONFIRMED_KEY + :definition: 0 + + .. 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. + +.. macro:: PSA_PAKE_CONFIRMED_KEY + :definition: 1 + + .. 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. + Some algorithms do not include confirmation of the shared key. + +.. function:: psa_pake_cs_get_key_confirmation + + .. summary:: + 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:: uint32_t + A key confirmation value: either `PSA_PAKE_UNCONFIRMED_KEY` or `PSA_PAKE_CONFIRMED_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. + +.. function:: psa_pake_cs_set_key_confirmation + + .. summary:: + 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:: uint32_t key_confirmation + The key confirmation value to write: either `PSA_PAKE_UNCONFIRMED_KEY` or `PSA_PAKE_CONFIRMED_KEY`. + + .. return:: void + + This function overwrites any key confirmation previously set in ``cipher_suite``. + + 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. .. _pake-roles: @@ -742,6 +811,7 @@ Multi-part PAKE operations * The algorithm in ``cipher_suite`` is not a PAKE 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 @@ -750,6 +820,7 @@ Multi-part PAKE operations * The algorithm in ``cipher_suite`` is not a supported PAKE 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 +842,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 +857,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 @@ -999,30 +1070,83 @@ 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 + + .. todo:: + + Decide whether `psa_pake_get_shared_key()` can be called only once (and this terminates the operation), or if the application can sequentially extract multiple keys from the shared secret (much like can be done with a key derivation operation). + + If there are no use cases for multiple key extraction, then we should keep it simple and have a successful key extraction result in terminating the operation. This is the currently described behavior. + + Related: Does all of the shared secret need to be used to construct the output 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 + + .. todo:: + Decide where this parameter should go - :code:`psa_key_derivation_output_key()` has this as 1st parameter, before the operation object. + + The attributes for the new key. + This function uses the attributes as follows: + + * The key type is required. It cannot be an asymmetric public key. :issue:`Should we place other restrictions - e.g. forbidding key types that consume a variable amount of input?` + * The key size is always determined from the PAKE shared secret. If the key size in ``attributes`` is nonzero, it must be equal to the size of the shared secret, in bits. + + The bit-size of the shared secret is :code:`PSA_PAKE_SECRET_KEY_BITS(alg, primitive, hash_alg)`, where ``alg``, ``primitive``, and ``hash_alg`` are the PAKE algorithm, primitive, and hash in the operation's cipher suite. + + * 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_INSUFFICIENT_DATA + There was not enough data to create the desired key. :issue:`Is this the appropriate error for this condition?` .. 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 a PAKE output. + * The key size is nonzero, and is not the size of the shared secret. + * The key lifetime is invalid. + * The key identifier is not valid for the key lifetime. + * The key usage flags include invalid values. + * The key's permitted-usage algorithm is invalid. + * The key attributes, as a whole, are invalid. + .. retval:: PSA_ERROR_NOT_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,12 +1154,37 @@ 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. + This key can be used directly in cryptographic operations such as encryption, but is more typically used as an input to key derivation operations to produce additional cryptographic keys. + + 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 - 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. + * - **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. + + 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 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. 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. @@ -1046,7 +1195,7 @@ Multi-part PAKE operations 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,7 +1219,7 @@ 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 @@ -1143,3 +1292,25 @@ Support macros This macro can be useful when transferring inputs from the peer into the PAKE operation. See also `PSA_PAKE_INPUT_SIZE()`. + +.. macro:: PSA_PAKE_SECRET_KEY_BITS + :definition: /* implementation-defined value */ + + .. summary:: + The size of the secret key output from a PAKE algorithm, in bits. + + .. param:: alg + A PAKE algorithm: a value of type :code:`psa_algorithm_t` such that :code:`PSA_ALG_IS_PAKE(alg)` is true. + .. param:: primitive + A primitive of type `psa_pake_primitive_t` that is compatible with algorithm ``alg``. + .. param:: hash_alg + A hash algorithm: value of type :code:`psa_algorithm_t` such that :code:`PSA_ALG_IS_HASH(alg)` is true. + + .. return:: + The size, in bits, of the shared secret produced by the specified PAKE algorithm, primitive, and associated hash algorithm. + An implementation can return either ``0`` or a correct size for a PAKE algorithm, primitive, and hash algorithm that it recognizes, but does not support. + If the parameters are not valid, the return value is unspecified. + + When extracting the shared secret using `psa_pake_get_shared_key()`, the application is not required to set the key size in the attributes. + + :issue:`Do we actually need this, if the only option is to extract all of the bits into the key?` diff --git a/doc/ext-pake/appendix/history.rst b/doc/ext-pake/appendix/history.rst index 8b22b27e..2ee4f4ef 100644 --- a/doc/ext-pake/appendix/history.rst +++ b/doc/ext-pake/appendix/history.rst @@ -19,6 +19,9 @@ API changes * 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. +* 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`. + Clarifications ~~~~~~~~~~~~~~ From 8fb03e41b1b945860e6b9377d0d61d95dbf19e29 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Tue, 31 Oct 2023 17:19:23 +0000 Subject: [PATCH 06/14] Update J-PAKE flow graphic --- doc/ext-pake/figure/j-pake.pdf | Bin 29446 -> 29304 bytes doc/ext-pake/figure/j-pake.pdf.license | 2 +- doc/ext-pake/figure/j-pake.puml | 4 ++-- doc/ext-pake/figure/j-pake.svg | 2 +- doc/ext-pake/figure/j-pake.svg.license | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/ext-pake/figure/j-pake.pdf b/doc/ext-pake/figure/j-pake.pdf index 96a090f51306715e73b0bfff7d06e75c4d2aff58..ab7a94f50c9298d46f7f1f706b3ce4376075cbf7 100644 GIT binary patch delta 11819 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 ALI3~& 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 From 65dab7291b31c360fcf1cb2b5b1d537ca86288ae Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Tue, 31 Oct 2023 17:31:35 +0000 Subject: [PATCH 07/14] Reversed the definitions for PAKE key confirmation values --- doc/ext-pake/api.db/psa/crypto-pake.h | 4 +-- doc/ext-pake/api/pake.rst | 35 +++++++++++++++------------ 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/doc/ext-pake/api.db/psa/crypto-pake.h b/doc/ext-pake/api.db/psa/crypto-pake.h index 3fed8b94..07c62911 100644 --- a/doc/ext-pake/api.db/psa/crypto-pake.h +++ b/doc/ext-pake/api.db/psa/crypto-pake.h @@ -11,7 +11,7 @@ typedef uint8_t psa_pake_step_t; #define PSA_ALG_IS_PAKE(alg) /* specification-defined value */ #define PSA_ALG_JPAKE ((psa_algorithm_t)0x0a000100) #define PSA_PAKE_CIPHER_SUITE_INIT /* implementation-defined value */ -#define PSA_PAKE_CONFIRMED_KEY 1 +#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 */ @@ -33,7 +33,7 @@ typedef uint8_t psa_pake_step_t; #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 0 +#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); diff --git a/doc/ext-pake/api/pake.rst b/doc/ext-pake/api/pake.rst index b2248d83..ab18dbca 100644 --- a/doc/ext-pake/api/pake.rst +++ b/doc/ext-pake/api/pake.rst @@ -100,10 +100,11 @@ 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); + 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_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. @@ -402,7 +403,7 @@ A PAKE cipher suite is required when setting up a PAKE operation in `psa_pake_se .. list-table:: :header-rows: 1 - :widths: auto + :widths: 1 4 :align: left * - Attribute @@ -415,7 +416,7 @@ A PAKE cipher suite is required when setting up a PAKE operation in `psa_pake_se * - hash - :code:`PSA_ALG_NONE` --- an invalid algorithm identifier. * - key confirmation - - `PSA_PAKE_UNCONFIRMED_KEY` --- requesting that the unconfirmed secret key is returned. + - `PSA_PAKE_CONFIRMED_KEY` --- requesting that the secret key is confirmed before it can be returned. The algorithm and primitive values must be set for all PAKE algorithms, the hash and key confirmation values are required for some PAKE algorithms. @@ -545,26 +546,28 @@ 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. -.. macro:: PSA_PAKE_UNCONFIRMED_KEY +.. 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. -.. macro:: PSA_PAKE_CONFIRMED_KEY - :definition: 1 - - .. 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. - Some algorithms do not include confirmation of the shared key. - .. function:: psa_pake_cs_get_key_confirmation .. summary:: @@ -574,7 +577,7 @@ A PAKE cipher suite is required when setting up a PAKE operation in `psa_pake_se The cipher suite object to query. .. return:: uint32_t - A key confirmation value: either `PSA_PAKE_UNCONFIRMED_KEY` or `PSA_PAKE_CONFIRMED_KEY`. + A key confirmation value: either `PSA_PAKE_CONFIRMED_KEY` or `PSA_PAKE_UNCONFIRMED_KEY`. .. admonition:: Implementation note @@ -589,7 +592,7 @@ A PAKE cipher suite is required when setting up a PAKE operation in `psa_pake_se .. param:: psa_pake_cipher_suite_t* cipher_suite The cipher suite object to write to. .. param:: uint32_t key_confirmation - The key confirmation value to write: either `PSA_PAKE_UNCONFIRMED_KEY` or `PSA_PAKE_CONFIRMED_KEY`. + The key confirmation value to write: either `PSA_PAKE_CONFIRMED_KEY` or `PSA_PAKE_UNCONFIRMED_KEY`. .. return:: void From 4fe9d498289cb8f4f227e65545be28f9dfc7e68c Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Wed, 1 Nov 2023 10:38:47 +0000 Subject: [PATCH 08/14] Fix typo --- doc/ext-pake/api/pake.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ext-pake/api/pake.rst b/doc/ext-pake/api/pake.rst index ab18dbca..8d4829cf 100644 --- a/doc/ext-pake/api/pake.rst +++ b/doc/ext-pake/api/pake.rst @@ -346,9 +346,9 @@ A PAKE primitive is required when constructing a PAKE cipher-suite object, `psa_ PAKE cipher suites ~~~~~~~~~~~~~~~~~~ -Most PAKE algorithms have parameters that must be specified by the application. These parameters include: +Most PAKE algorithms have parameters that must be specified by the application. These parameters include the following: -* The cryptographic primitive used for for key establishment, specified using a `PAKE primitive `. +* 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. From 2e780a92caa78d0b295121320b655d0d65e394b9 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Wed, 1 Nov 2023 10:40:22 +0000 Subject: [PATCH 09/14] Tidy up resolved issues. --- doc/ext-pake/api/pake.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/doc/ext-pake/api/pake.rst b/doc/ext-pake/api/pake.rst index 8d4829cf..0ef2eeb3 100644 --- a/doc/ext-pake/api/pake.rst +++ b/doc/ext-pake/api/pake.rst @@ -1089,10 +1089,6 @@ Multi-part PAKE operations .. param:: psa_pake_operation_t *operation Active PAKE operation. .. param:: const psa_key_attributes_t * attributes - - .. todo:: - Decide where this parameter should go - :code:`psa_key_derivation_output_key()` has this as 1st parameter, before the operation object. - The attributes for the new key. This function uses the attributes as follows: @@ -1134,8 +1130,6 @@ Multi-part PAKE operations * The library requires initializing by a call to :code:`psa_crypto_init()`. .. 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_INSUFFICIENT_DATA - There was not enough data to create the desired key. :issue:`Is this the appropriate error for this condition?` .. retval:: PSA_ERROR_NOT_SUPPORTED 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 From 0540976486307a5305a7648e0f55b5b6c01e351f Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Mon, 13 Nov 2023 15:21:50 +0000 Subject: [PATCH 10/14] Removed uncertainty about behavior or psa_pake_get_shared_key() * The shared secret is always output as a single key * Removed the input key size, key size is determined by operation * Removed key-size helper macro as unnecessary --- doc/ext-pake/api.db/psa/crypto-pake.h | 2 -- doc/ext-pake/api/pake.rst | 40 ++------------------------- 2 files changed, 3 insertions(+), 39 deletions(-) diff --git a/doc/ext-pake/api.db/psa/crypto-pake.h b/doc/ext-pake/api.db/psa/crypto-pake.h index 07c62911..89381d55 100644 --- a/doc/ext-pake/api.db/psa/crypto-pake.h +++ b/doc/ext-pake/api.db/psa/crypto-pake.h @@ -28,8 +28,6 @@ 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_SECRET_KEY_BITS(alg, primitive, hash_alg) \ - /* implementation-defined value */ #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) diff --git a/doc/ext-pake/api/pake.rst b/doc/ext-pake/api/pake.rst index 0ef2eeb3..446fe0f1 100644 --- a/doc/ext-pake/api/pake.rst +++ b/doc/ext-pake/api/pake.rst @@ -1075,14 +1075,6 @@ Multi-part PAKE operations .. function:: psa_pake_get_shared_key - .. todo:: - - Decide whether `psa_pake_get_shared_key()` can be called only once (and this terminates the operation), or if the application can sequentially extract multiple keys from the shared secret (much like can be done with a key derivation operation). - - If there are no use cases for multiple key extraction, then we should keep it simple and have a successful key extraction result in terminating the operation. This is the currently described behavior. - - Related: Does all of the shared secret need to be used to construct the output key? - .. summary:: Extract the shared secret from the PAKE as a key. @@ -1092,11 +1084,8 @@ Multi-part PAKE operations The attributes for the new key. This function uses the attributes as follows: - * The key type is required. It cannot be an asymmetric public key. :issue:`Should we place other restrictions - e.g. forbidding key types that consume a variable amount of input?` - * The key size is always determined from the PAKE shared secret. If the key size in ``attributes`` is nonzero, it must be equal to the size of the shared secret, in bits. - - The bit-size of the shared secret is :code:`PSA_PAKE_SECRET_KEY_BITS(alg, primitive, hash_alg)`, where ``alg``, ``primitive``, and ``hash_alg`` are the PAKE algorithm, primitive, and hash in the operation's cipher suite. - + * The key type is required. It must be an unstructured key type that can be constructed directly from the PAKE shared secret. For example, :code:`PSA_KEY_TYPE_DERIVE`, :code:`PSA_KEY_TYPE_HMAC`, or :code:`PSA_KEY_TYPE_AES`. + * 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`. @@ -1110,7 +1099,6 @@ Multi-part PAKE operations .. 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. @@ -1136,7 +1124,7 @@ Multi-part PAKE operations The following conditions can result in this error: * The key type is not valid for a PAKE output. - * The key size is nonzero, and is not the size of the shared secret. + * 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. @@ -1289,25 +1277,3 @@ Support macros This macro can be useful when transferring inputs from the peer into the PAKE operation. See also `PSA_PAKE_INPUT_SIZE()`. - -.. macro:: PSA_PAKE_SECRET_KEY_BITS - :definition: /* implementation-defined value */ - - .. summary:: - The size of the secret key output from a PAKE algorithm, in bits. - - .. param:: alg - A PAKE algorithm: a value of type :code:`psa_algorithm_t` such that :code:`PSA_ALG_IS_PAKE(alg)` is true. - .. param:: primitive - A primitive of type `psa_pake_primitive_t` that is compatible with algorithm ``alg``. - .. param:: hash_alg - A hash algorithm: value of type :code:`psa_algorithm_t` such that :code:`PSA_ALG_IS_HASH(alg)` is true. - - .. return:: - The size, in bits, of the shared secret produced by the specified PAKE algorithm, primitive, and associated hash algorithm. - An implementation can return either ``0`` or a correct size for a PAKE algorithm, primitive, and hash algorithm that it recognizes, but does not support. - If the parameters are not valid, the return value is unspecified. - - When extracting the shared secret using `psa_pake_get_shared_key()`, the application is not required to set the key size in the attributes. - - :issue:`Do we actually need this, if the only option is to extract all of the bits into the key?` From 2774133f6311ad47ef469978c154d422e21912ef Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Mon, 13 Nov 2023 15:22:26 +0000 Subject: [PATCH 11/14] Removed redundant (legacy) paragraph --- doc/ext-pake/api/pake.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/ext-pake/api/pake.rst b/doc/ext-pake/api/pake.rst index 446fe0f1..f7429a86 100644 --- a/doc/ext-pake/api/pake.rst +++ b/doc/ext-pake/api/pake.rst @@ -1171,10 +1171,6 @@ Multi-part PAKE operations .. note:: Some PAKE algorithms do not include any key-confirmation steps. - 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. - 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`. From 9d4f2c06cc737e029d19d3fb24e777daef8ea761 Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Tue, 14 Nov 2023 11:53:15 +0000 Subject: [PATCH 12/14] Specify key types output by psa_pake_get_shared_key() * Recognise that not all PAKE algorithms produce a secret that is suitable for use as an encryption key * Encourage the use of PAKE output as a key-derivation key --- doc/ext-pake/api/pake.rst | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/doc/ext-pake/api/pake.rst b/doc/ext-pake/api/pake.rst index f7429a86..94cc3dc3 100644 --- a/doc/ext-pake/api/pake.rst +++ b/doc/ext-pake/api/pake.rst @@ -119,7 +119,11 @@ PAKE algorithms 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. @@ -199,7 +203,7 @@ PAKE algorithms // Set r6, the ZKP proof for x4*s psa_pake_input(&jpake, PSA_PAKE_STEP_ZK_PROOF, ...); - #. To use the shared secret, extract it as a key. For example, to extract a derivation key for HKDF-SHA-256: + #. 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 @@ -1084,8 +1088,14 @@ Multi-part PAKE operations The attributes for the new key. This function uses the attributes as follows: - * The key type is required. It must be an unstructured key type that can be constructed directly from the PAKE shared secret. For example, :code:`PSA_KEY_TYPE_DERIVE`, :code:`PSA_KEY_TYPE_HMAC`, or :code:`PSA_KEY_TYPE_AES`. - * The key size in ``attributes`` must be zero. The returned key size is always determined from the PAKE shared secret. + * 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`. @@ -1123,7 +1133,7 @@ Multi-part PAKE operations .. retval:: PSA_ERROR_INVALID_ARGUMENT The following conditions can result in this error: - * The key type is not valid for a PAKE output. + * 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. @@ -1140,7 +1150,9 @@ Multi-part PAKE operations .. retval:: PSA_ERROR_DATA_INVALID This is the final call in a PAKE operation, which retrieves the shared secret as a key. - This key can be used directly in cryptographic operations such as encryption, but is more typically used as an input to key derivation operations to produce additional cryptographic keys. + 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: From 4f3c56fc7a1248373a2458a04566c3d7408e1d9a Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Wed, 15 Nov 2023 10:53:43 +0000 Subject: [PATCH 13/14] Update copyrights --- doc/ext-pake/figure/pake_encoding.json.license | 2 +- doc/ext-pake/figure/pake_encoding.pdf.license | 2 +- doc/ext-pake/figure/pake_encoding.svg.license | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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.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.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 From e784de8ef06984d518e00d139e2a22fe0effdcbb Mon Sep 17 00:00:00 2001 From: Andrew Thoelke Date: Wed, 15 Nov 2023 21:45:21 +0000 Subject: [PATCH 14/14] Added SPAKE2+ algorithms * Supporting both RFC 9393 and Matter * New APIs: - `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()` --- doc/ext-pake/api.db/psa/crypto-pake.h | 15 + doc/ext-pake/api/pake.rst | 440 +++++++++++++++++- doc/ext-pake/appendix/history.rst | 9 + doc/ext-pake/appendix/specdef_values.rst | 15 + doc/ext-pake/figure/spake2plus-reg.pdf | Bin 0 -> 41372 bytes .../figure/spake2plus-reg.pdf.license | 2 + doc/ext-pake/figure/spake2plus-reg.puml | 41 ++ doc/ext-pake/figure/spake2plus-reg.svg | 1 + .../figure/spake2plus-reg.svg.license | 2 + doc/ext-pake/figure/spake2plus.pdf | Bin 0 -> 39114 bytes doc/ext-pake/figure/spake2plus.pdf.license | 2 + doc/ext-pake/figure/spake2plus.puml | 54 +++ doc/ext-pake/figure/spake2plus.svg | 1 + doc/ext-pake/figure/spake2plus.svg.license | 2 + doc/ext-pake/references | 20 +- 15 files changed, 585 insertions(+), 19 deletions(-) create mode 100644 doc/ext-pake/figure/spake2plus-reg.pdf create mode 100644 doc/ext-pake/figure/spake2plus-reg.pdf.license create mode 100644 doc/ext-pake/figure/spake2plus-reg.puml create mode 100644 doc/ext-pake/figure/spake2plus-reg.svg create mode 100644 doc/ext-pake/figure/spake2plus-reg.svg.license create mode 100644 doc/ext-pake/figure/spake2plus.pdf create mode 100644 doc/ext-pake/figure/spake2plus.pdf.license create mode 100644 doc/ext-pake/figure/spake2plus.puml create mode 100644 doc/ext-pake/figure/spake2plus.svg create mode 100644 doc/ext-pake/figure/spake2plus.svg.license diff --git a/doc/ext-pake/api.db/psa/crypto-pake.h b/doc/ext-pake/api.db/psa/crypto-pake.h index 21a84e9c..5023b79a 100644 --- a/doc/ext-pake/api.db/psa/crypto-pake.h +++ b/doc/ext-pake/api.db/psa/crypto-pake.h @@ -10,7 +10,22 @@ 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_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 */ diff --git a/doc/ext-pake/api/pake.rst b/doc/ext-pake/api/pake.rst index 77824bf3..4ac49806 100644 --- a/doc/ext-pake/api/pake.rst +++ b/doc/ext-pake/api/pake.rst @@ -39,10 +39,10 @@ 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 KDF algorithm. +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 KDF 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 @@ -52,6 +52,9 @@ The permitted values of HASH-TYPE depend on the specific KDF algorithm. PAKE algorithm, PAKE-TYPE, Algorithm identifier, Algorithm value 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. @@ -110,21 +113,44 @@ The public key consists of the two values w0 and L, which result from the SPAKE2 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` + [ 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? + 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? + 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). + 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 -------------------------------------------- @@ -169,7 +195,9 @@ 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. + | `PSA_ALG_SPAKE2P_HMAC` + | `PSA_ALG_SPAKE2P_CMAC` + | `PSA_ALG_SPAKE2P_MATTER` .. macro:: PSA_KEY_TYPE_SPAKE2P_PUBLIC_KEY :definition: /* specification-defined value */ @@ -184,7 +212,9 @@ 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. + | `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 */ @@ -225,8 +255,10 @@ 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. -Key derivation of SPAKE2+ keys -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. _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. @@ -252,7 +284,8 @@ For example, after setting up the PBKDF2 operation, the following process will d 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()?` + .. 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: @@ -327,12 +360,18 @@ PAKE algorithms 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`. @@ -347,7 +386,7 @@ PAKE algorithms 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 @@ -455,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: @@ -983,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. @@ -1278,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: @@ -1446,7 +1807,7 @@ Support macros :definition: /* specification-defined value */ .. summary:: - Whether the specified algorithm is a J-PAKE algorithm (:code:`PSA_ALG_JPAKE(hash_alg)`). + Whether the specified algorithm is a J-PAKE algorithm. .. param:: alg An algorithm identifier: a value of type :code:`psa_algorithm_t`. @@ -1454,6 +1815,50 @@ Support macros .. 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 */ @@ -1511,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 067f5614..90cfad58 100644 --- a/doc/ext-pake/appendix/history.rst +++ b/doc/ext-pake/appendix/history.rst @@ -36,6 +36,15 @@ Changes to the API * 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: + + - `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 3210b0de..66d7f0d0 100644 --- a/doc/ext-pake/appendix/specdef_values.rst +++ b/doc/ext-pake/appendix/specdef_values.rst @@ -21,9 +21,24 @@ The examples here provide correct results for the valid inputs defined by each A #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 | \ diff --git a/doc/ext-pake/figure/spake2plus-reg.pdf b/doc/ext-pake/figure/spake2plus-reg.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7140f56066fde4cee1d1a2e8c07c53d1a8b9bf05 GIT binary patch literal 41372 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 b)1Q0F6OX~+w{{c^1Ymd3i;8L;*QWmudKQmB literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..aba6461a955029b1c3f2fb1e31ada9d8c3c941fd GIT binary patch literal 39114 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 h5f;w~bh|tp +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/