Re: Key updates

Martin Thomson <> Tue, 07 August 2018 06:37 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 6CDA5130FA8 for <>; Mon, 6 Aug 2018 23:37:31 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -2
X-Spam-Status: No, score=-2 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: (amavisd-new); dkim=pass (2048-bit key)
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id reWjBNR9tgmb for <>; Mon, 6 Aug 2018 23:37:21 -0700 (PDT)
Received: from ( [IPv6:2607:f8b0:4003:c06::232]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by (Postfix) with ESMTPS id 6CC26130FBB for <>; Mon, 6 Aug 2018 23:37:21 -0700 (PDT)
Received: by with SMTP id v8-v6so26559135oie.5 for <>; Mon, 06 Aug 2018 23:37:21 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=gi4Mi9vnvsU9VgVl+jPW9EsOxh32tfbtn2E4/45PPOI=; b=LNmsnBAOdTZ8deZLPTNBmXcuE37Ut/EPbqulv/CP/fXQ4cg5k0WnE53irx0IgWcQWx G1+VnOtYV+KzKUQt67Z6lTM/Gaq7t5Lxu3HUhna4J0PEFrSoZz339LH7fEIkm9SInRqA 84wbrUOTzG9Xt1zRftbyYs1hMeF/5Iz3xC4zcdnJaw/yRDEvwCPY/olDlQ6OkwNmMm6K hd0D2wht7pVO/ok9Uj1KCTgxwcVQ8IG8ufU5UfQlmOzJx0PpsAghJh0Nzk4m7Ta3Bm2T Rx01bFa75XR4XPv2+yVjHCcrwFciR4/rxGFj1AoCDKkSDZFoDAo+zMRh1fmtuDuGEHcY TCLA==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=gi4Mi9vnvsU9VgVl+jPW9EsOxh32tfbtn2E4/45PPOI=; b=Kk4W8R5/lC/psucQY5TqovCXWtQ2NbeiyW2iJN+3A9mTu5M6TWq4/uSdBKbJocqbUv zGs8bgKUVDieFIvBLBJGiPrREdugrsJqe/QVb9X9I51YCz/thaJiDuFZ2ImU0N95gsLi AHFk59IoTrTSF45F5ySbS/7y2E/Ipuo8Y9DJP96X/oRB/uIi8O2wW0/sbhxmZdW+EsO/ lGeRhCM+vNkuWr1094NWc5/pNXTV/zM1v1RDNYCA41ZFRH8zxaoIBJbOTFtpsUc96guK Ii3w2ouj5ZX4uIrQTWS7md7u2/hskEIXTakCg3Hgsfj9OUes7vB//Ck4e3/s4+Zij0UI rGzA==
X-Gm-Message-State: AOUpUlG+7cwbp401QHtuSuThmgy87Vc7H+JQh1HhuukmnRInsNsY6R+X /ZYPe0Th4MIUVAsjNfKZ38+oPw62lB8BRXPcnNk=
X-Google-Smtp-Source: AAOMgpfP87OsQl22idMiHGMGoPYNooDi7nLtmKw+dXwJLs9N+6N7XVqG5fwyEwUK5obtYn2tLrMBn9bF39weg8yk/RA=
X-Received: by 2002:aca:3d56:: with SMTP id k83-v6mr16905419oia.166.1533623840611; Mon, 06 Aug 2018 23:37:20 -0700 (PDT)
MIME-Version: 1.0
References: <> <> <> <>
In-Reply-To: <>
From: Martin Thomson <>
Date: Tue, 7 Aug 2018 16:37:09 +1000
Message-ID: <>
Subject: Re: Key updates
To: Kazuho Oku <>
Cc: QUIC WG <>
Content-Type: text/plain; charset="UTF-8"
Archived-At: <>
X-Mailman-Version: 2.1.27
Precedence: list
List-Id: Main mailing list of the IETF QUIC working group <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
X-List-Received-Date: Tue, 07 Aug 2018 06:37:38 -0000

On Tue, Aug 7, 2018 at 4:10 PM Kazuho Oku <> wrote:
> > There is a problem right now with concurrent updates.  If both peers
> > bump at the same time, then N-1 packets could still be in flight.
> I think that we might be having different models in our minds.
> My view is that, in principle, an endpoint unilaterally updates its
> epoch that it uses for "sending" packets. An endpoint MUST NOT update
> the send epoch before it sees an acknowledgement for a packet that was
> sent encrypting using the current epoch.
> To implement reciprocal key update, we will also state that, if the
> send epoch used by the peer becomes greater than the value used by an
> endpoint, then the endpoint SHOULD increment it's send epoch as well.
> If we define the rules this way, I would assume that there is not
> chance of key getting updated twice even in case both the peers decide
> to update at the same moment.
> To put it another way, the issue with the reciprocal (D)TLS-style key
> update is that it is defined as a "request" rather than a state change
> with idempotency. The rules above is designed as an idempotent state
> change from N to N+1 that can be implemented by either peer without
> the fear of double update that will lead to potential loss (unless the
> endpoints retains more than two keys).

There is nothing inherently wrong with the current design, but I
recently realized that there is a corner case that is awkward at best
without trial decryption, even if you follow those rules.

A sends N+1
B sends N followed by N+1 around the same time.
0.5 RTT later both receive a packet at N+1, so both update (not
naturally noticing that the response was a little faster than it
should have been).
A receives the packet from B at N, reordered a little (maybe the N+1
was a small packet at the tail of a burst).
A thinks that this is N+2 and discards it.

Now, this isn't a correctness issue.  But it's annoying.  It drives
the congestion controller down more than is ideal and adds a bit of
extra latency for anything depending on the contents of that packet
(or those packets if there is more than one).

You fix this by running trial decryption for N and N+2 for a short
time, or you move to the prepare-commit style of update.

> I think that the described algorithm will work fine, but I am not sure
> if I like the fact that it requires the QUIC stack to remember the new
> encryption key and the fact that a KeyUpdate message has been sent in
> a CRYPTO frame at certain offset, and switch to the new key when all
> the data up to that offset is acknowledged.

The QUIC stack doesn't have to remember anything other than that is
received new TLS data at epoch N and a key change after that.  The
rules for transmitting CRYPTO frames at the same encryption level
ensure that everything works correctly.  Now it has new send keys, but
the only new rule it needs would be that until all crypto frames for N
are acknowledged, you can't starting sending on N+1.  I tend to think
of this as not being a new rule, but instead that there are
exceptional rules for this during the handshake.

The rules for receiving are different: you install N+1 for reading
immediately (discarding N-1 if that is still around).  You can discard
N+1 on a timer (that can start immediately, I think, based on what I
worked out for key expiration timers, which I am about to put up as a