Re: New Version Notification for draft-kazuho-quic-authenticated-handshake-00.txt

Kazuho Oku <kazuhooku@gmail.com> Sun, 16 December 2018 08:58 UTC

Return-Path: <kazuhooku@gmail.com>
X-Original-To: quic@ietfa.amsl.com
Delivered-To: quic@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 029671293FB for <quic@ietfa.amsl.com>; Sun, 16 Dec 2018 00:58:32 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -1.999
X-Spam-Level:
X-Spam-Status: No, score=-1.999 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, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.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 IMgRlOkHHmgr for <quic@ietfa.amsl.com>; Sun, 16 Dec 2018 00:58:28 -0800 (PST)
Received: from mail-lj1-x231.google.com (mail-lj1-x231.google.com [IPv6:2a00:1450:4864:20::231]) (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 4D3A1124D68 for <quic@ietf.org>; Sun, 16 Dec 2018 00:58:28 -0800 (PST)
Received: by mail-lj1-x231.google.com with SMTP id k19-v6so8371471lji.11 for <quic@ietf.org>; Sun, 16 Dec 2018 00:58:28 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=K22j8HctIpNgooLO0QWZPr1vOeRThIG7ufvNbCvTlm0=; b=RinerOT9B+CJVxNzM/LeRNJTtw4hxOKiaVqnp//lAgSk8rQuzl93LiMymhOLnc/Owc xWtNMCATiSscpXrKhXS+eJn+KZPToNvGawQIGwGV5IG57GLAlNSQLzCbwPg6Bk+Bscw2 MhO6W5+906CQou9MUW+P809Ou1F5NF/+SgBSog2c2EftMUD0RW9kaluV7UqnPktd+3/s z02ffjTT4pgWh8jnym2CMwSfJisurr5DiF7qY3OusLOE63/gPdtK1XDWgJAVvsn59dVc ytcZoOlozxjX8a2JWSw/SvJ2GO5rUyGn2jrLsyEUirLX1PsX+51P806JHWUMF5hbTuVV Lucg==
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:content-transfer-encoding; bh=K22j8HctIpNgooLO0QWZPr1vOeRThIG7ufvNbCvTlm0=; b=L1xUog9qgB2lJ21Fbx6ZQTw+vhXbcSo6+J6CLaznv370yXTyO1DnSnT2qKrdQ2JfrW 7z720VUYMo+tA0czlIR3xuUUVbkeCSmZWtINXipaAyDJyV2R8xGX++mHtpjSNDVV9wqa DKYfguZ2MiIj8RxFgqpni+mSV5ONX2B39RMata6mw/5Bx/B78UZEI2TwSzBGpiUGLHvg DolaADPwLomyMuAlluLxyj+IlYr+FkplqV69GgTOWjymJ3sR4JYT4/0PwrJOLKjz52ZD Eqw3kE7FgRrllXdoVJBAVprae9AYd1LmKEg1aHPDV7NCLwmZTbgcBn70mb3BNfrN3ueq /wVw==
X-Gm-Message-State: AA+aEWbkrOSlnR33O9PIO/+qP+mjgKf1UjENXUAGVW9i5qqxYm13SZdm jh7UtrZCFmD0bHDkm8cJDqtOnqMBxAbr86Z7RtLEWXAL
X-Google-Smtp-Source: AFSGD/XYjHnH/mTZHnr4lVwFqETA9BdHRT3SkKtdh2gdkcsoBuIBc9qt3TtELj5PX33P7bchwEQcImOeOt5RGjkEyHg=
X-Received: by 2002:a2e:9715:: with SMTP id r21-v6mr5043697lji.30.1544950706385; Sun, 16 Dec 2018 00:58:26 -0800 (PST)
MIME-Version: 1.0
References: <154475462982.32005.8870303572182973327.idtracker@ietfa.amsl.com> <CANatvzwbL-NoRK1boZmFkA8kEvJzCQTP26FCh31_c0rRrYvSOw@mail.gmail.com> <CABcZeBNOAw3b504yZ5rV2THroe0K_y-T=_ya8-t0zDC5k6X8+g@mail.gmail.com> <98ac8dac-393c-92e4-776c-2c27c55be7a2@huitema.net> <CANatvzwe2dJ8hCrsrnL3uXkcsbODKTLtZeLcsTDF_yuypxvxng@mail.gmail.com> <9032a8c6-7f7d-2482-3d68-82bbbe876d2e@huitema.net>
In-Reply-To: <9032a8c6-7f7d-2482-3d68-82bbbe876d2e@huitema.net>
From: Kazuho Oku <kazuhooku@gmail.com>
Date: Sun, 16 Dec 2018 17:58:14 +0900
Message-ID: <CANatvzweHE5cFY_gzW=qV6oDjxZzzBjeinw2BLL=DOR=mVz7WQ@mail.gmail.com>
Subject: Re: New Version Notification for draft-kazuho-quic-authenticated-handshake-00.txt
To: Christian Huitema <huitema@huitema.net>
Cc: Eric Rescorla <ekr@rtfm.com>, IETF QUIC WG <quic@ietf.org>
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Archived-At: <https://mailarchive.ietf.org/arch/msg/quic/9aUxohN3ah7G79AjGvBhjuZeugA>
X-BeenThere: quic@ietf.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Main mailing list of the IETF QUIC working group <quic.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/quic>, <mailto:quic-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/quic/>
List-Post: <mailto:quic@ietf.org>
List-Help: <mailto:quic-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/quic>, <mailto:quic-request@ietf.org?subject=subscribe>
X-List-Received-Date: Sun, 16 Dec 2018 08:58:32 -0000

2018年12月16日(日) 13:22 Christian Huitema <huitema@huitema.net>:
>
>
> On 12/15/2018 7:21 PM, Kazuho Oku wrote:
> > 2018年12月16日(日) 9:45 Christian Huitema <huitema@huitema.net>:
> >> Quoting the whole message, because it is a nice analysis.
> >>
> >> On 12/15/2018 10:50 AM, Eric Rescorla wrote:
> >>> Kazuho,
> >>>
> >>> Thanks for sending this. I think it's a very interesting direction. I have
> >>> some comments below.
> >>>
> >>> DEPLOYMENT MODEL
> >>> It seems to me that there are two models to consider here. In the
> >>> first, the server *only* supports authenticated handshakes (AH) and in
> >>> the second, it supports both authenticated and unauthenticated
> >>> handshakes. In general, I think the second case is far more likely,
> >>> because in general we can't assume that clients can receive the
> >>> ESNIKeys records, and that means that some clients will not use AH.
> >>>
> >>>
> >>> THREAT MODEL
> >>> This leads us directly to the question of the threat model. I assume
> >>> that we have what I termed a Class (3) attacker, which can inject
> >>> packets and will always win the race but cannot delete packets.
> >>> With that, you get the following pattern:
> >>>
> >>>
> >>> Client                  Attacker                Server
> >>>
> >>> CInitial ->
> >>>                         CInitial' ->
> >>>                         CInitial  ->
> >>>                                            <- SInitial
> >>>                         <- SInitial'
> >>>                         <- SInitial
> >>>
> >>> CHandshake ->
> >>>                         CHandshake ->
> >>>
> >>> Our objective is to have the handshake survive this treatment. In an
> >>> ideal world, we would cause the server and client to reject X' and
> >>> process X but this isn't possible, with the design you suggest,
> >>> because the attacker can always take CInitial, replace the CRYPTO
> >>> frames with his own and then send it to the server, computing
> >>> a new MAC based on *his* Zx. Note that this won't necessarily have
> >>> the right ESNI but that doesn't matter, because it will have
> >>> the same [SC]CID, and so will cause cause CInitial to be discarded
> >>> when it is received. As far as I can tell, your current design
> >>> does not prevent this. If I'm missing something here, let me
> >>> know [0]
> >>
> >> Agreed.
> >>
> >>>
> >>>
> >>> FIRST CLIENT INITIAL
> >>> It seems like the obvious defense is the one you suggest in S 3.2.2,
> >>> namely to treat each distinct CInitial as its own handshake and create
> >>> separate state on the server for each one. Then this will cause the
> >>> server to send two SInitials, one in response to CInitial and one
> >>> in response to CInitial'. This gives us the diagram below.
> >>>
> >>> Client                  Attacker                Server
> >>>
> >>> CInitial ->
> >>>                         CInitial' ->
> >>>                                            <- SInitialX   //
> >>> Corresponds to CInitial'
> >>>
> >>>                         <- SInitialX'
> >>>                         <- SInitialX
> >>>
> >>>                         CInitial  ->
> >>>                                             <- Sinitial   //
> >>> Corresponds to CInitial
> >>>                         <- Sinitial'
> >>>                         <- SInitial
> >>>
> >>> CHandshake ->
> >>>                         CHandshake ->
> >>>
> >>> Note that the attacker can duplicate and tamper with any message
> >>> either side sends so because the server sends two SInitials, the
> >>> attacker ends up potentially sending 4.
> >> The suggestion is S 3.2.2. is basically the same as PR 2706: create a
> >> separate server context for each separate CH. Like Kazuho, I think it is
> >> pretty much required for any good defense.
> > Yeah. As I suggested in my response to EKR, it might be worth
> > considering going one step further; i.e. derive DCID from ClientHello.
>
> Do you mean "the Initial CID that the client uses as Destination CID in
> the Initial Packet"?

Yes.

> Yes, that can work. The ICID is an unconstrained
> random number, at least 8 byte long, but very possibly 16 bytes.
> Specifying that ICID = hash(Initial Payload) would pretty much seal that
> payload and prevent lots of games. It might be a good idea regardless of
> what we do, because then attackers would have a very hard time creating
> faked CInitial. If the content changes, the ICID also changes.
>
>
> >>> SERVER INITIAL FLIGHT
> >>> So, what we need at this point is to ensure that the client rejects
> >>> (a) SInitial', SInitialX' and (b) SInitialX, and accepts SInitial (I'm
> >>> ignoring subsequent Initial packets from the Client at this point),
> >>> but I'll get there shortly. Rejecting SInitial' happens automatically
> >>> in your design. The attacker doesn't have Zx and so SInitial' will not
> >>> deprotect correctly.
> >>>
> >>> Rejecting SInitialX is harder, but I think can be fixed by mixing
> >>> CInitial1
> >>> into the the key schedule. I.e., the initial key would be something
> >>> like:
> >>>
> >>>   IS = HKDF-Extract(0xef4fb0abb47470c41befcf8031334fae485e09a0,
> >>>                     Zx)
> >>>
> >>>   initial_secret = HKDF-Extract(HKDF-Expand(IS, ...),
> >>>                                 F(CInitial))
> >>>
> >>> Where F(CInitial is some sanitized version of CInitial, that is
> >>> invariant under retransmission, perhaps the payload + the CIDs.
> >>> The result of this is that SInitialX and SInitial will be encrypted
> >>> with separate keys (with only the one for SInitial being the one
> >>> that the client expects) and the client will discard SInitialX
> >>> after it fails to decrypt.
> >> We tried to not have rekeying at the client, i.e. keep the same hmac key
> >> throughout the session.
> > Agreed. I think that that would be a nice property to have (for
> > simplicity). And IMO there's no downside in doing that, because an
> > attacker cannot generate a spoofed packet that would be processed by
> > either of the endpoints, assuming that we address the issue of server
> > not rejecting spoofed Initial packets carrying legitimate a ESNI
> > extension (discussed above).
> >
> >> The assumption is that the data incorporated in
> >> the "hmac_key" contains something that client and server know, but the
> >> attacker cannot guess. The structure "ClientESNIInner" has that
> >> property, as long as the nonce really is unguessable. Caveats about
> >> random number generation seem to apply. Now it may well be that our
> >> draft refers to "ESNIContents" when in fact it should refer to
> >> "ClientESNIInner". That would be a simple fix.
> > Zx is the shared secret between the client and server, therefore
> > hmac_key cannot be calculated by an attacker.
>
> You mean the shared secret derived from the ESNI and used to encrypt the
> original SNI?
>
> We may need to make that a bit more explicit in the draft.

I've added clarification that says that "Zx is the extracted DH shared
secret of Encrypted SNI".

> > Hash(ESNIContents) is the equivalent of AAD. Therefore I am not sure
> > if ClientESNIInner is the correct thing to do. Instead we should
> > expand that to cover the entire ClientHello, to ensure that HMAC key
> > would be unique to ClientHello.
>
> If we make ICID = hash(ClientHello), then we make the Initial AEAD key
> dependent on the content of the Client Hello. The more I think of it,
> the more it looks like a good idea.
>
> >>>
> >>> SUBSEQUENT CLIENT INITIALS
> >>> The diagram looks like this
> >>>
> >>> Client                  Attacker                Server
> >>>
> >>> CInitial ->
> >>>                         CInitial' ->
> >>>                                            <- SInitialX   //
> >>> Corresponds to SInitial'
> >>>                         CInitial  ->
> >>>                                             <- Sinitial
> >>>
> >>>                         <- SInitialX'
> >>>                         <- SInitialX
> >>>                         <- SInitial
> >>>                         <- Sinitial'
> >>>
> >>> CInitial2 ->
> >>>                         CInitial2' ->
> >>>                         CInitial2 ->
> >>>
> >>> There are actually two types of subsequent client Initials
> >>>
> >>>
> >>> 1. Those after SH that contain ACKs (and the like) for server
> >>>    Initial.
> >>> 2. Those after HRR
> >>>
> >>> With case (1), we should just rekey off of Initial secret. The server
> >>> can sort out which keys to use based on trial decryption or perhaps
> >>> some extra flag in the packet (probably the second is better).
>
> >> This gets better if the client switches to using the server chosen SCID
> >> instead of the ICID in the subsequent initials. If we do that, then
> >> there is no ambiguity: Clinitial2 arrives with the SCID chosen by the
> >> server when sending SInitial, and is authenticated using the HMAC key
> >> derived from CInitial.
> >>
> >> If we insist that all Initial packets shall have Dest=ICID, then we do
> >> indeed have a problem, and we need to put a unique token somewhere in
> >> the payload. Hash(CInitial) would work.
> > I think deriving DCID from Hash(ClientHello) would also fix the issue.
>
> Yes. The entire exchange then get tied to the Client Hello.
>
> >>> Case (2) (HRR) is more complicated. Trying to use data in the ESNI
> >>> extension when you're not going to use g^x is tricky (though maybe
> >>> possible), so we could potentially handle this as in case (1). Another
> >>> alternative is to use the same general strategy we used for the
> >>> first Initial and bucket the CInitial1/CInitial2 pairs. This is
> >>> easiest done
> >>> if we force each CInitial2 to commit to a specific CInitial1 (thus
> >>> avoiding
> >>> the need to do combinatoric explosion on the server). You could
> >>> do this by including a hash of CInitial1 in CInitial2. The attacker
> >>> can obviously bind CInitial2' to any CInitial he wants, but he has
> >>> to transmit one message for each, so the result is the same as
> >>> sending N CInitial1s.
> >> That, or sending the messages with dest=SCID instead of dest=ICID.
> >>
> >> I think we went back and forth with that idea. I don't quite remember
> >> why we nixed it. Is there a potential deployment issue?
>
> Having one ICID per client hello feels better. There is always a risk
> that having some Initial packets routed by ICID and others routed by
> SCID would confuse firewalls or load balancers.
>
> >>> VERSION NEGOTIATION
> >>> In your design you move version negotiation to the client and forbid
> >>> VN:
> >>>
> >>>    A client MUST ignore Version Negotiation packets.  When the client
> >>>    gives up of establishing a connection, it MAY report the failure
> >>>    differently based on the receipt of (or lack of) Version Negotiation
> >>>    packets.
> >>>
> >>> More concerning, this moves the QUIC version negotiation to the ESNI
> >>> record, which permits downgrade attacks by that server (or anyone who
> >>> controls DNS). We've generally avoided this in TLS ESNI. It could
> >>> be solved by having the true origin sign the ESNIKeys structure
> >>> (as we have discussed for semi-static).
> >>>
> >>> It's worth noting that this is a consequence of QUIC's VN design. With
> >>> the simplified VN design I suggested in PR #2113, you wouldn't have
> >>> this problem: the server would commit to its *minimum* version (this
> >>> is implicit in ESNIKeys already, as it requires TLS 1.3) and then you
> >>> could upward negotiate as expected.
> >> And maybe we should specify that. After all, we are creating a new QUIC
> >> version, so we can just as well have a couple of extra transport parameters.
> >>
> >>
> >>> [0] Another possibility with your current design is for the attacker
> >>> to tamper with CH, for instance by adding a dummy extension, because
> >>> the ESNI extension doesn't protect all of CH, just g^x. This will
> >>> cause the server's Handshake messages to deprotect incorrectly. One
> >>> could imagine a fix for this if the ESNI extensions covered more
> >>> of the CH.
> >> If the attacker did that, wouldn't the HMAC fail at the server? Also,
> >> isn't that just a variant of CInitial' ?
>
>
> I think we are making progress. We should write the ICID = hash(Client
> Hello) requirement in the next version of the draft. My only question is
> whether this hash should be some plain SHA256 hash, or instead an HMAC
> using the ESNI-derived key. I am leaning towards the simpler solution,
> because clients could do it in a version independent way.

I also prefer using a hash function rather than exposing a value
derived from the secret (even though doing that should be safe). OTOH,
I prefer having agility instead of hard-coding the algorithm.

I've filed https://github.com/kazuho/draft-kazuho-quic-authenticated-handshake/pull/8
based on my preference, I'd appreciate it if you could take a look. I
hope that having a PR will help us confirm that we are talking about
the same idea.


>
> -- Christian Huitema
>
>


-- 
Kazuho Oku