Re: [TLS] implementing ESNI/ECH draft-09

David Benjamin <davidben@chromium.org> Tue, 02 March 2021 21:49 UTC

Return-Path: <davidben@google.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 930F03A1160 for <tls@ietfa.amsl.com>; Tue, 2 Mar 2021 13:49:30 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -9.496
X-Spam-Level:
X-Spam-Status: No, score=-9.496 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.248, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.25, HTML_MESSAGE=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001, USER_IN_DEF_SPF_WL=-7.5] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (1024-bit key) header.d=chromium.org
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 SVPfLchK3KKE for <tls@ietfa.amsl.com>; Tue, 2 Mar 2021 13:49:28 -0800 (PST)
Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) (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 425603A11A0 for <tls@ietf.org>; Tue, 2 Mar 2021 13:49:27 -0800 (PST)
Received: by mail-pl1-x62d.google.com with SMTP id s16so12807090plr.9 for <tls@ietf.org>; Tue, 02 Mar 2021 13:49:27 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=FwkGIkWVFSBGSi4Kuu+EQaZplWiuhZMYuvcc+dQwLjM=; b=ZiNL2IvC4yfUxKbAQwQd2P1FC9kwffJI1IX2W4gObxnkLynOQy6F+Dyv/77qj8pi2u 9CbAEW40avdqs6zbzNyFi+OfYgQ7XH8m16vjWKCiF50HCSp+itfgZD1GE13pa75UrBBh 4biJ1SZKdLk5pqTxtnZhw1NqAKjZshxKbRL3g=
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=FwkGIkWVFSBGSi4Kuu+EQaZplWiuhZMYuvcc+dQwLjM=; b=NMgHMlXeKu0LEb2zaiOs2W07wf1xJrEWeyiMCUVF135z6iOxZ67BStxQLovg/iZzQC 9zVxzIJ1fOAJTOUX8gjC02RU+DQVhrAq1qvZkAGBxMh0DgK34jnkFYPQwnXweKW+47sq Sd6mBHKNWoXaUBLyABTgHG5M4mf26B0miOTofHqpNegiO/Feq2+m1teBZ+7biodVa2Tu 9LYX8NGKL9ftauXliwT6HDxwlIKZLD8TVanwTCAVmsEd/63yTbnK4dIhyPxgbCJlLIGh YqL+koSgHIP2NHkopraEP/JsfafpeczqVpGuamGbM/SaNi8kb8R5dlsrnHogV49XErhK vjxA==
X-Gm-Message-State: AOAM532ke6/8mBDrF8MmxH3q6cL3feS7t8viai3j0E2kolssCHwF9Xdz znkbwuxiDVZLFmoYhnFBou2bELBTUYjlSO/rROE5yjJaew==
X-Google-Smtp-Source: ABdhPJzEoaYRCgMTDCN0PZX+rAvVdBLnEpX6UpwjVyMBHwcPjyuvyIG+U8HCHFasJvtx8dsN83FY2rIbnuT7mJYG/4k=
X-Received: by 2002:a17:90a:4f85:: with SMTP id q5mr6146497pjh.42.1614721765445; Tue, 02 Mar 2021 13:49:25 -0800 (PST)
MIME-Version: 1.0
References: <29b50ab1-a76f-e72d-28d8-b975e39a1f10@cs.tcd.ie>
In-Reply-To: <29b50ab1-a76f-e72d-28d8-b975e39a1f10@cs.tcd.ie>
From: David Benjamin <davidben@chromium.org>
Date: Tue, 02 Mar 2021 16:49:08 -0500
Message-ID: <CAF8qwaACXfHcn06p6sPXju9Bzzaj_1U1AMkUWCE+VBKdRzEXvg@mail.gmail.com>
To: Stephen Farrell <stephen.farrell@cs.tcd.ie>
Cc: "tls@ietf.org" <tls@ietf.org>
Content-Type: multipart/alternative; boundary="0000000000003e0e3505bc94b5f5"
Archived-At: <https://mailarchive.ietf.org/arch/msg/tls/dJemdTEuQxMMfxtqoU93NFd8W08>
Subject: Re: [TLS] implementing ESNI/ECH draft-09
X-BeenThere: tls@ietf.org
X-Mailman-Version: 2.1.29
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: Tue, 02 Mar 2021 21:49:36 -0000

On Sun, Feb 28, 2021 at 12:35 PM Stephen Farrell <stephen.farrell@cs.tcd.ie>
wrote:

> - This is *much* harder to implement compared to ESNI as
>    it interacts with the rest of the TLS stack/library in
>    many more ways. It should be an explicit goal to reduce
>    that complexity IMO and not increase it further.  That
>    complexity leads to *many* new failure modes that not
>    everyone will get right, e.g. incorrect encoding of inner
>    extensions, extension handlers that have side-effects
>    being called twice etc.
>      - Possible fix: organise an interim session (or slot
>        therein) with the explicit and only goal of
>        simplifying ECH.
>      - Possible fix: publish test vectors and require a
>        test vector from anyone proposing any new construct,
>        before accepting their suggested new crypto-wrinkle.
>      - Possible fix: make the spec much more explicit about
>        what goes into the transcript at every possible
>        stage, esp when that changes.
>

I agree calling extensions handlers twice would be problematic, but it
seems to me that's not necessary. The spec conceptually splits ECH into a
client-facing server and a backend server which I think, even for "Shared
Mode" implementations, hints at a cleaner implementation strategy:

Early in the handshake, before even version negotiation (as section 7.1
says) and certainly before calling any extensions handlers, see if there is
an ECH extension in the ClientHello. If so, attempt to decrypt the inner
ClientHello. If you succeed, continue the handshake with the inner
ClientHello. If you fail, continue the handshake with the outer
ClientHello. Ignore the ClientHello you didn't use.

This way you only run the complex stateful handshake logic on one
ClientHello, since that's logically the "backend server". The
"client-facing server" is really just a ClientHello dispatcher that needn't
interact with most of the handshake.

- There's no simple, sensible way to decide which
>    extensions to "compress" in the inner that I can see. As
>    a library, one could come up with some vastly complex API
>    to allow applications pretend to handle this, but that'd
>    seem more dangerous than useful. While I made the code
>    generic, it's not at all clear that'll ever be useful.
>      - Possible fix: forget generic compression and define
>        a small set of extension types that can be inherited
>        from the outer with all others being present as
>        needed in inner and outer. For future extensions
>        (e.g.  some many-octet PQ key agreement), have the
>        extension definition include the option of "see
>        outer" within the extension encoding.
>

Yeah, the compression mechanism is a bit complicated. I don't think "see
outer" in the extension definition is the right path. It would likely
introduce ClientHello malleability problems (see
https://tools.ietf.org/html/draft-ietf-tls-esni-09#section-10.10.3), unless
the extension further defines how to "compile out" out the "see outer"
portion.

Rather than exposing the details of the compression to the API, I think
it's better to reason about what is public, what is private, and what are
the goals of the wire image. It seems to me we have roughly two kinds
of clients to consider:

First, there are clients that send GREASE and wish to align their ECH and
non-ECH ClientHellos as much as possible. Those clients will likely send
the bulk of their extensions in ClientHelloOuter as most do not depend on
the server name. E.g. a browser always sends ALPN={h2,http/1.1}. There, the
default is to reference the extension, so the encrypted payload only
contains the couple of extensions that vary (SNI, PSK). Keeping that small
is good for bandwidth not just in ECH connections, but also to avoid an
overly expensive GREASE payload in non-ECH connections. Keeping the two
ClientHellos aligned also simplifies the rest of the handshake: you only
have one set of preferences to evaluate the server response against.

Then there are clients that don't especially care about their wire image.
They may instead send a minimal ClientHelloOuter, just enough to
authenticate a replacement config. (Or maybe they don't care about the
recovery flow at all and don't even do that.) Those clients will likely
send the bulk of their extensions in just ClientHelloInner, and omit them
from ClientHelloOuter altogether. There are a few extensions (key_share,
signature_algorithms, etc.) that are necessary in a minimal
ClientHelloOuter, so they may compress those still. Though this does give
outer and inner paths wildly different preferences, so the client needs to
modify the handshake accordingly.

Probably the way to simplify, in both spec and implementation, is to focus
on those two kinds of clients.


> - Given inner and outer can have different sets of
>    extensions, I guess there'll never be a way to make ECH
>    handling constant-time. If so, then that ought be covered
>    as a security consideration. If not, how'd that work?
>      - Possible fix: document potential consequences of
>        ECH never being constant time?
>

Yeah, constant-time seems a bit hopeless here. The point of ECH is to
protect sensitive fields in the inner ClientHello, but those sensitive
fields result in a choice of different extensions, certificate, and private
key in the server. That's going to result in a wildly different instruction
and memory access trace.


> - I don't plan on implementing the "MUST check
>    outer.sni==public_name" check ever really. (Unless
>    forced to as part of upstreaming maybe.)
>      - Possible fix: remove that MUST.
>

Is there such a requirement? I didn't think there was. This came up in
https://github.com/tlswg/draft-ietf-tls-esni/issues/389, which was closed.

David