commit 1253010f83b1935e4681d9f9310b19311395ac62
parent 4139a9af86f95735d9ccc7acff7d7b4b5a88fdde
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date: Fri, 1 Aug 2025 13:04:36 +0200
some implementation updates
Diffstat:
1 file changed, 64 insertions(+), 37 deletions(-)
diff --git a/draft-schanzen-cake.xml b/draft-schanzen-cake.xml
@@ -144,7 +144,7 @@
<dt>H(D):</dt> <dd>A 512-bit hash over D. The hash function is TBD (Blake2b or SHA-512).</dd>
<dt>T(M):</dt> <dd>means the transcript as a concatenation of received/sent messages starting from and including the InitiatorHello pk_e until and including M. Note that the transcript refers to everything that is seen on the wire, including potentially encrypted messages or fields and metadata.</dd>
<dt>'{}K'</dt> <dd>indicates encryption with a handshake traffic key K and a modified <xref target="RFC8439"/>, the XChaCha20-Poly1305 Authenticated Encryption with Associated Data (AEAD) construction.</dd>
- <dt>'[]K'</dt> <dd>indicates encryption with an application traffic key K and a modified <xref target="RFC8439"/>, the XChaCha20-Poly1305 Authenticated Encryption with Associated Data (AEAD) construction.</dd>
+ <dt>'[]K'</dt> <dd>indicates encryption with an application traffic key K using the XChaCha20-Poly1305 Authenticated Encryption with Associated Data (AEAD) construction.</dd>
</dl>
</section>
<section anchor="rationale" numbered="true" toc="default">
@@ -219,12 +219,12 @@ ss_R | |
| | ss_R
| | ss_I
| | ss_e
- | ResponderHello: |
+ | ResponderHello: |
| c_e |
| r_R |
| {svcinfo_R,c_I}RHTS |
- | {finished_R}RHTS |
- | *[Application Payload]RATS |
+ | {finished_R}RHTS |
+ | [ACK]RATS |
|<----------------------------------------------+
r_R | |
c_I | |
@@ -232,8 +232,8 @@ c_e | |
ss_I | |
ss_e | |
| InitiatorDone: |
- | {finished_I}IHTS |
- | *[Application Payload]IATS |
+ | {finished_I}IHTS |
+ | [ACK]IATS |
+---------------------------------------------->|
| |
| |
@@ -246,14 +246,12 @@ ss_e | |
]]></artwork>
</figure>
<t>
- Notice how we do not need any acknowledgement messages until after finished<sub>I</sub> (after 1.5 RTT).
+ Notice how we do not need any acknowledgement messages until after finished<sub>R</sub> (after 1 RTT).
+ We use the ACKs in the handshake as explicit key confirmations.
The InitiatorHello message is a single flight that is implicitly ack'ed with ResponderHello.
ResponderHello is a single flight that is implicitly ack'ed with finished<sub>I</sub>.
- finished<sub>I</sub> requires an explicit ack; at this time R and I have already established a secure channel
- and R can use an EncryptedMessage to send the ack.
The reason why this works is because CAKE groups the messages in row 3 of Table 1 in <xref target="RFC9147" section="5.7"/> into a single message (ResponderHello).
- Hence the only message that is sent without any expected response (and consequently requiring an explicit
- ACK) is finished<sub>I</sub> (and KeyUpdate).
+ Hence the only message that is sent without any expected response (and consequently requiring an explicit ACK) is finished<sub>I</sub> (and Heartbeats).
N<sub>I</sub> is a nonce generated by the initiator.
N<sub>R</sub> is a nonce generated by the responder.
</t>
@@ -417,7 +415,7 @@ nonce = HKDF-Expand-Label ([I,R][A,H]TS, "iv", 24)
]]></artwork>
</figure>
<t>
- When a peer wants to update keys, it sends a key update message <xref target="key_update_msg"/>.
+ When a peer wants to update keys, it sends a key update message <xref target="heartbeat_msg"/>.
Implementations <bcp14>SHOULD</bcp14> delete old traffic secrets and their derived keys.
</t>
</section>
@@ -584,9 +582,9 @@ nonce = HKDF-Expand-Label ([I,R][A,H]TS, "iv", 24)
<artwork name="" type="" align="left" alt=""><![CDATA[
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
-| Epoch | Sequence Number |
+| Epoch |
+-----+-----+-----+-----+-----+-----+-----+-----+
-| Timestamp |
+| Sequence Number |
+-----+-----+-----+-----+-----+-----+-----+-----+
| Tag |
| |
@@ -595,19 +593,49 @@ nonce = HKDF-Expand-Label ([I,R][A,H]TS, "iv", 24)
</figure>
<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"/>
+ Any peer may at any time update to a new epoch.
+ Peers may keep a history of secrets for respective epochs at their own discretion in
+ order to handle out-of-order message deliveries.
+ Unlike DTLS1.3 in CAKE does not truncate the epoch and no reconstruction is
+ necessary, hence the epoch may be bumped by peers at their own discretion without
+ explicit key update mechanisms.
+ A peer may consider the epoch too old or too far in the future and reject description.
+ For this purpose, a peer may manage a sliding window of epochs that can be used
+ by the other peer.
+ </t>
+ <t>
+ The sequence number is encrypted 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:
- The sequence number is padded to the left such that it is exactly 8 bytes (as if the Epoch field
- was still present).
- Then, the first 8 bytes of the output of ChaCha20 are XORed with the resulting byte string.
- The first 16 bits can be ignored (zeroed).
- Note that an implementation may simply XOR the first 8 byte of the EncryptedMessage.
- However, this will include the Epoch field and whatever value it was set to so after
- the XOR this value will have to be reconstructed or otherwise masked beforehand.
+ The Tag is divided into a 32-bit counter and 96-bit nonce for use with ChaCha20.
+ The key is derived from the *ats as follows:
</t>
+ <figure anchor="figure_sn_key_derivation" title="Traffic Key Generation.">
+ <artwork name="" type="" align="left" alt=""><![CDATA[
+sn_secret = HKDF-Expand-Label [I,R]ATS_N, "sn", 32)
+ ]]></artwork>
+ </figure>
<t>
- The tag is followed by encrypted application data.
+ Where [I,R]ATS_N is the respective ATS secret of epoch N.
+ The leading 8 bytes of the 64 byte output of ChaCha20 are then
+ XORed with the sequence number in network byte order:
+ </t>
+ <figure anchor="figure_sn_xor" title="Traffic Key Generation.">
+ <artwork name="" type="" align="left" alt=""><![CDATA[
+sn_key = HKDF-Expand-Label(Secret, "sn", "", 8)
+mask = ChaCha20(sn_key, Ciphertext[0..3], Ciphertext[4..15])
+sn_enc = mask[0..8] XOR sn_nbo
+ ]]></artwork>
+ </figure>
+ <t>
+ Notice how this requires a ciphertext of at least 16 bytes.
+ But our ciphertexts are always at least 16 bytes due to the Poly1305
+ atuthentication tag. In fact, since the authentication tag is considered
+ part of the ciphertext, and is prepended in front of the encrypted plaintext,
+ the mask is always computed on the authentication tag only.
+ </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>
@@ -616,17 +644,16 @@ nonce = HKDF-Expand-Label ([I,R][A,H]TS, "iv", 24)
<!-- FIXME the records/encryptions apply to all messages(?)-->
</t>
</section>
- <section anchor="key_update_msg" numbered="true" toc="default">
- <name>KeyUpdate</name>
+ <section anchor="heartbeat_msg" numbered="true" toc="default">
+ <name>Heartbeat</name>
<t>
- The KeyUpdate message is a simple MessageHeader inside an EncryptedMessage with type <tt>CORE_KEY_UPDATE</tt>
- followed by an UpdateRequested indicator.
+ The HEARTBEAT message is a simple MessageHeader inside an EncryptedMessage with type <tt>CORE_HEARTBEAT</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"/>.
+ the peer <bcp14>MUST</bcp14> check if this is a Heartbeat.
+ A Heartbeat message may implicitlyindicate that the sender has switched its
+ traffic secrets according to the key schedule in <xref target="key_schedule"/>.
If any bit in the UpdateRequested field is set, this means that the responder
- of the KeyUpdate <bcp14>MUST</bcp14> send its own KeyUpdate message.
+ of the Heartbeat <bcp14>SHOULD</bcp14> increment its epoch.
Any bytes following the UpdateRequested field are updated services info
svcinfo (<xref target="svcinfo"/>).
Services info updates are optional.
@@ -646,18 +673,18 @@ nonce = HKDF-Expand-Label ([I,R][A,H]TS, "iv", 24)
<section anchor="ack_msg" numbered="true" toc="default">
<name>ACK</name>
<t>
- The ACK message: See <xref target="RFC9147" section="7"/>.
+ The ACK message is a simple MessageHeader inside an EncryptedMessage with
+ type <tt>CORE_ACK</tt>.
+ This means that for every received EncryptedMessage
+ the peer <bcp14>MUST</bcp14> check if this is an ACK message after decryption.
+ The peer may use the ACK in order to ensure liveliness of connected peers in
+ combination with Heartbeats.
</t>
</section>
</section>
<section anchor="open" numbered="true" toc="default">
<name>Open Issues</name>
<t>
- We must include ACK handling. In general we need to take a look at DTLS and port
- whatever it does to ensure failure tolerance with out-of-order and unreliable transmissions.
- This includes ACKs as well as retransmission (timers).
- </t>
- <t>
We must discuss EdDSA vs X25519 KEM usage. Maybe see Communicator draft for this.
</t>
<t>