Subject: [TLS] close_notify and TLS 1.3

From: David Schinazi <[email-masked]>
Date: Sat, 11 Nov 2017 17:21:11 +0800

Hello all,

Currently TLS 1.3 specifies close_notify in the same way that TLS 1.2 did.
I believe that has issues and this might be the right time to fix them.
The purpose of close_notify is to protect against data truncation attacks,
each side is required to send close_notify before closing the write side of
the transport connection so the other side knows that the data was not truncated.
As such, close_notify only needs half-close semantics to prevent truncation.

However, the specification contains the following text:
<< Each party MUST send a “close_notify” alert before closing the write side
    of the connection, unless some other fatal alert has been transmitted.
    The other party MUST respond with a “close_notify” alert of its own and close
    down the connection immediately, discarding any pending writes. >>

This means that an application-layer client can't send a query then close their
write transport when they know that they're done, because the server would
terminate the TLS session before sending the reply. On top of this, when
the server receives the close_notify, it may have already sent part of the reply
(or wrote it to the socket send buffer) so the responding close_notify would
in effect be inflicting a truncation attack on the client.

This doesn't make much difference for HTTP because clients already
don't close their write transport after sending a reply, however having the
option do do this could allow innovation in new protocols that can define
the semantics of when they use close_notify. An example is DNS PUSH:
https://tools.ietf.org/html/draft-ietf-dnssd-push <https://tools.ietf.org/html/draft-ietf-dnssd-push>

A proposal to solve this problem would be to give close_notify half-close
semantics: we keep the requirements that a close_notify be sent before
closing the transport, and that any data received after a close_notify is
ignored, but we simply remove the requirement to immediately reply
with a close_notify. This has the advantage that current implementations
are already compliant but future ones can leverage this improvement.

What do you think? Is this worth discussing on Thursday?

Thanks,
David Schinazi

---

From: Martin Thomson <[email-masked]>
Date: Sat, 11 Nov 2017 23:18:20 +0800

This seems like it might be worth looking at.  This seems to be
something that harks back to SSL3 or even earlier.  We aren't going to
make it so that you can rely on this behaviour, but we might be able
to make it possible to half-close, which for new protocols using TLS
could be hugely useful.

On Sat, Nov 11, 2017 at 5:21 PM, David Schinazi <[email-masked]> wrote:
> https://tools.ietf.org/html/draft-ietf-dnssd-push
>
> _______________________________________________
> TLS mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/tls
>

---

From: David Benjamin <[email-masked]>
Date: Sat, 11 Nov 2017 23:46:08 +0000

I think this change is a good idea.

Our implementation actually does this already anyway. We are happy to
continue servicing writes even when the read half has consumed a
close_notify. I believe we inherited this behavior from OpenSSL, so it
should be there too. Go's crypto/tls implementation appears to also already
do this.

We don't have a particular need for the half-close semantics that I know
of, but I don't care for the current spec text (it requires yet another
undesirable read/write sync point). Aligning with TCP's semantics is also
generally a good default.

On Sat, Nov 11, 2017 at 11:18 PM Martin Thomson <[email-masked]>
wrote:

> >     The other party MUST respond with a “close_notify” alert of its own
> and
> > close
> > the server receives the close_notify, it may have already sent part of
> the
> > reply

---

From: Eric Rescorla <[email-masked]>
Date: Sat, 11 Nov 2017 17:13:14 -0800

Initial inspection suggests that NSS behaves the same way, so I would be
fine with this change.

-Ekr

On Sat, Nov 11, 2017 at 3:46 PM, David Benjamin <[email-masked]>
wrote:

>> > This means that an application-layer client can't send a query then
>> close
>> > their

---

From: David Schinazi <[email-masked]>
Date: Sun, 12 Nov 2017 09:24:28 +0800

Thanks for checking gents!

Would you like me to send a PR?

David

> On Nov 12, 2017, at 09:13, Eric Rescorla <[email-masked]> wrote:
> 
> Initial inspection suggests that NSS behaves the same way, so I would be fine with this change.
> 
> -Ekr
> 
> 
> On Sat, Nov 11, 2017 at 3:46 PM, David Benjamin <[email-masked] <mailto:[email-masked]>> wrote:
> Our implementation actually does this already anyway. We are happy to continue servicing writes even when the read half has consumed a close_notify. I believe we inherited this behavior from OpenSSL, so it should be there too. Go's crypto/tls implementation appears to also already do this.
> 
> We don't have a particular need for the half-close semantics that I know of, but I don't care for the current spec text (it requires yet another undesirable read/write sync point). Aligning with TCP's semantics is also generally a good default.
> 
> On Sat, Nov 11, 2017 at 11:18 PM Martin Thomson <[email-masked] <mailto:[email-masked]>> wrote:
> On Sat, Nov 11, 2017 at 5:21 PM, David Schinazi <[email-masked] <mailto:[email-masked]>> wrote:
> > Hello all,
> >
> > [email-masked] <mailto:[email-masked]>
> > https://www.ietf.org/mailman/listinfo/tls <https://www.ietf.org/mailman/listinfo/tls>
> >
> 
> [email-masked] <mailto:[email-masked]>
> https://www.ietf.org/mailman/listinfo/tls <https://www.ietf.org/mailman/listinfo/tls>
> 
> [email-masked] <mailto:[email-masked]>
> https://www.ietf.org/mailman/listinfo/tls <https://www.ietf.org/mailman/listinfo/tls>
> 
>

---

From: Eric Rescorla <[email-masked]>
Date: Sat, 11 Nov 2017 17:29:04 -0800

Please.

-Ekr

On Sat, Nov 11, 2017 at 5:24 PM, David Schinazi <[email-masked]> wrote:

>>> >     The other party MUST respond with a “close_notify” alert of its
>>> own and
>>> > close

---

From: Martin Thomson <[email-masked]>
Date: Sun, 12 Nov 2017 09:47:37 +0800

We suppress the sending of a close_notify if we have received one, but
that's a fairly simple thing to correct.

---

From: David Schinazi <[email-masked]>
Date: Sun, 12 Nov 2017 10:39:41 +0800

I've sent out a PR:
https://github.com/tlswg/tls13-spec/pull/1092 <https://github.com/tlswg/tls13-spec/pull/1092>

It might be a little verbose but I think it explains and solves the problem.
Please let me know what you think!

Thanks,
David Schinazi

> On Nov 12, 2017, at 09:47, Martin Thomson <[email-masked]> wrote:
>

---

From: Ilari Liusvaara <[email-masked]>
Date: Sun, 12 Nov 2017 10:58:33 +0200

> Initial inspection suggests that NSS behaves the same way, so I would be

My implementation also has half-close semantics for close_notify
(both TLS 1.2 and 1.3).

This does not address beyond-TCP semantics some applications need, but
those applications are unlikely to run directly on top of TLS without
some layer in between, so getting those semantics from TLS would not
be useful.

-Ilari

---

From: Hubert Kario <[email-masked]>
Date: Mon, 13 Nov 2017 12:37:15 +0100

On Saturday, 11 November 2017 10:21:11 CET David Schinazi wrote:
> the transport connection so the other side knows that the data was not
> truncated. As such, close_notify only needs half-close semantics to prevent
> truncation.
> 
> of the connection, unless some other fatal alert has been transmitted. The
> other party MUST respond with a “close_notify” alert of its own and close
> This means that an application-layer client can't send a query then close
> their write transport when they know that they're done, because the server
> would terminate the TLS session before sending the reply. On top of this,
> when the server receives the close_notify, it may have already sent part of
> the reply (or wrote it to the socket send buffer) so the responding
> close_notify would in effect be inflicting a truncation attack on the
> client.
> 
> <https://tools.ietf.org/html/draft-ietf-dnssd-push>
> 

what about alerts?

if you half-closed the connection for write and then received key-update, or 
message with an invalid tag, how are you supposed to react to it?

-- 
Regards,
Hubert Kario
Senior Quality Engineer, QE BaseOS Security team
Web: www.cz.redhat.com
Red Hat Czech s.r.o., Purkyňova 115, 612 00  Brno, Czech Republic

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 13 Nov 2017 12:25:07 +0000

On Mon, Nov 13, 2017 at 11:37 AM, Hubert Kario <[email-masked]> wrote:

> The

> if you half-closed the connection for write and then received key-update,

I assume you mean with update_requested set. in any case, you do nothing:

If the request_update field is set to "update_requested" then the receiver
MUST
send a KeyUpdate of its own with request_update set to
"update_not_requested" prior
to sending its next application data record.

> or

I think it would be fine to either silently tear down the connection or to
send an alert.

-Ekr

---

From: David Benjamin <[email-masked]>
Date: Mon, 13 Nov 2017 13:37:49 +0000

> I think it would be fine to either silently tear down the connection or to

The latter seems better to me. The peer isn't going to parse it anyway,
since it was preceded by a closure alert, and it keeps the invariant that
one does not send anything after a closure alert.

But this problem isn't caused by this proposal and exists regardless. The
proposal is about whether the party which closes *second* must *send* a
close_notify after *receiving* one. This problem is if the party which
closes *first* *receives* garbage after *sending* a close_notify and
waiting for the corresponding one. That case is unavoidable so long as
waiting for the peer's close_notify after sending one is a supported
operation. The peer may send garbage.

David

---

From: Hubert Kario <[email-masked]>
Date: Mon, 13 Nov 2017 15:38:46 +0100

On Monday, 13 November 2017 13:25:07 CET Eric Rescorla wrote:
> > > Currently TLS 1.3 specifies close_notify in the same way that TLS 1.2
> > 
> > did.
> > 
> > > The purpose of close_notify is to protect against data truncation
> > 
> > attacks,
> > 
> > > each side is required to send close_notify before closing the write side
> > 
> > of
> > 
> > > truncated. As such, close_notify only needs half-close semantics to
> > 
> > prevent
> > 
> > > truncation.
> > > 
> > > << Each party MUST send a “close_notify” alert before closing the write
> > 
> > side
> > 
> > > their write transport when they know that they're done, because the
> > 
> > server
> > 
> > > when the server receives the close_notify, it may have already sent part
> > 
> > of
> > 
> > > don't close their write transport after sending a reply, however having
> > 
> > the
> > 

how "MUST send a KeyUpdate of its own" is "you do nothing"?

Either you "MUST" act on received control messages or you do not.
If not, then the handling of errors by closing the read side (and NOT sending 
fatal alerts) should be specified.

Sending bad_record_mac while not replying to KeyUpdate seems very ugly to me; 
if the rest of the document is not updated in PR#1092.

> I think it would be fine to either silently tear down the connection or to

sending alerts after close_notify goes against the semantics of TCP half-
close. If the intention is to support TCP half-close-like mechanism in TLS, we 
need to document when and where that abstraction is broken. In particular - 
that sending close_notify shouldn't be followed by closing the write side of 
the connection (be it TCP or Unix socket). Only that application_data packets 
are disallowed after close_notify.
-- 
Regards,
Hubert Kario
Senior Quality Engineer, QE BaseOS Security team
Web: www.cz.redhat.com
Red Hat Czech s.r.o., Purkyňova 115, 612 00  Brno, Czech Republic

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 13 Nov 2017 20:34:36 +0000

On Mon, Nov 13, 2017 at 2:38 PM, Hubert Kario <[email-masked]> wrote:

> > > > closing the transport, and that any data received after a
> close_notify
> > > > is

You need to read to the end of the sentence
"prior to sending its next application data record". As no such record is
sent, you don't need to do anything.

> are disallowed after close_notify.

As David says, this problem already exists.

-Ekr

--