Skip to content

Conversation

@yaroslavros
Copy link
Collaborator

As discussed at IETF124 I have tightened up the process and eliminated 1 unnecessary message in both TLS and DTLS flows.

Please check.

Comment on lines 337 to 340
1. After the initiator sends `ExtendedKeyUpdate(new_key_update)` it
MUST update its send keys. Upon receipt of this message, the responder
MUST update its receive keys and then send
`ExtendedKeyUpdate(new_key_update)`, after which it MUST update its
send keys.
MUST update its receive and send keys.
Copy link

@ilaril ilaril Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think receive keys should be updated in previous step — since responder updates its send keys upon sending NKRes, the initiator should update its receive keys after receiving NKRes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the text

Comment on lines +345 to +348
Both initiator and responder MUST encrypt their `ExtendedKeyUpdate` messages
with the old keys. Responder MUST ensure that the `ExtendedKeyUpdate(new_key_update)`
encrypted with the old key is received before accepting any messages encrypted with
the new key.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How could responder accept any messages with new key before receiving NKU?

However, because NKRes and NKU both update keys, endpoints must both check those messages are the last in record — Similarly to the finished message.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Responder has access to new key schedule. So technically it could accept messages using trial decryption with new keys before receiving confirmation from the initiator. This text instructs implementers not to do that.

Comment on lines 430 to 434
# and updates SEND keys here
# Client derives new secrets
[EKU(new_key_update)] -------->
# Client updates SEND keys here
# Client updates SEND and
# RECEIVE keys here
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As in previous prose, I think it should be "Client derives new secrets and updates RECEIVE keys here" and "Client updates SEND keys here".

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

If a peer key_update_request arrives while in WAIT_RESP (crossed updates), apply the crossed-request rule above. If the peer's key_exchange is higher, abandon the local update (updating := 0) and continue as responder: send key_update_response, derive new secrets, then proceed with the responder flow. If lower, ignore the peer's request; if equal, abort with "unexpected_message".

Upon receiving the responder's NKU (tag equals the current rx, meaning the responder is still tagging with its old tx), the initiator:
Upon receiving the responder's ACK matching the updated epoch, the responder completes the transition by synchronizing transmit and receive epochs (tx := rx), disabling retention, and clearing the update flag. The state machine returns to FINISHED, ready for subsequent updates.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Upon receiving the responder's ACK matching the updated epoch, the responder completes the transition by synchronizing transmit and receive epochs (tx := rx), disabling retention, and clearing the update flag. The state machine returns to FINISHED, ready for subsequent updates.
Upon receiving the responder's ACK matching the updated epoch, the initiator completes the transition by synchronizing transmit and receive epochs (tx := rx), disabling retention, and clearing the update flag. The state machine returns to FINISHED, ready for subsequent updates.

Copy link
Collaborator

@tireddy2 tireddy2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes look good except for a Nit.

@hannestschofenig
Copy link
Collaborator

I am still not convinced about this optimization. The initial design was selected to separate the two phases - first phase is to exchange the DH public keys and the second phase is to activate the keys. Our use cases, long-lived connections in telco networks and in the industurial IoT sector, do not have any performance constraints.

Making this change will also requires us to re-do the formal analysis.

@ilaril
Copy link

ilaril commented Nov 12, 2025

It also seems like this prevents the initiator from delaying the update in TLS (due to unexpected overload) without stalling the entire channel, as the responder will immediately change the keys it uses after sending key_update_response. Delaying the update still works in DTLS, as the initiator can explicitly ACK the response, which does not trigger any actions from the responder.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants