New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rework Key Update #2237
Rework Key Update #2237
Changes from 1 commit
867af94
b4ddb7f
4d3f65a
4836c87
8c72c8d
a2ef722
d62829d
e9bb544
acff3b6
a2a860f
e378a88
1b63f75
fcc1d9e
940bac4
3fca7a5
8fd93b8
efeaf0d
5fb15c8
b3d8ff1
b56d3d9
5b075a8
331d3a7
1c9fe31
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -863,7 +863,7 @@ This protection applies to the least-significant bits of the first byte, plus | |
the Packet Number field. The four least-significant bits of the first byte are | ||
protected for packets with long headers; the five least significant bits of the | ||
first byte are protected for packets with short headers. For both header forms, | ||
this covers the reserved bits and the Packet Number Length field; the Key Phase | ||
this covers the reserved bits and the Packet Number Length field; the Key Update | ||
bits are also protected for packets with a short header. | ||
|
||
The same header protection key is used for the duration of the connection, with | ||
|
@@ -1105,21 +1105,23 @@ possible to update the keys used to protect packets. The Key Update field in the | |
short header is used to indicate when key updates are permitted and when they | ||
have occurred. | ||
|
||
The low bit of the Key Update field (0x04) is the Key Phase bit. The Key Phase | ||
The low bit of the Key Update field (0x04) is the Key Phase bit. The key phase | ||
is used to indicate which packet protection keys are used to protect the packet. | ||
The Key Phase bit is initially set to 0 for the first set of 1-RTT packets. The | ||
Key Phase is toggled to signal each key update. | ||
key phase is toggled to signal each key update. | ||
|
||
The Key Phase bit allows a recipient to detect a change in keying material | ||
without needing to receive the first packet that triggered the change. An | ||
endpoint that notices a changed Key Phase updates keys and decrypts the packet | ||
that contains the changed value. | ||
The key phase allows a recipient to detect a change in keying material without | ||
needing to receive the first packet that triggered the change. An endpoint that | ||
notices a changed key phase updates keys and decrypts the packet that contains | ||
the changed value. | ||
|
||
The high bit of the Key Update field (0x08) is the Key Update Permitted bit. | ||
Endpoints set this value to 0 until they successfully process a packet with keys | ||
from the same key phase as they are using to send. An endpoint MUST NOT | ||
initiate a key update until it receives a packet with the Key Update Permitted | ||
bit set. | ||
The high bit of the Key Update field (0x08) is the Key Update Permitted bit. An | ||
endpoint MUST NOT initiate a key update unless they have received a packet with | ||
the current Key Phase and the Key Update Permitted bit set to 1. An endpoint | ||
MAY keep this value set to 0, forbidding key updates. An endpoint MUST NOT set | ||
this value to 1 until it successfully processes a packet with keys from the same | ||
key phase. Once this bit is set it MUST NOT be cleared for packets in the same | ||
key phase. | ||
|
||
Only packets that increase the largest received packet number are used to | ||
trigger key updates or changes in the Key Update Permitted bit. | ||
|
@@ -1164,20 +1166,20 @@ corresponding key and IV are created from that secret as defined in | |
{{protection-keys}}. The header protection key is not updated. | ||
|
||
The endpoint clears the Key Update Permitted bit, and toggles the value of the | ||
low Key Phase bit, and uses the updated key and IV to protect all subsequent | ||
Key Phase bit, and uses the updated key and IV to protect all subsequent | ||
packets. | ||
|
||
An endpoint MUST NOT initiate more than one key update at a time. A subsequent | ||
key update can only be performed after the endpoint has successfully processed a | ||
packet with a matching Key Phase and the Key Update Permitted bit set. | ||
packet with a matching key phase and the Key Update Permitted bit set. | ||
Together, these indicate that the key update was received and acted on. | ||
|
||
Once an endpoint has received and successfully processed packets with the same | ||
Key Phase value, this indicates that the peer has also updated keys. The | ||
key phase, this indicates that the peer has also updated keys. The | ||
endpoint can then set the Key Update Permitted bit to 1 on packets it | ||
subsequently sends. An endpoint MUST NOT set Key Update Permitted to 1 on | ||
packets it sends unless it has successfully processed packets with a matching | ||
Key Phase. An endpoint MAY defer setting Key Update Permitted to 1 until it has | ||
key phase. An endpoint MAY defer setting Key Update Permitted to 1 until it has | ||
discarded old keys, see {{key-update-old-keys}}. | ||
|
||
Using Key Update Permitted in this manner guarantees at least one round trip | ||
|
@@ -1192,15 +1194,15 @@ connection error of type KEY_UDPATE_ERROR. | |
## Responding to a Key Update | ||
|
||
An endpoint that sets Key Update Permitted to 1 on packets it sends is willing | ||
to accept key updates. If a packet is received with a Key Phase that differs | ||
to accept key updates. If a packet is received with a key phase that differs | ||
from the value the endpoint expects, the endpoint creates a new packet | ||
protection secret for reading and the corresponding key and IV. The endpoint | ||
uses the same key derivation process as its peer uses to generate keys for | ||
receiving. | ||
|
||
If the packet protection is successfully removed using the updated key and IV, | ||
then the keys the endpoint initiates a key update in response, as described in | ||
{{key-update-initiate}}. However, as packets with a matching Key Phase have | ||
{{key-update-initiate}}. However, as packets with a matching key phase have | ||
been received, the Key Update Permitted bit can be set to 1 on the next packet | ||
it sends. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't that a restatement of the lines 1167-1169? Why do we have the same text twice, with slightly different phrasing, "processed" vs. "packet protection is successfully removed" ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No difference intended. I've tried to even this out. |
||
|
@@ -1215,7 +1217,7 @@ connection error of type KEY_UDPATE_ERROR. | |
## Using Old Keys {#key-update-old-keys} | ||
|
||
If the most recent packet sent by the endpoint contained a Key Update Permitted | ||
bit set to 0, a Key Phase other than the value expected indicates that the | ||
bit set to 0, a key phase other than the value expected indicates that the | ||
packet was protected with old keys. If those old keys are available, then they | ||
can be used to remove packet protection. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "key updates that use the Key Phase bit". That's a weird way to put it. Maybe a reference to the ladder diagram in the transport spec? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe "after the handshake is complete," assuming that's now a defined term? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've tried very hard to separate key update as a concept from the key changes that happen during the handshake. So I'll remove the 'that use the Key Phase bit' part. |
||
|
@@ -1235,10 +1237,10 @@ read keys to limit the number of keys it maintains. An endpoint MAY also | |
prevent key update until it discards keys from the handshake, including any | ||
0-RTT keys. An endpoint SHOULD set the Key Update Permitted bit when possible. | ||
|
||
Once set, the Key Update Permitted bit MUST NOT be cleared for packets protected | ||
with the same keys. An endpoint MAY treat receipt of a packet with the Key | ||
Update Permitted bit cleared as a connection error of type KEY_UPDATE_ERROR if | ||
the bit was previously set on packets protected with the same keys. | ||
Once set, the Key Update Permitted bit MUST NOT be cleared for packets with the | ||
same key phase. An endpoint MAY treat receipt of a packet with the Key Update | ||
Permitted bit cleared as a connection error of type KEY_UPDATE_ERROR if the bit | ||
was previously set on packets protected with the same keys. | ||
|
||
Endpoints MUST NOT generate a timing side-channel signal that might indicate | ||
that the Key Update field was invalid (see {{header-protect-analysis}}). | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer stronger language here. Ideally, a MUST (although we'd have to rearrange the text a bit to allow deferring this until the old keys are discarded).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I struggled with this too. I want people to enable key updates, but the fact is that we can't really enforce it. If we didn't want to allow peers to minimize the number of active keys, you could allow endpoints to punish them if they acknowledged a packet with a matching key phase in a packet that didn't include the Key Update Permitted bit. I will try to work in a SHOULD somehow.