Re: Key updates

Kazuho Oku <> Tue, 07 August 2018 04:55 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 37848130E6B for <>; Mon, 6 Aug 2018 21:55:49 -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 zWRpCRQXgTts for <>; Mon, 6 Aug 2018 21:55:47 -0700 (PDT)
Received: from ( [IPv6:2a00:1450:4864:20::12d]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by (Postfix) with ESMTPS id 985DB130E69 for <>; Mon, 6 Aug 2018 21:55:46 -0700 (PDT)
Received: by with SMTP id v22-v6so10652873lfe.8 for <>; Mon, 06 Aug 2018 21:55:46 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=MV/lJRx/z/ALWE2gG/2gBDeflVaBLZeEB4VQn3VHDh4=; b=hUJa4P0jwU9t5kVB3RDCajmLhgpcWzfxDmdN0lnu17F+/KGQVjJM+b+NXeibck36ZI Ca6ae/Nc7X3+YvaKIlHqvwc/U98RdhLQzAgBwoLG7EwyDCPSPT4mW3XvLKi22EpQ/GJH nAxT5DmX5u4o1jRAT8HRCwcYm4B7wqsdlincu78+OSwxuRBiFp6g7+fYVsZVvNZ4kTEv bZElzcqFL13wqN0zkyKp7nsgDUBaH8k0Y2s/gBq/+iB6dTxAHwoHB70Dp6DfsSOdGSZH L0dhXUCfi7M48W6yWs3ZQIspk3+1URjzCj1sL9ziTuSYyTCRvg76lTP7p5vpeuU4Fr7e joTw==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=MV/lJRx/z/ALWE2gG/2gBDeflVaBLZeEB4VQn3VHDh4=; b=toPDCwE8lUsWt+Yn8UBzh+0W/MMrHU6SWlAPel73mcHHpV5TYGlYPtoxzv7dSfLtPw RJGMyEG3VfxAUH9GLqlw/sNu1EPwKUBgt8XvHiSutfEdjrQIwjVrr+OJX7CW+AS0Umln VGJ0rWPRe/SOQPjzFN6GyPPCZs3LZ62GNuilD3OYWH1RyVyGpd2zPF4ttNHQ+HSYxcmP BKTJbFPk3CFeiYKOzMPtxoiu0fP8JibDsYKMSjcgdpYCIzTLKe/464FcM3rol3yYH1P4 mcUMLXici/OK2r0adH5DP2oLMnAx0UWdoG2Z9iZxUCMsMUrT6kU9OyqlLJnv0L0EPLp8 kiuQ==
X-Gm-Message-State: AOUpUlEELkvG5xjks8CH0Sw9SaN/dv23p3J6023lgzKzMiFXTiupDD7L NckwYhOKQNVuu3edudNWOr7io5k06HxxO3L2bXs=
X-Google-Smtp-Source: AAOMgpfilKeJxeXtVMedUjS/lqqyy9kkdcFP7iwkObxZiWAK7IsizGDdqpDDHQ5yDX+reZLc+OE0pfSCuktHse2n/O8=
X-Received: by 2002:a19:6b03:: with SMTP id d3-v6mr12364723lfa.81.1533617744831; Mon, 06 Aug 2018 21:55:44 -0700 (PDT)
MIME-Version: 1.0
Received: by 2002:a2e:8996:0:0:0:0:0 with HTTP; Mon, 6 Aug 2018 21:55:44 -0700 (PDT)
In-Reply-To: <>
References: <>
From: Kazuho Oku <>
Date: Tue, 07 Aug 2018 13:55:44 +0900
Message-ID: <>
Subject: Re: Key updates
To: Martin Thomson <>
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 04:55:49 -0000

2018-08-06 14:55 GMT+09:00 Martin Thomson <>:
> One of the open items out of the design team work was the interaction
> between TLS and key updates.  As you might know, TLS key updates are
> synchronous, which works well in TCP, but less well in QUIC, where you
> need at least two active keys for reception around a key change.
> As it is, I think that there are two serious options:
> 1. Use KEY_PHASE to signal a change.  This requires that both
> endpoints are loosely synchronized, which disadvantages asymmetric
> data exchanges.
> 2. Use a prepare-commit style.  DTLS does this by having each peer
> send a KeyUpdate message, then requiring that to be acknowledged
> before they can switch to the new epoch. QUIC could do the same. The
> change is still signaled in the key phase bit, but only after this
> signaling exchange.
> The weakness of the first option is that packets marked with a change
> of key phase trigger trial decryption.

I think that I might prefer option 1.

I do not think that the current mechanism requires trial decryption.
IIUC, the endpoints are not allowed to start sending packets at epoch
N+1 until they see peers acknowledging packets that were sent in epoch
N. That means that an endpoint only needs to have at most 2 keys (for
epoch N+1 and N). The epoch (either N or N+1) can be recovered from
the KEY_PHASE bit and there is no need for trial decryption.

Am I missing something?

The issue that might exist with option 2 is that it does not work well
with our model of using QUIC to transport TLS handshake messages.

In the model, the TLS stack never waits for ACK. Handling of
retransmits in the responsibility of QUIC. This is fine for
"handshake", because the moment when a new encryption key becomes
usable is indicated by a TLS message.

However, for key update, the TLS stack needs to wait for the peer to
acknowledge the receipt of the KeyUpdate message before it can start
using it. At least that is what is defined in the DTLS draft. Section
8 of the draft states, quote: "In order to facilitate epoch
reconstruction Section 4.2.2 implementations MUST NOT send with the
new keys or send a new KeyUpdate until the previous KeyUpdate has been
acknowledged (this avoids having too many epochs in active use)."

I am not sure if adding a way to signal the receipt of ACK for a
particular TLS message from QUIC to TLS stack is worth the cost. We do
not have that kind of mechanism. I am scared that such mechanism could
become very complex, considering the fact that the QUIC stack can
split TLS handshake in any way that it would like.

Or are you suggesting a mechanism other than what is defined in DTLS?

> And it requires synchronized
> changes, where if one endpoint moves to epoch N (epoch == encryption
> level with fewer characters to type), then the other has to follow
> before either can move to epoch N+1.  The second has more moving
> parts, but avoids both of these problems.
> I tend to think that the second is a better design on balance, if only
> to dispense with the trial decryption, which we've managed to avoid in
> every other case thus far.  The complication might also present some
> opportunities, which I will explain below, but that's a secondary
> concern.
> If we want to use this signaling method, we need to decide who drives
> key updating, TLS or QUIC:
> TLS: The DTLS design might work in QUIC, but with the KeyUpdate
> message hidden in an opaque CRYPTO frame, it could be a little tricky
> to manage properly.  If we let TLS drive the key update, then it will
> send a KeyUpdate message in a CRYPTO frame and inform QUIC of the
> change in sending keys.  From here, QUIC can keep using old keys until
> all CRYPTO frames from that epoch are acknowledged.  The receiver will
> inform QUIC of new receive keys when it receives KeyUpdate, which can
> be installed.
> QUIC: Here we define a new frame type (KEY_UPDATE, say) that QUIC
> sends when it wants to update keys.  When this is acknowledged, new
> keys can be installed and used for sending.  A new API is needed to
> TLS to support cranking the key schedule forward.  Invoking that API
> would lead to TLS signaling the availability of new keys.  The receive
> side isn't any different from the TLS option.  If this was to have
> parity with TLS, this would probably need to be two frame types so
> that a unilateral update could be distinguished from an update that
> includes a request for a mutual update.
> In both cases, QUIC will install new receive keys, but retain old
> receive keys so that it can deal with reordering.  A few round trips,
> an RTO, 2MSL, or whatever we decide for the handshake is probably
> fine.  Sending keys can be discarded immediately.
> The advantage of having TLS drive is that it uses the same machinery
> we have for the handshake.  And there is no disparity between what TLS
> and QUIC understand to be current: when TLS wants to send something (a
> NewSessionTicket message for example), then it asks for an epoch that
> matches what QUIC is using.
> The disadvantage of using TLS is that there are more moving parts
> involved.  It fits the rules we have for the handshake neatly: for
> instance, the CRYPTO frame would be retransmitted using the strict
> encryption-level rules, reusing that code from the handshake.  But
> those rules aren't really necessary given that the rules for a
> KEY_UPDATE easily have the same effect.
> My inclination here is to have TLS drive this.  The additional
> complexity seems to be manageable in the sense that it uses mechanisms
> that should already exist for the handshake.  I also don't think that
> a new API for this feature is a good way to ensure that it is used.
> Those who are implementing, I know that key updates are often a long
> way down the list of priorities, but has anyone spent time considering
> the options here?  (I personally implemented key updates for TLS, but
> I still haven't managed to find time to do it for DTLS, which might
> say something...)
> --
> Addendum: Optional Key Phase ?
> One of the nice things about either prepare-commit design is that it
> opens a new option for how we use bits in headers.  If there is a
> concern about spending a bit on every packet for the key phase (a
> whole bit!), we could design an encoding that only included the key
> phase if a longer packet number encoding was in use.
> The idea would be that you could use the longer packet number encoding
> while you have a key update outstanding, so that the key phase was
> available for the entirety of the changeover.  Once packets with the
> new epoch were acknowledged, you could switch back to a shorter
> encoding that didn't include a key phase.  The receiver would switch
> to expecting the new epoch after receiving the first packet in the new
> epoch.
> That's a saving that might allow endpoints to use the shortest packet
> number encoding in more cases.  Of course, the header design is
> already complex enough, so maybe we don't actually *want* more options
> to consider there :)

Kazuho Oku