Re: [TLS] Cleaning up 0-RTT Signaling (ciphersuites, replays, PSK context)

Eric Rescorla <ekr@rtfm.com> Fri, 25 March 2016 17:06 UTC

Return-Path: <ekr@rtfm.com>
X-Original-To: tls@ietfa.amsl.com
Delivered-To: tls@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 3BB4612D15F for <tls@ietfa.amsl.com>; Fri, 25 Mar 2016 10:06:27 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.599
X-Spam-Level:
X-Spam-Status: No, score=-2.599 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_LOW=-0.7] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=rtfm-com.20150623.gappssmtp.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 9z4sHQGgEZKj for <tls@ietfa.amsl.com>; Fri, 25 Mar 2016 10:06:24 -0700 (PDT)
Received: from mail-qk0-x22d.google.com (mail-qk0-x22d.google.com [IPv6:2607:f8b0:400d:c09::22d]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 2525512D122 for <tls@ietf.org>; Fri, 25 Mar 2016 10:06:24 -0700 (PDT)
Received: by mail-qk0-x22d.google.com with SMTP id s5so33819687qkd.0 for <tls@ietf.org>; Fri, 25 Mar 2016 10:06:24 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rtfm-com.20150623.gappssmtp.com; s=20150623; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=g977soxxDTbI1sWv7xClOuLZUEyYRrCPiZAmrdO92PM=; b=w113crI7hPNqPscME+7TigZYtAXjw398LbSUEZdMHGfPT0jQfQK5RU1Z6uG48HkU3T ZXPG7Wh97sgLrgh5lEP0lB4n9dF9kjs2TikGcwQKS7UZ0xkVgUwr4VY2O83J+sgbWD+S gYzZlI5jEEh6nQycfSDoCgzPrB8pFoYkO46l96nTFY7DioONcg/v9uH94UZvxvYoFm1Z GgXiLJni0QxFKjiERL3HTP6SgxuOtCI5SIb8ij12NJBqfFMieSAMX0jiExVVcgPTsV/U Q1FyUHrGdVgaf2gcELDJqwPGxgKrPAVMD2sbqrBmCSaLgAwL3RU/Qt1wDQYvvsOuDo0w tXfg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=g977soxxDTbI1sWv7xClOuLZUEyYRrCPiZAmrdO92PM=; b=Sqh2xomm7hLkfRrebA+ZHiNvusUJRMejmhRK9+POAexLd/z4ADpFWsSHOt9OIt+kDc eAA1bF0xeCHSlJ97PeGMGI+NiChbrk/90aJMXy2BEg3c4PClmLC3E9oLjNspMP5DbK5S /ozPRjrXQLQBNidSNaCEbT8c/HWtfJnCHj2sQ5OWXlOqkuXXgkdwFTmwxsGVNMSgF7tW oaK6ZTEFTu71oEAwTJanxOzmrhm3D+8tcIkln56LZV0o6pORjGaz3Ykxvct5ltn0RLWa ta0FZp8Eh3ETatV3lTcwxDw0MYg8FxeyQ1N253UNfZF0+tue5QmAbcV0ttNpd/suRxp4 6DrQ==
X-Gm-Message-State: AD7BkJKHXdEJAPpy7p4vqKvptMi6t3BckSd7IelzhhBK0UBgjOH5c2eRU5pwUv/P11Qn8pj80qiFmfov0gD8Jg==
X-Received: by 10.37.230.212 with SMTP id d203mr8432339ybh.74.1458925583155; Fri, 25 Mar 2016 10:06:23 -0700 (PDT)
MIME-Version: 1.0
Received: by 10.13.249.5 with HTTP; Fri, 25 Mar 2016 10:05:43 -0700 (PDT)
In-Reply-To: <BC748097-6833-4BEB-9282-AF278B00FB96@inria.fr>
References: <BC748097-6833-4BEB-9282-AF278B00FB96@inria.fr>
From: Eric Rescorla <ekr@rtfm.com>
Date: Fri, 25 Mar 2016 10:05:43 -0700
Message-ID: <CABcZeBOP08V6obrN1vQkXkvFEXdux33mu_8zn=uyFo2OVim7Eg@mail.gmail.com>
To: Karthik Bhargavan <karthikeyan.bhargavan@inria.fr>
Content-Type: multipart/alternative; boundary="94eb2c0a79ca239c38052ee29585"
Archived-At: <http://mailarchive.ietf.org/arch/msg/tls/fGzp6hv5NPYPSij2iE5XQEOBPUQ>
Cc: "tls@ietf.org" <tls@ietf.org>
Subject: Re: [TLS] Cleaning up 0-RTT Signaling (ciphersuites, replays, PSK context)
X-BeenThere: tls@ietf.org
X-Mailman-Version: 2.1.17
Precedence: list
List-Id: "This is the mailing list for the Transport Layer Security working group of the IETF." <tls.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/tls>, <mailto:tls-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/tls/>
List-Post: <mailto:tls@ietf.org>
List-Help: <mailto:tls-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/tls>, <mailto:tls-request@ietf.org?subject=subscribe>
X-List-Received-Date: Fri, 25 Mar 2016 17:06:27 -0000

Karthik,

Thanks for sending this. Some initial thoughts below.

> After implementing and analyzing TLS 1.3, here are a few suggestions for
discussion.
>
> 1) Early Data Extension
>
> The current early-data extension is too DH-specific.
> When using PSK, we now have to look at both early_data and pre_shared
extensions.
> I suggest reusing the same extension for both, with the following
interpretation:
>
>         struct {
>           select (Role) {
>               case client:
>                   opaque id<1..2^16-1>;
>                   opaque context<0..255>;
>                   CipherSuite cipher_suite;
>                   Extension extensions<0..2^16-1>;
>
>               case server:
>                  struct {};
>                 }
>         } EarlyDataIndication;
>
>
> In the semi-static DH case:
> - id is the configuration id
> - context is the hash of the ServerConfiguration + Server Certificate +
CertificateRequest
>
> In the PSK resumption case:
> - id is the session ticket
> - context is a *public* value unique to the derived session. For example,
it could be defined as the session hash of the original handshake,
>   or it could be derived by the client as HKDF(RMS, “early data context”)
>
> In the pure PSK case
> - id is the PSK identifier
> - context is unique to the PSK and its allowed use.
>   For example, it can be generated (out-of-band) as HKDF(PSK, “early data
context”)

There seem to be several ideas here:

1. Dispose of PreSharedKey and only use EarlyDataIndication.
2. Have an explicit context field that is derived in a deterministic
fashion.


I'm not sure that the first of these is a good idea, for several reasons.

1. While it's not sensible to have 0-RTT data encrypted with multiple
PSKs, it's not at all silly for the client to offer multiple PSKs to
the server. Note that the current TLS 1.2 PSK extension allows the
server to provide a hint on the theory that the client might have more
than one PSK. Having separate extensions allows this.

2. It burdens servers and clients which don't want to do 0-RTT (but do
want to do PSK-resumption) with 0-RTT machinery. This is a particular
concern with the extension version proposed above because it doesn't
give the client any way to say "this is just a resumption, I'm not
sending any 0-RTT data". This means that servers have to at least
implement the 0-RTT skipping algorithm even if they refuse 0-RTT. [You
could say that the server had indicated "I won't accept 0-RTT" when it
established the ticket, and then act as if the client complied but
that produces a really ugly decryption failure rather than a handshake
failure]. We'd at least want to restore the EarlyDataType value from
previous versions of EarlyDataIndication so that the client could
express what it did here.


The second idea seems sensible, and I do like the idea of binding the
session hash of the previous handshake into PSK-Resumption. One thing
that seems unclear would be what the responsibilities of the server
are with respect to the context. In the current draft, the client
and server both digest it explicitly but it's not signalled, which
has the disadvantage that you can't just run the session transcript
forward. If the client just provides it to the server, then that
seems to have different security properties unless we require the
server to verify it. Is that what you have in mind here?

I note that the context value here was intended for a different
purpose, namely tying the handshake to some external context (for
instance, if you have an external anti-replay mechanism). I'm not sure
if that's still valuable, but if we wanted to do so, then we'll need a
separate field somewhere.


Another possible design here would be:

        struct {
           opaque psk_identity<0..2^16-1>;
           opaque context<0..255>;
        } PreSharedKeyInfo;

        struct {
           select (Role) {
               case client:
                   PreSharedKeyInfo keys<2..2^16-1>;

               case server:
                   uint16 index;  // The selected index
           }
         } PreSharedKeyExtension;


         struct {
           select (Role) {
               case client:
                   CipherSuite cipher_suite;
                   select (key_exchange) {
                      case PSK:
                         uint16 index;   // PSK index

                      case (EC)DHE
                         opaque configuration_id<1..2^16-1>;
                         opaque server_context<0..255>; //
ServerConfiguration + Server Certificate + CertificateRequest
                   }
                   Extension extensions<0..2^16-1>;

               case server:
                  struct {};
                 }
         } EarlyDataIndication;

It's not super-elegant to have a switch here in the decode for
EarlyDataIndication, but they actually are semantically different, so
I'm not sure it's that bad. The idea here would be to design to a
different invariant, namely:

- The client gets to offer the server a bunch of options for the
  1-RTT handshake. The server picks one.

- The client offers the server exactly one option for 0-RTT and
  the server can take it or leave it.

This is the way that 0-RTT DHE works now. It does open the door
to the server somehow picking a different option for 1-RTT than
the client chose for 0-RTT, but this is something we could forbid.


> 2) New Session Ticket
>
> The NewSessionTicket message needs to indicate whether the server will
accept 0-RTT,
> and what ciphersuites it is willing to accept (e.g. pure PSK resumption
vs only PSK-ECDHE).

> I suggest the following modification to this message:
>         struct {
>          uint32 ticket_lifetime;
>          opaque ticket<0..2^16-1>;
>          CipherSuite cipher_suites<2..2^16-2>;
>          EarlyDataType early_data_type
>         } NewSessionTicket;

The cipher suites indication seems generally sensible.


>         enum {
>           no_early_data_allowed(0),
>           replayable_early_data_allowed (1),
>           all_early_data_allowed(2),
>           (65535)
>        } EarlyDataType;
>
> The interpretation of the early_data_type field is that the server is
either:
> (a) unwilling to accept 0-RTT (no_early_data_allowed),
> (b) willing to accept 0-RTT, but it has no replay cache
(replayable_early_data_allowed),
> (c) willing to accept 0-RTT and has a replay cache that it uses to
prevent replay (all_early_data_allowed)

This is an interested suggestion. I agree that it's important to
be able to say "don't send me 0-RTT data" (see above). ISTM that
"all_early_data_allowed" would be useful primarily if we allowed
clients who received it to use the ordinary TLS 1.3 API for sending
0-RTT data. That would be a real advantage, it seems to me.



> There has been much discussion on 0-RTT replay and here’s a quick summary
of my understanding.
> We already knew that an active attacker, or a lossy network, or an
overzealous web browser could
> and would cause 0-RTT (and even 1-RTT) data to be replayed to the server.
This can already happen
> in TLS 1.2, in QUIC, and so we accepted it as a given in TLS 1.3.
>
> The new concerns on the mailing list (and in my TRON talk which was based
on a ProVerif model)
> are that unlike TLS 1.2:
> (a) even a passive attacker could replay 0-RTT data, long after the
client has gone away,

Nit: This doesn't sound like a passive attacker to me...


> Even if we eliminate client certificate authentication from 0-RTT, this
notion of “context" is still useful for two reasons:
> (a) the application may use TokenBinding or some such protocol to
authenticate 0-RTT data, and we need to understand what “channel binding”
to provide for this case,
> (b) in PSK resumption mode, since the handshake log does not contain much
information that is specific to the previous connection, it would be more
robust to add an explicit context.

Yes, I agree that this is an improvement.

-Ekr


On Fri, Mar 25, 2016 at 2:29 AM, Karthik Bhargavan <
karthikeyan.bhargavan@inria.fr> wrote:

> We currently allow 0-RTT with Semi-static DH, with PSK resumption, and
> with pure PSK.
> Whether or not we keep all of these, it would be good to clean up the
> protocol design
> so that both the client and server have a uniform way of signaling their
> preferences.
>
> After implementing and analyzing TLS 1.3, here are a few suggestions for
> discussion.
>
> 1) Early Data Extension
>
> The current early-data extension is too DH-specific.
> When using PSK, we now have to look at both early_data and pre_shared
> extensions.
> I suggest reusing the same extension for both, with the following
> interpretation:
>
>         struct {
>           select (Role) {
>               case client:
>                   opaque id<1..2^16-1>;
>                   opaque context<0..255>;
>                   CipherSuite cipher_suite;
>                   Extension extensions<0..2^16-1>;
>
>               case server:
>                  struct {};
>                 }
>         } EarlyDataIndication;
>
>
> In the semi-static DH case:
> - id is the configuration id
> - context is the hash of the ServerConfiguration + Server Certificate +
> CertificateRequest
>
> In the PSK resumption case:
> - id is the session ticket
> - context is a *public* value unique to the derived session. For example,
> it could be defined as the session hash of the original handshake,
>   or it could be derived by the client as HKDF(RMS, “early data context”)
>
> In the pure PSK case
> - id is the PSK identifier
> - context is unique to the PSK and its allowed use.
>   For example, it can be generated (out-of-band) as HKDF(PSK, “early data
> context”)
>
> 2) New Session Ticket
>
> The NewSessionTicket message needs to indicate whether the server will
> accept 0-RTT,
> and what ciphersuites it is willing to accept (e.g. pure PSK resumption vs
> only PSK-ECDHE).
>
> I suggest the following modification to this message:
>         struct {
>          uint32 ticket_lifetime;
>          opaque ticket<0..2^16-1>;
>          CipherSuite cipher_suites<2..2^16-2>;
>          EarlyDataType early_data_type
>         } NewSessionTicket;
>
>         enum {
>           no_early_data_allowed(0),
>           replayable_early_data_allowed (1),
>           all_early_data_allowed(2),
>           (65535)
>        } EarlyDataType;
>
> The interpretation of the early_data_type field is that the server is
> either:
> (a) unwilling to accept 0-RTT (no_early_data_allowed),
> (b) willing to accept 0-RTT, but it has no replay cache
> (replayable_early_data_allowed),
> (c) willing to accept 0-RTT and has a replay cache that it uses to prevent
> replay (all_early_data_allowed)
>
> The client’s response to this ticket message should be to store it in its
> session along with the “context” (session hash or derived from RMS),
> the allowed cipher suites, and the early_data_indication.
>
> When resuming with this ticket:
> - the client should not send any 0-RTT data if no_early_data_allowed
> - the client should only send replayable data if
> replayable_early_data_allowed (e.g. GET requests)
> - the client can send any 0-RTT data if all_early_data_allowed, trusting
> the server to do the right thing.
>
>
> A note on replay
> ----------------------
>
> There has been much discussion on 0-RTT replay and here’s a quick summary
> of my understanding.
> We already knew that an active attacker, or a lossy network, or an
> overzealous web browser could
> and would cause 0-RTT (and even 1-RTT) data to be replayed to the server.
> This can already happen
> in TLS 1.2, in QUIC, and so we accepted it as a given in TLS 1.3.
>
> The new concerns on the mailing list (and in my TRON talk which was based
> on a ProVerif model)
> are that unlike TLS 1.2:
> (a) even a passive attacker could replay 0-RTT data, long after the client
> has gone away,
> (b) replaying authenticated 0-RTT data can be more damaging (whether
> authenticated with client cert or with a cookie), and
> (c) by replaying 0-RTT data, the attacker can obtain encrypted 0.5-RTT
> data which opens up new attack vectors.
>
> As a result of these new concerns, I would say that TLS 1.3 should
> recommend that all servers SHOULD
> implement a replay cache, and those that cannot should clearly signal this
> to the client, so that the client
> can adjust its 0-RTT use case and its expectations accordingly.
>
> A note on authenticating the 0-RTT “context”
> ----------------------------------------------------------
>
> When trying to figure out how to authenticate 0-RTT DH mode in an earlier
> draft, we came upon the
> design of signing the Handshake Context that consists of the ClientHello +
> additional information from the previous handshake.
> This construction prevents 0-RTT authentication from unknown key share
> attacks.
>
> Even if we eliminate client certificate authentication from 0-RTT, this
> notion of “context" is still useful for two reasons:
> (a) the application may use TokenBinding or some such protocol to
> authenticate 0-RTT data, and we need to understand what “channel binding”
> to provide for this case,
> (b) in PSK resumption mode, since the handshake log does not contain much
> information that is specific to the previous connection, it would be more
> robust to add an explicit context.
>
> If we accept the definition of “context” in the EarlyDataIndication
> extension, then we can use the hash of the ClientHello uniformly in all
> 0-RTT modes for deriving keys, and for deriving a channel binding for the
> application. Furthermore, we can safely introduce a PSK_ECDHE
> mode where the server sends its Certificate and CertificateVerify and its
> signature is correctly bound to the PSK (via the “context” field).
>
> Best regards,
> Karthik
>
>
>
>
>
> _______________________________________________
> TLS mailing list
> TLS@ietf.org
> https://www.ietf.org/mailman/listinfo/tls
>