lsd0012

LSD0012: CORE Authenticated Key Exchange (CAKE)
Log | Files | Refs

commit 6a2cf3bd7f4d9582244ae0985e0afc6ad0ebe08c
parent b9b97be40e1998afb849cbc074602f74d6d26c3a
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date:   Wed, 13 Nov 2024 22:57:40 +0100

pass through

Diffstat:
Mdraft-schanzen-cake.xml | 215++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
1 file changed, 132 insertions(+), 83 deletions(-)

diff --git a/draft-schanzen-cake.xml b/draft-schanzen-cake.xml @@ -187,8 +187,13 @@ pk_R | | sk_e | | ES,ETS | | | | - | InitiatorHello | - | {pk_I,ServicesInfo} | + | InitiatorHello: | + | EphemeralKey | + | ReceiverKemChallenge | + | InitiatorNonce | + | InitiatorPkHash | + | {pk_I} | + | {ServicesInfo} | +---------------------------------------------->| | | pk_I | | ES,ETS @@ -197,11 +202,13 @@ ES,ETS | | | | MS | | [I,R]HTS | | RATS - | ReceiverHello | + | ReceiverHello: | + | HandshakeKemCiphertext | + | ReceiverNonce | | {ServicesInfo} | - | {ReceiverKemCiphertext} | + | {InitiatorKemChallenge} | | {ReceiverFinished} | - | [Application Payload] | + | *[Application Payload] | |<----------------------------------------------+ dES | | (d)HS | | @@ -209,45 +216,33 @@ MS | | [I,R]HTS | | [I,R]ATS | | | | - | {InitiatorFinished} | - | [Application Payload] | + | {InitiatorFinished} | + | *[Application Payload] | +---------------------------------------------->| | | IATS | | | | | | - | [Application Payload] | + | [Application Payload] | |<--------------------------------------------->| | | v v ]]></artwork> </figure> <t> - The Initiator creates the first message containing InitiatorHello and the encrypted tuple (pk<sub>I</sub>,ServicesInfo)*ETS according to <xref target="figure_swimlane"/> and <xref target="figure_key_schedule"/> using: + The Initiator creates the InitiatorHello message which includes the encrypted tuple (pk<sub>I</sub>,ServicesInfo). + The fields are encrypted using a key derived from the ETS according to <xref target="figure_swimlane"/> + and <xref target="figure_key_schedule"/>. + The ReceiverKemChallenge is computed as: </t> <ol> <li>(ss<sub>R</sub>,c<sub>R</sub>) &lt;- Encaps(pk<sub>R</sub>)</li> </ol> <t> - pk<sub>I</sub> and <tt>ServicesInfo</tt> are encrypted using the early secret ETS - using ChaCha20-Poly1305 <xref target="RFC8439"/>. - <!-- FIXME: Discuss IV. We may be able to use data from HKDF-Expand for that --> - </t> - <t> - I sends to R: + R processes the InitiatorHello as follows: </t> <ol> - <li>InitiatorHello &lt;- (c<sub>R</sub>,r<sub>I</sub>)</li> - <li>(pk<sub>I</sub>,ServicesInfo)*ETS.</li> - </ol> - <t> - R receives the first message, and processes it as defined in the following. - The encryption key ETS to decrypt the encrypted tuple (pk<sub>I</sub>,<tt>ServicesInfo</tt>), the Handshake and Master Secrets are generated according to <xref target="figure_key_schedule"/>. - The secrets can also be generated as-needed and not necessarily all at once. - Note that IATS cannot be derived (yet) at this point. - </t> - <ol> - <li>Verify that the message type is TBD</li> + <li>Verify that the message type is CORE_INITIATOR_HELLO</li> <li>(ss<sub>R</sub>,c<sub>R</sub>) &lt;- Decaps(sk<sub>R</sub>, c<sub>R</sub>)</li> <li>(ss<sub>e</sub>,c<sub>e</sub>) &lt;- Encaps(pk<sub>e</sub>)</li> <li>Generate ETS from <xref target="key_schedule"/> and decrypt pk<sub>I</sub>.</li> @@ -255,33 +250,46 @@ MS | | <li>Generate RHTS and RATS from <xref target="key_schedule"/>.</li> </ol> <t> - R sends to I: + The ETS, the Handshake and Master Secrets are generated according to <xref target="figure_key_schedule"/>. + Note that IATS cannot be derived (yet) at this point. + R may now generate its ReceiverHello message: </t> <ol> - <li>ReceiverHello &lt;- (c<sub>e</sub>,r<sub>R</sub>)</li> - <li>Create ReceiverFinished as per <xref target="wire_formats"/>.</li> - <li>(ServicesInfo, c<sub>I</sub>, ReceiverFinished)*RHTS.</li> - <li>Optionally, R may already send application data encrypted with RATS.</li> + <li>r<sub>R</sub> &lt;- RandomUInt64()</li> + <li>Create ReceiverFinished as per <xref target="cake_hs_proto"/>.</li> + <li>Encrypt ServicesInfo, c<sub>I</sub> and ReceiverFinished with a key derived from RHTS.</li> + <li>Optionally, R may now already send application data encrypted with RATS.</li> </ol> <t> I processes the message received by R: </t> <ol> - <li>Verify that the message type is TBD</li> + <li>Verify that the message type is CORE_RECEIVER_HELLO</li> <li>ss<sub>e</sub> &lt;- Decaps(sk<sub>e</sub>,c<sub>e</sub>)</li> <li>Generate IHTS and RHTS from <xref target="key_schedule"/> and decrypt ServicesInfo, c<sub>I</sub> and ReceiverFinished.</li> <li>ss<sub>I</sub> &lt;- Decaps(sk<sub>I</sub>,c<sub>I</sub>).</li> - <li>Create ReceiverFinished as per <xref target="wire_formats"/> and check against decrypted payload.</li> - <li>Create IteratorFinished as per <xref target="wire_formats"/>.</li> + <li>Create ReceiverFinished as per <xref target="cake_hs_proto"/> and check against decrypted payload.</li> + <li>Create IteratorFinished as per <xref target="cake_hs_proto"/>.</li> + <li>Send InteratorFinished message encrypted with the key derived from IHTS to R</li> </ol> <t> - I sends to R: + At this point we have a secure channel. </t> - <ol> - <li>(InitiatorFinished)*IHTS</li> - </ol> <t> - At this point we have a secure channel. + Note that for the handshake we do not use epochs or sequence numbers. + The reason for this is simple: DTLS uses epoch 0 for plaintext messages. + Epoch 1 is reserved for payload encrypted with a key derived from ETS. + However, we only have a single message that contains such a payload: InitiatorHello. + Epoch 2 is reserved for payload encrypted with a key derived from *HTS. + But we only have a single message that contains a payload encrypted with a key + derived from RHTS: ReceiverHello. + We also only have a single message that contains a payload encrypted with a key + derived from AHTS: InitiatorFinished. + Consequently, we do not need any signalling of Epochs until we encrypt data using + *ATS secrets. + The optional application data that may already be sent by the receiver after its first + handshake message or by the initiator after its second handshake message, are + already wrapped inside an EncryptedMessage and have both Epoch and sequence numbers set. </t> </section> <section anchor="key_schedule" numbered="true" toc="default"> @@ -319,11 +327,11 @@ ss_e -> HKDF-Extract = Handshake Secret (HS) ss_I -> HKDF-Extract = Master Secret (MS) | +-----> HKDF-Expand(., "i ap traffic", - | InitiatorHello...ReceiverFinished) + | InitiatorHello...InitiatorFinished) | = IATS_0 | +-----> HKDF-Expand(., "r ap traffic", - InitiatorHello...ReceiverFinished) + InitiatorHello...ReceiverHello) = RATS_0 ]]></artwork> </figure> @@ -353,24 +361,65 @@ nonce = HKDF-Expand ([I,R][A,H]TS, "iv", 12) Implementations <bcp14>SHOULD</bcp14> delete old traffic secrets and their derived keys. </t> </section> - <section anchor="wire_formats" numbered="true" toc="default"> - <name>Wire Formats</name> - <section anchor="message_hdr" numbered="true" toc="default"> - <name>Message Header</name> + <section anchor="cake_hs_proto" numbered="true" toc="default"> + <name>The CAKE Handshake Protocol</name> + <t> + This section is named and structured to mimic <xref target="RFC9147" section="5"/>. + </t> + <section anchor="timeout_retransmission" numbered="true" toc="default"> + <name>Timeout and Retransmission</name> + <t> + CAKE reuses the logic for timeout and retransmission from <xref target="RFC9147" section="5.8"/>. + It differs in that large flight sizes are not of concern for CAKE. + Similarly, the only Post-Handshake message relevant for CAKE is the KeyUpdate message. + </t> + </section> + <section anchor="crypto_label" numbered="true" toc="default"> + <name>Cryptographic Label Prefix</name> <t> - Any sent message is prepended with a <tt>MessageHeader</tt>: + <xref target="RFC8446" section="7.1"/> specifies that HKDF-Expand-Label uses a label prefix of "tls13 ". + For CAKE, that label <bcp14>SHALL</bcp14> be "cake ". + This ensures key separation between CAKE, DTLS 1.3 and TLS 1.3. + </t> + </section> + <section anchor="cake_hs_msg_fmt" numbered="true" toc="default"> + <name>CAKE Handshake Message Format</name> + <t> + Any sent message in the handshake starts with a <tt>MessageHeader</tt>: </t> <figure anchor="figure_msghdr" title="The Wire Format of the Message Header."> <artwork name="" type="" align="left" alt=""><![CDATA[ 0 8 16 24 32 40 48 56 +-----+-----+-----+-----+-----+-----+-----+-----+ - | Size | Purpose (0xXX) | + | Size | Type (0xXX) | +-----+-----+-----+-----+-----+-----+-----+-----+ ]]></artwork> </figure> + <dl> + <dt>size:</dt> <dd>The size of the message including the Size and Type fields.</dd> + <dt>type:</dt> <dd>The message type.</dd> + </dl> + <t> + The possible types of messages are: + </t> + <ul> + <li>InitiatorHello</li> + <li>ReceiverHello</li> + <li>HandshakeFinished</li> + <li>KeyUpdate</li> + </ul> + </section> + <section anchor="svcinfo" numbered="true" toc="default"> + <name>ServicesInfo String</name> + <t> + The ServicesInfo is a string consisting of key-value pairs separated by + a separator indicating supported services and their versions. + E.g. "dht:1.1;cadet:0.4". + The ServicesInfo is zero terminated. + </t> </section> <section anchor="initiator_hello" numbered="true" toc="default"> - <name>InitiatorHello</name> + <name>InitiatorHello Message</name> <t> The InitiatorHello: </t> @@ -382,7 +431,8 @@ nonce = HKDF-Expand ([I,R][A,H]TS, "iv", 12) | | | | +-----+-----+-----+-----+-----+-----+-----+-----+ - | KemCiphertext | + | InitiatorKemChallenge | + | | | | | | +-----+-----+-----+-----+-----+-----+-----+-----+ @@ -392,30 +442,23 @@ nonce = HKDF-Expand ([I,R][A,H]TS, "iv", 12) +-----+-----+-----+-----+-----+-----+-----+-----+ | Nonce | +-----+-----+-----+-----+-----+-----+-----+-----+ + / {pk_I,ServicesInfo} / ]]></artwork> </figure> <t> - The KemCiphertext is generated according to <xref target="figure_key_schedule"/> using: + The InitiatorKemChallenge is generated according to <xref target="figure_key_schedule"/> using: </t> <ol> <li>(ss<sub>R</sub>,c<sub>R</sub>) &lt;- Encaps(pk<sub>R</sub>)</li> </ol> <t> - The pk<sub>I</sub> and <tt>ServiceInfo</tt> are encrypted using ChaCha20-Poly1305 <xref target="RFC8439"/>. + The pk<sub>I</sub> and <tt>ServiceInfo</tt> are encrypted using ChaCha20-Poly1305 <xref target="RFC8439"/> + with key and IV derived from the ETS. <!-- FIXME: Discuss IV. We may be able to use data from HKDF-Expand for that --> </t> </section> - <section anchor="svcinfo" numbered="true" toc="default"> - <name>ServicesInfo</name> - <t> - The ServicesInfo is a string consisting of key-value pairs separated by - a separator indicating supported services and their versions. - E.g. "dht:1.1;cadet:0.4". - The ServicesInfo is zero terminated. - </t> - </section> <section anchor="receiver_hello" numbered="true" toc="default"> - <name>ReceiverHello</name> + <name>ReceiverHello Message</name> <t> The ReceiverHello: </t> @@ -423,37 +466,43 @@ nonce = HKDF-Expand ([I,R][A,H]TS, "iv", 12) <artwork name="" type="" align="left" alt=""><![CDATA[ 0 8 16 24 32 40 48 56 +-----+-----+-----+-----+-----+-----+-----+-----+ - | KemCiphertext | + | HandshakeKemCiphertext | + | | | | | | +-----+-----+-----+-----+-----+-----+-----+-----+ | Nonce | +-----+-----+-----+-----+-----+-----+-----+-----+ + / {ServicesInfo,ReceiverKemCiphertext,Finished} / ]]></artwork> </figure> + <t> + The protected fields after the nonce are encrypted using a key derived from AHTS. + They are not encrypted individually but as a single payload. + </t> </section> - <section anchor="initiator_finished" numbered="true" toc="default"> - <name>InitiatorFinished</name> + <section anchor="handshake_finished" numbered="true" toc="default"> + <name>Finished Field</name> <t> - The InitiatorFinished: + The HandshakeFinished field contains either InitiatorFinished + or ReceiverFinished value: </t> <ol> <li>fk<sub>I</sub> &lt;- HKDF-Expand(MS, "i finished", NULL)</li> - <li>IF &lt;- HMAC(fk<sub>I</sub>, InitiatorHello...ReceiverFinished)</li> - <li>InitiatorFinished &lt;- Enc(IHTS, IF)</li> + <li>InitiatorFinished &lt;- HMAC(fk<sub>I</sub>, InitiatorHello...ReceiverFinished)</li> + <li>The InitiatorFinished message is encrypted using a key derived from IHTS.</li> </ol> - </section> - <section anchor="receiver_finished" numbered="true" toc="default"> - <name>ReceiverFinished</name> - <t> - The ReceiverFinished: - </t> <ol> <li>fk<sub>R</sub> &lt;- HKDF-Expand(MS, "r finished", NULL)</li> <li>ReceiverFinished &lt;- HMAC(fk<sub>R</sub>, InitiatorHello...ReceiverKemCiphertext)</li> - <li>(ReceiverFinished)*RHTS</li> </ol> </section> + <section anchor="ack_msg" numbered="true" toc="default"> + <name>ACK</name> + <t> + The ACK message: See <xref target="RFC9147" section="7"/>. + </t> + </section> <section anchor="encrypted_message" numbered="true" toc="default"> <name>EncryptedMessage</name> <t> @@ -473,11 +522,7 @@ nonce = HKDF-Expand ([I,R][A,H]TS, "iv", 12) ]]></artwork> </figure> <t> - This is followed by encrypted application data. - The length of the data is included in the size field of the MessageHeader - preceeding the EncryptedMessage header. - </t> - <t> + The epoch starts at 0 after the handshake with the first *ATS secret. The sequence number is encrypted with the output as defined in <xref target="RFC9147" section="4.2.3"/> for ChaCha20-based AEAD schemes. For clarity, the XOR-based encryption using the 64 byte output of ChaCha20 is as follows: @@ -490,6 +535,11 @@ nonce = HKDF-Expand ([I,R][A,H]TS, "iv", 12) the XOR this value will have to be reconstructed or otherwise masked beforehand. </t> <t> + The tag is followed by encrypted application data. + The length of the data is included in the size field of the MessageHeader + preceeding the EncryptedMessage header. + </t> + <t> The per-message nonce is not transmitted and instead generated as defined in <xref target="RFC8446" section="5.3"/>. <!-- FIXME the records/encryptions apply to all messages(?)--> </t> @@ -497,14 +547,13 @@ nonce = HKDF-Expand ([I,R][A,H]TS, "iv", 12) <section anchor="key_update_msg" numbered="true" toc="default"> <name>KeyUpdate</name> <t> - The KeyUpdate message is a simple MessageHeader with type <tt>CORE_KEY_UPDATE</tt> - followed by a UpdateRequested indicator. - It is always a payload inside an EncryptedMessage. + The KeyUpdate message is a simple MessageHeader inside an EncryptedMessage with type <tt>CORE_KEY_UPDATE</tt> + followed by an UpdateRequested indicator. This means that for every received EncryptedMessage the peer <bcp14>MUST</bcp14> check if this is a KeyUpdate. A KeyUpdate message indicates that the sender has switched its traffic secrets according to the key schedule in <xref target="key_schedule"/>. - If any bit in the first byte of the UpdateRequested field is set, this means that the receiver + If any bit in the UpdateRequested field is set, this means that the receiver of the KeyUpdate <bcp14>MUST</bcp14> send its own KeyUpdate message. Any bytes following the UpdateRequested field are updated ServicesInfo (<xref target="svcinfo"/>). ServicesInfo updates are optional.