Re: [quicwg/base-drafts] token-based greasing / initial packet protection (#3166)

David Schinazi <> Tue, 29 October 2019 17:41 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 7CF0B1200F5 for <>; Tue, 29 Oct 2019 10:41:31 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -8
X-Spam-Status: No, score=-8 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_HELO_NONE=0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: (amavisd-new); dkim=pass (1024-bit key)
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id miDraWpcIetA for <>; Tue, 29 Oct 2019 10:41:29 -0700 (PDT)
Received: from ( []) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by (Postfix) with ESMTPS id C8375120018 for <>; Tue, 29 Oct 2019 10:41:28 -0700 (PDT)
Received: from ( []) by (Postfix) with ESMTP id 14C038C0783 for <>; Tue, 29 Oct 2019 10:41:28 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=pf2014; t=1572370888; bh=6RPiaa0NnNG1b7fK3nsHFvS2+wYzf4xZG2cydc7fdao=; h=Date:From:Reply-To:To:Cc:In-Reply-To:References:Subject:List-ID: List-Archive:List-Post:List-Unsubscribe:From; b=IJhkal2T/sUWE1BnlOTEYoCsAruTZmTPZNrGp6FKp+UMmuX4hxoAfR4S2iU0dbQR5 hb3aIB0YRcDwGj6OYvXyQVQUqgBbMgVdJOU8YeXghpyydm19WIBb/81lpFsNKk03aD WM5Hlrb8pg74LJoFQHd9I04GVnb2tIxryV0Zsiws=
Date: Tue, 29 Oct 2019 10:41:27 -0700
From: David Schinazi <>
Reply-To: quicwg/base-drafts <>
To: quicwg/base-drafts <>
Cc: Subscribed <>
Message-ID: <quicwg/base-drafts/pull/3166/review/>
In-Reply-To: <quicwg/base-drafts/pull/>
References: <quicwg/base-drafts/pull/>
Subject: Re: [quicwg/base-drafts] token-based greasing / initial packet protection (#3166)
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary="--==_mimepart_5db879c7e4ce2_60323fcec2ecd968435b9"; charset="UTF-8"
Content-Transfer-Encoding: 7bit
Precedence: list
X-GitHub-Sender: DavidSchinazi
X-GitHub-Recipient: quic-issues
X-GitHub-Reason: subscribed
X-Auto-Response-Suppress: All
Archived-At: <>
X-Mailman-Version: 2.1.29
List-Id: Notification list for GitHub issues related to the QUIC WG <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
X-List-Received-Date: Tue, 29 Oct 2019 17:41:32 -0000

DavidSchinazi commented on this pull request.

Thanks for writing this up! I like the token approach but we might need to tighten how this interacts with version negotiation.

> @@ -2721,6 +2721,66 @@ between endpoints.  Application protocols SHOULD define rules for handling
 streams that are prematurely cancelled by either endpoint.
+# Alternative Initial Set {#alternative-initial}
+In order to avoid ossification of the cleartext and obfuscated fields of QUIC
+packets, a server can announce an alternative set of initial values to be used,
+which is comprised of:
+* Alternative version number; a 32-bit unsigned number that is to be presented
+  on wire in place of the version number specified in this document.  This value
+  MUST NOT be a reserved version ({{versions}}).
+* Packet type modifier; a two-bit value that is to be applied as a bit-wise
+  exclusive or (XOR) to the most significant bits of the Initial, Handshake,

Shouldn't this be `to the Long Packet Type field of` instead of `to the most significant bits of` ?

> +  0-RTT, and Retry packets. This XOR is applied after the packets are encrypted
+  and before they are decrypted.
+* Alternative initial salt; a 16-byte binary blob that is to be used in place of
+  the initial salt defined in section 5.2 of {{QUIC-TLS}}.
+A server advertises these values using a NEW_TOKEN frame {{frame-new-token}}.
+The token MUST include or associated with the alternative version number with
+which it can be used.
+Typically, a server would pre-allocate a set of unused version numbers as the
+alternative version numbers, associating each of those version numbers with a
+packet type modifier chosen at random.  Then, when issuing a token using a
+NEW_TOKEN frame, the server generates the alternative initial salt by calling a
+pseudo-random function, embeds that initial salt into the token which is then
+encrypted, and sends a NEW_TOKEN frame that comprises of the generated token and

I might be worth adding a bit more detail to how the token is encrypted, perhaps `which is then encrypted using a key only known to the server`

> +NEW_TOKEN frame, the server generates the alternative initial salt by calling a
+pseudo-random function, embeds that initial salt into the token which is then
+encrypted, and sends a NEW_TOKEN frame that comprises of the generated token and
+the alternative initial set.
+When the client reconnects to the server by using the provided token and the
+alternative initial set, the server first checks if the version number field of
+the incoming packet contains one of the alternative version numbers it
+advertises, then if that is the case, applies the corresponding packet type
+modifier to recover the correct packet type.  If the recovered packet type is an
+Initial packet and that packet contains a NEW_TOKEN token, the server decrypts
+the embedded token and recovers the alternative initial salt, uses that to
+decrypt the payload of the Initial packet.
+When the server is incapable of determining the alternative initial salt, it can
+send a Version Negotiation packet that instructs the client to use the default

In the current spec, the client fails the connection upon receipt of a Version Negotiation packet. So this has a dependency on the version downgrade prevention extension.

But assuming the presence of a version negotiation mechanism with downgrade prevention, I think we have an issue here. If the server rotates the key it uses to encrypt the alternative initial salt, and then receives a token it can no longer decrypt, it sends a version negotiation packet, and the client tries again with QUICv1. This is likely to trip the version downgrade prevention mechanism - how do we distinguish between a server that has forgotten their key and an attacker that is trying to force a downgrade to QUICv1?

> @@ -3940,6 +4007,19 @@ described in {{QUIC-TLS}}.  This protection does not provide confidentiality or
 integrity against on-path attackers, but provides some level of protection
 against off-path attackers.
+Additionally, the token is accompanied by a checksum.  This is because when a

Seeing a checksum here makes me uncomfortable. We're adding a checksum to retry packets because they have no other mechanism to detect corruption. Initial packets on the other hand have an auth tag, so a corrupted token will cause the deprotection to fail. In an ideal world we should handle that like any other corruption on the initial packet. But I think this goes back to my other question about version negotiation, I think there be dragons.

You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub: