Subject: [quicwg/base-drafts] simultaneous key update can lead to deadlock (#2214)

From: Marten Seemann <[email-masked]>
Date: Thu, 20 Dec 2018 03:14:46 -0800

Imagine the following (somewhat contrived) situation:

1. The peers are currently both sending with key phase 0, and simultaneously and independently decide that it's time for a key update. They both derive the new keys for the next key phase, and start sending packets with key phase 1.
2. Peer B receives one of the packets with key phase 1. It (incorrectly) concludes that A received one of its key phase 1 packets, and initiates the next key update, and continues sending packets with key phase 0.
3. All packets with key phase 1 sent by B are lost. A now receives the new packets with key phase 0 sent by B. Since it didn't receive any key phase 1 packets, it doesn't derive new keys, and tries to decrypt the packets with the old key phase 0 key. All of those packets will end up undecrytable, leading to a stalling of the connection.
4. There's nothing A can do to recover from this situation (other than trial decryption). If it continues to send key phase 1 packets, B will interpret this as yet another key update.

One might argue that it's improbable that *all* packets with a certain key phase are lost, and certainly the probability decreases with the number of packets sent in one key phase. However, there's nothing in the spec that prevents a peer from rotating keys as frequently as it is allowed to (i.e. directly after receiving a single packet with a matching key phase).

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2214

---

From: Kazuho Oku <[email-masked]>
Date: Thu, 20 Dec 2018 03:30:01 -0800

FWIW, I had assumed that we agreed that an endpoint is required to have two generation counters, one for the send key and the other for the receive key, and to update it's send key either when it wants to, or when the receive key's generation counter becomes greater than that of the send key.

However, I do not see that specified, and I agree that we have an issue.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2214#issuecomment-448965316

---

From: Martin Thomson <[email-masked]>
Date: Thu, 20 Dec 2018 17:01:52 -0800

@kazuho, that's not a fix the problem that @marten-seemann is talking about, but if that's not written down, then that's also a problem.

The problem here is that one endpoint is updating too aggressively, even if it is entirely permissible.  If that coincides with an update on the other end, there is the possibility that one side thinks that no update has occurred, when two updates have happened.

The fix here is - I think - waiting for acknowledgment of a packet with the key phase.  Which means that you don't get to just use the key phase bit to drive this.  The interesting thing here is that when you couple this to acknowledgments you can validate updates.  If someone acknowledges an update with old keys, then you know they are misbehaving.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2214#issuecomment-449195528

---

From: Marten Seemann <[email-masked]>
Date: Thu, 20 Dec 2018 18:31:04 -0800

If we want to avoid relying on acknowledgements as proposed in #2237, another way to solve this issue would be to extend the key phase to two bits (and increment the key phase by 1 every time we do a key update). This would allow peer A to detect in step 3 that a simultaneous key update happened, and to catch up with updating its read keys.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/2214#issuecomment-449219993