Re: [quicwg/base-drafts] Rework Key Update (#2237)

Jana Iyengar <notifications@github.com> Thu, 14 February 2019 04:15 UTC

Return-Path: <noreply@github.com>
X-Original-To: quic-issues@ietfa.amsl.com
Delivered-To: quic-issues@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id B7E76130F61 for <quic-issues@ietfa.amsl.com>; Wed, 13 Feb 2019 20:15:41 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -8.001
X-Spam-Level:
X-Spam-Status: No, score=-8.001 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HTML_MESSAGE=0.001, MAILING_LIST_MULTI=-1, RCVD_IN_DNSWL_HI=-5, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (1024-bit key) header.d=github.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id UWtzQkNU8WuQ for <quic-issues@ietfa.amsl.com>; Wed, 13 Feb 2019 20:15:37 -0800 (PST)
Received: from out-3.smtp.github.com (out-3.smtp.github.com [192.30.252.194]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 9288B130F09 for <quic-issues@ietf.org>; Wed, 13 Feb 2019 20:15:37 -0800 (PST)
Date: Wed, 13 Feb 2019 20:15:36 -0800
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=github.com; s=pf2014; t=1550117736; bh=gTam0NjGtWv4Wm4G9+yzkdiNvX4vxCscOE1Z2f9tqXc=; h=Date:From:Reply-To:To:Cc:In-Reply-To:References:Subject:List-ID: List-Archive:List-Post:List-Unsubscribe:From; b=uNJaMbikBPv9sfpA1JfhiPMZ8qzr8qV3XuYbNNV367rXCaZg/0BmhGxfOPCB/YvCJ TxLfwh/MfVlOxLV5MJxuwMbC7vGt+m1i9ojtKK7OufZ/j0Qdy7C6D2CPkhKq30iMyS P72zA/ZXlE9nvBLZMxGApUmsxypsM2edrc+jOGpE=
From: Jana Iyengar <notifications@github.com>
Reply-To: quicwg/base-drafts <reply+0166e4abec5027d2273445b430ca06025ac689c813bb6a4592cf00000001187cad6892a169ce1770e975@reply.github.com>
To: quicwg/base-drafts <base-drafts@noreply.github.com>
Cc: Subscribed <subscribed@noreply.github.com>
Message-ID: <quicwg/base-drafts/pull/2237/review/203548487@github.com>
In-Reply-To: <quicwg/base-drafts/pull/2237@github.com>
References: <quicwg/base-drafts/pull/2237@github.com>
Subject: Re: [quicwg/base-drafts] Rework Key Update (#2237)
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary="--==_mimepart_5c64eb684e9c9_2b7e3fc27e6d45b8461e4"; charset="UTF-8"
Content-Transfer-Encoding: 7bit
Precedence: list
X-GitHub-Sender: janaiyengar
X-GitHub-Recipient: quic-issues
X-GitHub-Reason: subscribed
X-Auto-Response-Suppress: All
X-GitHub-Recipient-Address: quic-issues@ietf.org
Archived-At: <https://mailarchive.ietf.org/arch/msg/quic-issues/Roo_or0PZp9HOcwG8R3ggK0nB8Y>
X-BeenThere: quic-issues@ietf.org
X-Mailman-Version: 2.1.29
List-Id: Notification list for GitHub issues related to the QUIC WG <quic-issues.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/quic-issues>, <mailto:quic-issues-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/quic-issues/>
List-Post: <mailto:quic-issues@ietf.org>
List-Help: <mailto:quic-issues-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/quic-issues>, <mailto:quic-issues-request@ietf.org?subject=subscribe>
X-List-Received-Date: Thu, 14 Feb 2019 04:15:42 -0000

janaiyengar commented on this pull request.

This is some heavy lifting, thank you for doing it! A few comments.

>  
-The KEY_PHASE bit allows a recipient to detect a change in keying material
-without necessarily needing to receive the first packet that triggered the
-change.  An endpoint that notices a changed KEY_PHASE bit can update keys and
-decrypt the packet that contains the changed bit.
+The Key Phase bit is used to indicate which packet protection keys are used to

```suggestion
The Key Phase bit indicates which packet protection keys are being used to
```

>  
-The KEY_PHASE bit allows a recipient to detect a change in keying material
-without necessarily needing to receive the first packet that triggered the
-change.  An endpoint that notices a changed KEY_PHASE bit can update keys and
-decrypt the packet that contains the changed bit.
+The Key Phase bit 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 bit is toggled to signal each key update.

```suggestion
of 1-RTT packets and toggled for each subsequent key.
```

>  
-The KEY_PHASE bit allows a recipient to detect a change in keying material
-without necessarily needing to receive the first packet that triggered the
-change.  An endpoint that notices a changed KEY_PHASE bit can update keys and
-decrypt the packet that contains the changed bit.
+The Key Phase bit 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

```suggestion
protect the packet.  The Key Phase bit is set to 0 for the first set
```

> -packet with a higher packet number.  This is only possible if there is a key
-compromise and an attack, or if the peer is incorrectly reverting to use of old
-keys.  Because the latter cannot be differentiated from an attack, an endpoint
-MUST immediately terminate the connection if it detects this condition.
+
+## Initiating a Key Update {#key-update-initiate}
+
+Endpoints maintain separate read and write secrets for packet protection.  An
+endpoint initiates a key update by updating its packet protection write secret
+and using that to protect new packets.  The endpoint creates a new write secret
+from the existing write secret as performed in Section 7.2 of {{!TLS13}}.  This
+uses the KDF function provided by TLS with a label of "quic ku".  The
+corresponding key and IV are created from that secret as defined in
+{{protection-keys}}.  The header protection key is not updated.
+
+The endpoint toggles the value of the Key Phase bit, and uses the updated key

```suggestion
The endpoint toggles the value of the Key Phase bit and uses the updated key
```

>                        <--------
+... Update to @N
+@N [1] QUIC Packets

This is a bit confusing. The KEYS_ACTIVE sent above are for @M, right? If so, shouldn't the endpoint send a KEYS_ACTIVE for @N as soon as it updates to the new keys (on line 1133)?

> +
+An endpoint MUST NOT initiate a key update prior to having received and
+successfully processed a KEYS_ACTIVE frame contained in a packet from the
+current key phase.  This ensures that keys are available to both peers before
+another can be initiated.
+
+Note:
+
+: Changes in keys from Initial to Handshake and from Handshake to 1-RTT don't
+  use this key update process. Key changes during the handshake do not need to
+  wait for a KEYS_ACTIVE frame, they are driven solely by changes in the TLS
+  handshake.  The KEYS_ACTIVE frame is used to allow Initial and Handshake keys
+  to be discarded when they are no longer needed and - in the case of the first
+  1-RTT key phase - to enable the first key update.
+
+Once an endpoint has successfully processed a packet with the same key phase, it

"with the same key phase" as what?

> +  handshake.  The KEYS_ACTIVE frame is used to allow Initial and Handshake keys
+  to be discarded when they are no longer needed and - in the case of the first
+  1-RTT key phase - to enable the first key update.
+
+Once an endpoint has successfully processed a packet with the same key phase, it
+MUST send a KEYS_ACTIVE frame, though endpoints MAY defer sending the frame (see
+{{key-update-old-keys}}).
+
+
+## Responding to a Key Update
+
+An endpoint that sends a KEYS_ACTIVE frame can accept further key updates.  A
+key update can happen even without seeing a KEYS_ACTIVE frame from the peer.  If
+a packet is received with a key phase that differs from the value the endpoint
+used to protect the packet containing its last KEYS_ACTIVE frame, the endpoint
+creates a new packet protection secret for reading and the corresponding key and

Is this always the case? If I was using 0, and now start using 1 and send KEYS_ACTIVE with 1, I will continue to receive packets with key phase 0. That doesn't mean I need to create a new secret, since I haven't discarded the previous secret yet, right?

> +{{key-update-initiate}}.  An endpoint that responds to a key update MUST send a
+KEYS_ACTIVE frame to indicate that it is both sending and receiving with updated
+keys, though it MAY defer sending the frame (see {{key-update-old-keys}}).
+
+An endpoint does not always need to send packets when it detects that its peer
+has updated keys.  The next packet that it sends use the new keys and include
+the KEYS_ACTIVE frame.  If an endpoint detects a second update before it has
+sent any packets with updated keys or a KEYS_ACTIVE frame, it indicates that its
+peer has updated keys twice without awaiting a reciprocal update.  An endpoint
+MUST treat consecutive key updates as a connection error of type
+KEY_UPDATE_ERROR.
+
+Endpoints responding to an apparent key update MUST NOT generate a timing
+side-channel signal that might indicate that the Key Phase bit was invalid (see
+{{header-protect-analysis}}).  Endpoints can use dummy packet protection keys in
+place of discarded keys when key updates are not permitted; using dummy keys

If this were to happen, wouldn't the connection be closed with a KEY_UPDATE_ERROR? Is there much value in the timing signal at this point?

> +delayed by the network.  If those old keys are available, then they can be used
+to remove packet protection.
+
+An endpoint always sends packets that are protected with the newest keys.  Keys
+used for protecting packets that an endpoint sends can be discarded immediately
+after newer keys are available.
+
+After a key update, an endpoint MAY delay sending the KEYS_ACTIVE frame by up to
+three times the Probe Timeout (PTO, see {{QUIC-RECOVERY}}) to minimize the
+number of active keys it maintains.  During this time, an endpoint can use old
+keys to process delayed packets rather than enabling a new key update.  This
+only applies to key updates; endpoints MUST NOT defer sending of KEYS_ACTIVE
+during and immediately after the handshake.
+
+Even if old keys are available, those keys MUST NOT be used to protect packets
+with packets that have higher packet numbers than packets that were protected

```suggestion
that have higher packet numbers than packets that were protected
```

> +## Using Old Keys {#key-update-old-keys}
+
+During a key update, packets protected with older keys might arrive if they were
+delayed by the network.  If those old keys are available, then they can be used
+to remove packet protection.
+
+After a key update, an endpoint MAY delay sending the KEYS_ACTIVE frame by up to
+three times the Probe Timeout (PTO, see {{QUIC-RECOVERY}}) to minimize the
+number of active keys it maintains.  During this time, an endpoint can use old
+keys to process delayed packets rather than enabling a new key update.  This
+only applies to key updates that use the Key Phase bit; endpoints MUST NOT defer
+sending of KEYS_ACTIVE during and immediately after the handshake.
+
+Even if old keys are available, those keys MUST NOT be used to protect packets
+with packets that have higher packet numbers than packets that were protected
+with newer keys.  An endpoint that successfully removes protection with old keys

Why? It seems appropriate to close the connection here.

> +number of active keys it maintains.  During this time, an endpoint can use old
+keys to process delayed packets rather than enabling a new key update.  This
+only applies to key updates; endpoints MUST NOT defer sending of KEYS_ACTIVE
+during and immediately after the handshake.
+
+Even if old keys are available, those keys MUST NOT be used to protect packets
+with packets that have higher packet numbers than packets that were protected
+with newer keys.  An endpoint that successfully removes protection with old keys
+when newer keys were used for packets with lower packet numbers MUST treat this
+as a connection error of type KEY_UPDATE_ERROR.
+
+An endpoint SHOULD retain old read keys for a period of no more than three times
+the current PTO.  After this period, old read keys and their corresponding
+secrets SHOULD be discarded.
+
+An endpoint that receives a packet protected with old keys that includes an

Suggestion: "An endpoint that receives an acknowledgement for a packet protected with new keys in a packet protected with older keys MAY treat that as a ..."

> @@ -2934,6 +2931,9 @@ containing that information is acknowledged.
 * PING and PADDING frames contain no information, so lost PING or PADDING frames
   do not require repair.
 
+* KEYS_ACTIVE frames are sent until acknowledged or until newer keys are used
+  for sending packets.

I'm not sure how this works. If KEYS_ACTIVE is not yet acked, we don't know if the peer has seen this KEYS_UPDATE YET.  We therefore cannot assume that the peer can accept another key update, and so this endpoint cannot use newer keys until an ack is received for the previously sent KEYS_UPDATE.

If this is correct, you should point this out earlier in "Responding to a Key Update" above as well.

> @@ -3414,7 +3414,7 @@ packet type.  While type-specific semantics for this version are described in
 the following sections, several long-header packets in this version of QUIC
 contain these additional fields:
 
-Reserved Bits (R):
+Reserved Bit (R):

It's still two bits.

> @@ -5012,6 +5017,45 @@ Reason Phrase:
   This SHOULD be a UTF-8 encoded string {{!RFC3629}}.
 
 
+## KEYS_ACTIVE Frame {#frame-keys-active}
+
+An endpoint sends a KEYS_ACTIVE frame (type=0x1e) to signal that it has
+installed keys for both sending and receiving packets.  Once this frame has been
+both sent and received, older keys can be safely discarded.
+
+The KEYS_ACTIVE frame contains no additional fields.
+
+The packet that carries a KEYS_ACTIVE frame determines which keys are active and
+usable.  The keys with the same key phase as those used in the packet that
+carries the KEYS_ACTIVE frame are active.
+
+An endpoint MUST send a KEYS_ACTIVE packet in the first packet it sends using

```suggestion
An endpoint MUST send a KEYS_ACTIVE frame in the first packet it sends using
```

> @@ -5012,6 +5017,45 @@ Reason Phrase:
   This SHOULD be a UTF-8 encoded string {{!RFC3629}}.
 
 
+## KEYS_ACTIVE Frame {#frame-keys-active}
+
+An endpoint sends a KEYS_ACTIVE frame (type=0x1e) to signal that it has
+installed keys for both sending and receiving packets.  Once this frame has been
+both sent and received, older keys can be safely discarded.
+
+The KEYS_ACTIVE frame contains no additional fields.
+
+The packet that carries a KEYS_ACTIVE frame determines which keys are active and
+usable.  The keys with the same key phase as those used in the packet that
+carries the KEYS_ACTIVE frame are active.
+
+An endpoint MUST send a KEYS_ACTIVE packet in the first packet it sends using
+keys, but only if it is also able to receive packets that are protected using

```suggestion
those keys, but only if it is also able to receive packets that are protected using
```

> +both sent and received, older keys can be safely discarded.
+
+The KEYS_ACTIVE frame contains no additional fields.
+
+The packet that carries a KEYS_ACTIVE frame determines which keys are active and
+usable.  The keys with the same key phase as those used in the packet that
+carries the KEYS_ACTIVE frame are active.
+
+An endpoint MUST send a KEYS_ACTIVE packet in the first packet it sends using
+keys, but only if it is also able to receive packets that are protected using
+the corresponding keys.
+
+KEYS_ACTIVE frames are retransmitted when declared lost, however implementations
+need to take care not to retransmit lost KEYS_ACTIVE frames if they initiate a
+subsequent key update.  This can happen if an acknowledgment for a packet
+containing a KEYS_ACTIVE frame is lost.

As I wrote above, I don't understand how this can happen.

> +
+The packet that carries a KEYS_ACTIVE frame determines which keys are active and
+usable.  The keys with the same key phase as those used in the packet that
+carries the KEYS_ACTIVE frame are active.
+
+An endpoint MUST send a KEYS_ACTIVE packet in the first packet it sends using
+keys, but only if it is also able to receive packets that are protected using
+the corresponding keys.
+
+KEYS_ACTIVE frames are retransmitted when declared lost, however implementations
+need to take care not to retransmit lost KEYS_ACTIVE frames if they initiate a
+subsequent key update.  This can happen if an acknowledgment for a packet
+containing a KEYS_ACTIVE frame is lost.
+
+Endpoints MUST NOT send KEYS_ACTIVE frames in Initial or 0-RTT packets.
+

I would move these last 3 paras to a new subsection called "Key Updates During the Handshake" in the "Key Update" section above.

> +keys, but only if it is also able to receive packets that are protected using
+the corresponding keys.
+
+KEYS_ACTIVE frames are retransmitted when declared lost, however implementations
+need to take care not to retransmit lost KEYS_ACTIVE frames if they initiate a
+subsequent key update.  This can happen if an acknowledgment for a packet
+containing a KEYS_ACTIVE frame is lost.
+
+Endpoints MUST NOT send KEYS_ACTIVE frames in Initial or 0-RTT packets.
+
+A KEYS_ACTIVE frame used during the handshake can be used to indicate the
+availability of Handshake keys by including it in a Handshake packet.  An
+endpoint sends this frame in its first Handshake packet.  Once received, an
+endpoint can discard Initial keys.
+
+A KEYS_ACTIVE frame used after the completion of the handshake in 1-RTT packets

```suggestion
A KEYS_ACTIVE frame used in 1-RTT packets immediately after the completion of the handshake
```
(not any time after handshake but immediately after)

> +the corresponding keys.
+
+KEYS_ACTIVE frames are retransmitted when declared lost, however implementations
+need to take care not to retransmit lost KEYS_ACTIVE frames if they initiate a
+subsequent key update.  This can happen if an acknowledgment for a packet
+containing a KEYS_ACTIVE frame is lost.
+
+Endpoints MUST NOT send KEYS_ACTIVE frames in Initial or 0-RTT packets.
+
+A KEYS_ACTIVE frame used during the handshake can be used to indicate the
+availability of Handshake keys by including it in a Handshake packet.  An
+endpoint sends this frame in its first Handshake packet.  Once received, an
+endpoint can discard Initial keys.
+
+A KEYS_ACTIVE frame used after the completion of the handshake in 1-RTT packets
+indicates that Handshake keys are no longer needed.  A client sends this frame

```suggestion
indicates that Handshake keys are no longer needed.  A client SHOULD send this frame
```

> +
+KEYS_ACTIVE frames are retransmitted when declared lost, however implementations
+need to take care not to retransmit lost KEYS_ACTIVE frames if they initiate a
+subsequent key update.  This can happen if an acknowledgment for a packet
+containing a KEYS_ACTIVE frame is lost.
+
+Endpoints MUST NOT send KEYS_ACTIVE frames in Initial or 0-RTT packets.
+
+A KEYS_ACTIVE frame used during the handshake can be used to indicate the
+availability of Handshake keys by including it in a Handshake packet.  An
+endpoint sends this frame in its first Handshake packet.  Once received, an
+endpoint can discard Initial keys.
+
+A KEYS_ACTIVE frame used after the completion of the handshake in 1-RTT packets
+indicates that Handshake keys are no longer needed.  A client sends this frame
+in its first 1-RTT packet, and a server sends this frame in the first packet it

```suggestion
in its first 1-RTT packet, and a server SHOULD send this frame in the first packet it
```

> +KEYS_ACTIVE frames are retransmitted when declared lost, however implementations
+need to take care not to retransmit lost KEYS_ACTIVE frames if they initiate a
+subsequent key update.  This can happen if an acknowledgment for a packet
+containing a KEYS_ACTIVE frame is lost.
+
+Endpoints MUST NOT send KEYS_ACTIVE frames in Initial or 0-RTT packets.
+
+A KEYS_ACTIVE frame used during the handshake can be used to indicate the
+availability of Handshake keys by including it in a Handshake packet.  An
+endpoint sends this frame in its first Handshake packet.  Once received, an
+endpoint can discard Initial keys.
+
+A KEYS_ACTIVE frame used after the completion of the handshake in 1-RTT packets
+indicates that Handshake keys are no longer needed.  A client sends this frame
+in its first 1-RTT packet, and a server sends this frame in the first packet it
+sends after completing the handshake.  A server might send 1-RTT keys prior to

A server never sends 1-RTT keys. I'm not sure what this sentence is trying to say.

-- 
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/pull/2237#pullrequestreview-203548487