Subject: Key change logic

From: Eric Rescorla <[email-masked]>
Date: Thu, 13 Apr 2017 13:49:44 -0700

I'm not sure that the logic around key changes is exactly clear.

Case 1:
Assume you are in steady state where you have just received a packet
with key generation G = 0, key phase bit P = 1, and packet number PN =
10 (i.e., there have been no key changes so far). You now receive a
packet with PN = 15, P = 1. Turning to 6.2, we see:

   A receiving endpoint detects an update when the KEY_PHASE bit doesn't
   match what it is expecting.  It creates a new secret (see
   Section 5.2) and the corresponding read key and IV.  If the packet
   can be decrypted and authenticated using these values, then the keys
   it uses for packet protection are also updated.  The next packet sent
   by the endpoint will then use the new keys.

   An endpoint doesn't need to send packets immediately when it detects
   that its peer has updated keys.  The next packet that it sends will
   simply use the new keys.  If an endpoint detects a second update
   before it has sent any packets with updated keys it indicates that
   its peer has updated keys twice without awaiting a reciprocal update.
   An endpoint MUST treat consecutive key updates as a fatal error and
   abort the connection.

So, we compute generation G=1 and try to decrypt the packet. If it
succeeds, we install key G=1 with the knowledge that the transition
happens somewhere between 10 and 15.

Case 2:
The same as Case #1, but I receive PN = 7, P = 1. I think what we do
then is just discard the packet immediately because it's impossible,
right? Not clear where the text says that.

Case 3:
Imagine we are in the state right after case #1 (i.e., we have sent no
packets) and now we receive a packet PN = 20, P = 0. Now, this looks
like a second key change, so what do we do now? It seems like we have
three choices:

1. Discard it because it's clearly illegal.
2. Try to decrypt it with key G=2 and process it as a key change (as
   the first paragraph of the citation above graf tells us to do).
3. Tear down the connection as specified in the second paragraph
   above tells us to do.

#2 seems pretty silly, because only one of two things can happen

(a) We can't decrypt it because it's bogus and we discard it.
(b) We can decrypt it (because the keys have been compromised
    or the other side is misbehaving) in which case we tear
    down the connection.

But it's almost certainly (a), so this doesn't seem like a good
use of resources.

#3 is even worse, because it means that anyone can send us an
unauthenticated packet and tear down the connection, so that
can't be right.

I think that leaves us with #2 as the right answer, but that's
the one thing that the spec doesn't tell us to do, and it renders
the second paragraph above irrelevant.

Case 4:
The same as case #1, but next I receive two packets:

- PN = 12, P = 1 [which decrypts with key G = 1]
- PN = 14, P = 0

Now, this second packet is impossible because we know that that
we have:

  PN = 10 [G = 0]
  PN = 12 [G = 1]
  PN = 15 [G = 1]

So we can't have a key change between 12 and 15, so here we are. The
spec doesn't give guidance on what to do. I think the answer is
"discard the packet".

I think we need to write these sections a bit more clearly. I'm
happy to take a crack at it, but I'd like to make sure that we all
agree that the behaviors above are the right ones.

-Ekr

---

From: Martin Thomson <[email-masked]>
Date: Wed, 19 Apr 2017 09:46:51 +1000

Yep, I followed your logic here and you are right:

Anything that doesn't decrypt has to be thrown away (no connection
closes on unauthenticated rubbish)

For the sequence P=1,N=15; P=0;N=20 without ever sending with P=1, the
second packet should be discarded rather than trying with G=2.

(The awkward thing is that you probably need to have more than two
generations of receive keys in play in the case you DO send with P=1
here.)

For the sequence P=1,N=15; P=1,N=12; P=0,N=14 the third packet should
be discarded.

---

From: Eric Rescorla <[email-masked]>
Date: Wed, 19 Apr 2017 07:28:58 -0400

> generations of receive keys in play in the case you DO send with P=1

As far as I can tell, this only happens if someone changes keys really
often, and
that seems like "it hurts when I do that". I mean, yeah, you could
compensate
for this, but I think better to give guidance not to change keys more than
once
in MSL.

-Ekr

---

From: Victor Vasiliev <[email-masked]>
Date: Thu, 20 Apr 2017 14:53:25 -0400

> for this, but I think better to give guidance not to change keys more than
I would also add a requirement that if the sender is currently using phase
P, it must not
switch to phase !P until at least one packet with phase P is acknowledged
and none of
the packets of previous phase !P are considered in-flight.

  -- Victor.

---

From: Martin Thomson <[email-masked]>
Date: Fri, 21 Apr 2017 09:29:40 +1000

> the packets of previous phase !P are considered in-flight.

Determining that packets are still in flight is hard.  It is
sufficient to know that the other side has moved up to the same key,
for which you don't need an ACK because use of the key implies
acknowledgment.

With huge delays on random packets being a thing, there is always the
chance that two fast changes lead to packets with the same phase and
different keys arriving at the same time.  Maybe a better bit of
guidance would be to avoid changing keys within an RTO of the last
change.  Maybe that is what you had in mind.