Subject: [tcpinc] Quick review of draft-rescorla-tcpinc-tls-option-04

From: Mirja Kühlewind <[email-masked]>
Date: Thu, 15 Oct 2015 14:04:27 +0200

Hi Ekr,

I did a quick review of draft-rescorla-tcpinc-tls-option-04, as an individual (not as chair).

Thanks for putting all the explanational text in there; at least for me that was very helpful. I have a few comments and (potentially stupid) questions:

1) Section 2 say that if there is a decryption failure/finished failure, endpoint SHOULD signal a connection failure. Does it mean that endpoint SHOULD/MUST also send a TCP RST? And do we really, really need to close the connection here, or is there maybe a way to think about falling back to TCP only…?

2) The current proposal has the possibility that both endpoints might not support the same chipper suite and therefore tcpinc will not be used. Should we maybe think about picking a default one (or set of default ones that can be ordered by preference) that must be supported. I know that's hard, but for tcpinc, as the intention is anyway ‚just‘ opportunistic encryption, that might make more sense. Maybe we can specify something while at the same time saying that the server should not expect that a specific chiper suite will be available such that we still have a change to deprecate this specification later…

3) Section 3.1.2.3 says
"Unless the implementation is specifically configured
      otherwise, it SHOULD NOT attempt to validate the certificate, even
      if it is of type X.509 but merely extract the key.“
Isn’t the intention here that TCP could pass the cert to the app and the app could validate if it wants…?

4) Figure 4 (in section 3.1.4 which is wrongly labeled Figure 2) indicated that the server cannot send data with the ServerHello. That means to actually access data form a server, you’ll always have an additional RTT even in 0-RTT mode. Is that true?

5) Section 3.2. says „… MUST respond to renegotiation with fatal „no_renegotiation“ alert“. What does this mean for the TCP connection? 
That’s also a general comment that the integration with TCP is probably in some cases not well enough specified yet. For my point of view that’s where a (kernel) implementation would be helpful!

6) I’d recommend to specify the ENO sub option at the beginning of the doc. And you further need to specify this more detailed, maybe with an image, and give all the specfic bits such as the application-aware bits, variable-length bit, and the sub option type.

7) Similar as in point 1 & 5: section 5 says „If [..] TLS integrity fails, the connection MUST be torn down". Should the endpoint send a TCP RST here? Further, as TLS integrity checking should effectively also be done in the kernel and data should not be delivered to the app if the integrity check fails, there is the option to simply drop the TCP packet and wait for a retransmit. This does have security implications but maybe we can come up with some additional logic that e.g. makes sure that if that happens ‚too often‘ we will close the connection…

8) Further the draft says in section 6, that there are two options for implementation. And I disagree there. tcpinc should always be implemented in the kernel and only if there is potentially an app that also implements TLS there might be a config option to allow the app to do the TLS handling if successfully negotiated in TCP. It is not an option to have a tcpinc implementation that relies on the possibility that the app might have TLS implemented because then we are end up at a the state where we already are.

9) Reading section 9, we must be careful that we don’t create a new attack here where broken data causes the connection to close, e.g. if packet seems to be in a valid window but does not pass the the integrity check. Don’t think that’s actually a case but maybe worth think about this.

And some nits/comments:
- in Figure 1) the packet from the server is 'SYN/ACK + TCP-ENO [ENO]‘ and should be 'SYN/ACK + TCP-ENO [TLS]‘…?
- second point in 3.1.1 says ‚(see Figure 2‘ which probably should be ‚(see Figure 3)‘ and Figure 3 is actually called Figure 1…
- Can you maybe try and expend (and refer) all acronyms (ECDSA, TOFO, ECDHE, ALPN, HKDF, AEAD, …)
- In 3.1.2.1.2 text says ‚(see {{server-first-flight)‘. As this reference is broken (missing closing brackets), the ref also doesn’t show up in the ref list at the end…  
- Missing reference in 3.3 (on session resumption; can you also provide more reasoning here) and in 3.4.
- Another broken reference in 7: {{RFC5246}
- section 3.1.6 is not really clear: what’s N_MIN, what’s the record seq number, is ContentType only one byte?

Hope that’s helpful!

Mirja

---

From: Eric Rescorla <[email-masked]>
Date: Sun, 18 Oct 2015 07:23:04 -0700

> Thanks for putting all the explanational text in there; at least for me
that was very helpful. I have a few comments and (potentially stupid)
questions:
>
> 1) Section 2 say that if there is a decryption failure/finished
> failure, endpoint SHOULD signal a connection failure. Does it mean
> that endpoint SHOULD/MUST also send a TCP RST? And do we really,
> really need to close the connection here, or is there maybe a way to
> think about falling back to TCP only…?

I don't know if we *really* need to, but my reasoning here is that
we now know that the middlebox messed with the data and so failing
the connection is safer.

> 2) The current proposal has the possibility that both endpoints
> might not support the same chipper suite and therefore tcpinc will
> not be used. Should we maybe think about picking a default one (or
> set of default ones that can be ordered by preference) that must be
> supported. I know that's hard, but for tcpinc, as the intention is
> anyway ‚just‘ opportunistic encryption, that might make more
> sense. Maybe we can specify something while at the same time saying
> that the server should not expect that a specific chiper suite will
> be available such that we still have a change to deprecate this
> specification later…

Well, there already is an MTI cipher suite (see: S. 3.5), but
someone could always be noncompliant, right?

> Isn’t the intention here that TCP could pass the cert to the app and the
app could validate if it wants…?

Well, maybe.

1. This applies only to the TLS portion of the system, so its
   consistent with that usage.
2. There's no requirement for the cert to be valid so absent
   out-of-band semantics the application has limited options
   for handling it

> 4) Figure 4 (in section 3.1.4 which is wrongly labeled Figure 2)
> indicated that the server cannot send data with the
> ServerHello. That means to actually access data form a server,
> you’ll always have an additional RTT even in 0-RTT mode. Is that
> true?

Diagram fail. In both the 0 and 1-RTT cases the server can send on
the first flight.

> 5) Section 3.2. says „… MUST respond to renegotiation with fatal
> „no_renegotiation“ alert“. What does this mean for the TCP
> connection?

You should fail the connection. Any failure post-handshake should
lead to the same result.

> 6) I’d recommend to specify the ENO sub option at the beginning of
> the doc. And you further need to specify this more detailed, maybe
> with an image, and give all the specfic bits such as the
> application-aware bits, variable-length bit, and the sub option
> type.

Sure, I can do that.

> 7) Similar as in point 1 & 5: section 5 says „If [..] TLS integrity
> fails, the connection MUST be torn down". Should the endpoint send a
> TCP RST here? Further, as TLS integrity checking should effectively
> also be done in the kernel and data should not be delivered to the
> app if the integrity check fails, there is the option to simply drop
> the TCP packet and wait for a retransmit. This does have security
> implications but maybe we can come up with some additional logic
> that e.g. makes sure that if that happens ‚too often‘ we will close
> the connection…

This seems like it's of modest value. The two main ways this can
happen are:

1. Middlebox modification (where retransmits won't help).
2. Bit-errors which are not detected by the TCP checksum.

I'n not aware of much experience that checksum-conforming bit errors
happen often enough to be worthwhile here. Moreover, if there's
any kind of realignment between the boundaries of the packets and
the TCP segments (as can happen with retransmits and MTU reductions)
then it can be hard to determine which segment is bogus.

> 8) Further the draft says in section 6, that there are two options
> for implementation. And I disagree there. tcpinc should always be
> implemented in the kernel and only if there is potentially an app
> that also implements TLS there might be a config option to allow the
> app to do the TLS handling if successfully negotiated in TCP. It is
> not an option to have a tcpinc implementation that relies on the
> possibility that the app might have TLS implemented because then we
> are end up at a the state where we already are.

We're defining a wire protocol here, so specifying particular
implementation tactics seems out of scope. With that said, I
don't think your assessment that we're back at the same state
we always were. As I think I pointed out when I first introduced
this draft, it addresses two problems with the same wire protocol:

1. The basic TCPINC use case.
2. Out-of-band negotiation of application-level TLS.

An application-level implementation is totally consistent with #2.

> 9) Reading section 9, we must be careful that we don’t create a new
> attack here where broken data causes the connection to close,
> e.g. if packet seems to be in a valid window but does not pass the
> the integrity check. Don’t think that’s actually a case but maybe
> worth think about this.

Well, this turns attacks that would involve valid data injection into
attacks on the connection. I think that's an imporovement.

> And some nits/comments:
> - in Figure 1) the packet from the server is 'SYN/ACK + TCP-ENO [ENO]‘
and should be 'SYN/ACK + TCP-ENO [TLS]‘…?
> - second point in 3.1.1 says ‚(see Figure 2‘ which probably should be
‚(see Figure 3)‘ and Figure 3 is actually called Figure 1

Thanks.

> - Can you maybe try and expend (and refer) all acronyms (ECDSA, TOFO,
ECDHE, ALPN, HKDF, AEAD, …)

Sure.

> - In 3.1.2.1.2 text says ‚(see {{server-first-flight)‘. As this reference
is broken (missing closing brackets), the ref also doesn’t show up in the
ref list at the end…
> - section 3.1.6 is not really clear: what’s N_MIN, what’s the record seq
number, is ContentType only one byte?

Thanks.

-Ekr

On Thu, Oct 15, 2015 at 5:04 AM, Mirja Kühlewind <
[email-masked]> wrote:

> Thanks for putting all the explanational text in there; at least for me
> that was very helpful. I have a few comments and (potentially stupid)
> questions:
>
> 1) Section 2 say that if there is a decryption failure/finished failure,
> endpoint SHOULD signal a connection failure. Does it mean that endpoint
> SHOULD/MUST also send a TCP RST? And do we really, really need to close the
> connection here, or is there maybe a way to think about falling back to TCP
> only…?
>
> 2) The current proposal has the possibility that both endpoints might not
> support the same chipper suite and therefore tcpinc will not be used.
> Should we maybe think about picking a default one (or set of default ones
> that can be ordered by preference) that must be supported. I know that's
> hard, but for tcpinc, as the intention is anyway ‚just‘ opportunistic
> encryption, that might make more sense. Maybe we can specify something
> while at the same time saying that the server should not expect that a
> specific chiper suite will be available such that we still have a change to
> deprecate this specification later…
>
> 3) Section 3.1.2.3 says
> 4) Figure 4 (in section 3.1.4 which is wrongly labeled Figure 2) indicated
> that the server cannot send data with the ServerHello. That means to
> actually access data form a server, you’ll always have an additional RTT
> even in 0-RTT mode. Is that true?
>
> 5) Section 3.2. says „… MUST respond to renegotiation with fatal
> „no_renegotiation“ alert“. What does this mean for the TCP connection?
> That’s also a general comment that the integration with TCP is probably in
> some cases not well enough specified yet. For my point of view that’s where
> a (kernel) implementation would be helpful!
>
> 6) I’d recommend to specify the ENO sub option at the beginning of the
> doc. And you further need to specify this more detailed, maybe with an
> image, and give all the specfic bits such as the application-aware bits,
> variable-length bit, and the sub option type.
>
> 7) Similar as in point 1 & 5: section 5 says „If [..] TLS integrity fails,
> the connection MUST be torn down". Should the endpoint send a TCP RST here?
> Further, as TLS integrity checking should effectively also be done in the
> kernel and data should not be delivered to the app if the integrity check
> fails, there is the option to simply drop the TCP packet and wait for a
> retransmit. This does have security implications but maybe we can come up
> with some additional logic that e.g. makes sure that if that happens ‚too
> often‘ we will close the connection…
>
> 8) Further the draft says in section 6, that there are two options for
> implementation. And I disagree there. tcpinc should always be implemented
> in the kernel and only if there is potentially an app that also implements
> TLS there might be a config option to allow the app to do the TLS handling
> if successfully negotiated in TCP. It is not an option to have a tcpinc
> implementation that relies on the possibility that the app might have TLS
> implemented because then we are end up at a the state where we already are.
>
> 9) Reading section 9, we must be careful that we don’t create a new attack
> here where broken data causes the connection to close, e.g. if packet seems
> to be in a valid window but does not pass the the integrity check. Don’t
> think that’s actually a case but maybe worth think about this.
>
>
> And some nits/comments:
> - second point in 3.1.1 says ‚(see Figure 2‘ which probably should be
> ‚(see Figure 3)‘ and Figure 3 is actually called Figure 1…
> - In 3.1.2.1.2 text says ‚(see {{server-first-flight)‘. As this reference
> is broken (missing closing brackets), the ref also doesn’t show up in the
> ref list at the end…

---

From: Mirja Kühlewind <[email-masked]>
Date: Wed, 21 Oct 2015 18:05:35 +0200

Hi Ekr,

see inline.

On 18.10.2015 16:23, Eric Rescorla wrote:
> that was very helpful. I have a few comments and (potentially stupid) questions:
>  >

Not sure what safer in this sense actually means, but the point I was trying 
to make is, that this might be a case, where a connection might fail when 
trying to use tcpinc while a regular tcp connection might succeed. An 
application that does not even know that it is using tcpinc, thus might not 
be able to connect.

> someone could always be noncompliant, right?

Actually I overlooked this. However, to be correct you probably have to say 
that one should not only implement those but also offer at least one of them 
with the ClientHello.

> You should fail the connection. Any failure post-handshake should

My point is that 'fail the connection' does not mean anything for someone who 
want to implement this in TCP. I guess you mean send a TCP RST and close the 
socket connection...?

> An application-level implementation is totally consistent with #2.

First of all, you have a section on implementation in the draft, I'm just 
commenting on what's written there.

I think David, made this point as well: tcpinc is charter for case 1, that 
means there MUST be a kernel implementation. Case 2 might be supported but 
doesn't have to to fulfill our charter. Of course I agree that case 2 makes a 
lot of sense if we use tls.

However, the point is, as long as the doc says that you can fulfill the 
specification of tcpinc even though you have an implementation that only uses 
tcpinc if TLS is supported by the app, this doc is not a tcpinc doc because 
it does not address our charter.

Mirja

---

From: Eric Rescorla <[email-masked]>
Date: Wed, 21 Oct 2015 09:19:11 -0700

On Wed, Oct 21, 2015 at 9:05 AM, Mirja Kühlewind <
[email-masked]> wrote:

> Not sure what safer in this sense actually means, but the point I was
> trying to make is, that this might be a case, where a connection might fail
> when trying to use tcpinc while a regular tcp connection might succeed. An

Well, as David points out, ENO specifically prohibits this. And I've
modified the
draft to say that.

> Actually I overlooked this. However, to be correct you probably have to
> say that one should not only implement those but also offer at least one of
> them with the ClientHello.

 I could live with that.

> My point is that 'fail the connection' does not mean anything for someone
> who want to implement this in TCP. I guess you mean send a TCP RST and
> close the socket connection...?

Yes. Once you adopt the position in ENO that you can only send ciphertext
then this naturally follows:

   Conversely, if a host receives an ACK segment containing an ENO
   option, then encryption MUST be enabled.  From this point the host
   MUST follow the encryption protocol of the negotiated spec and MUST
   NOT present raw TCP payload data to the application.  In particular,
   data segments MUST contain ciphertext or key agreement messages as
   determined by the negotiated spec, and MUST NOT contain plaintext
   application data.

> means there MUST be a kernel implementation.

I don't think this follows at all. The charter doesn't say anything about
kernel
implementations. It says "The protocol must be usable by unmodified
applications" and
"The protocol must not require any authentication or configuration", but
neither
of these require a *kernel* implementation. For example, one might implement
things with a divert socket (as the tcpcrypt implementation at
https://github.com/scslab/tcpcrypt does, though I know they have a kernel
implementation.). So this means you need a whole-system implementation
but doesn't mean you need a kernel one.

Another concrete scenario (which is attractive for a TLS implementation) is
to
use a minimal kernel component (or a divert socket) to do the ENO options
with a modified libc to actually do the TLS negotiation and data handling.
This would also provide system-wide support but would not be in the kernel.
I don't see anything in the charter which prohibits this.

> Case 2 might be supported but doesn't have to to fulfill our charter. Of
> course I agree that case 2 makes a lot of sense if we use tls.
>
> specification of tcpinc even though you have an implementation that only
> uses tcpinc if TLS is supported by the app, this doc is not a tcpinc doc
> because it does not address our charter.

I think this is kind of a semantic distinction, but would you consider it
satisfactory
if this were rewritten to indicate that it is possible to build an
implementation which will
interoperate with a system-wide implementation (scenario 1) using solely an
application-level
technique?

-Ekr

---

From: Mirja Kühlewind <[email-masked]>
Date: Wed, 21 Oct 2015 18:59:40 +0200

Hi again,

see below.

On 21.10.2015 18:19, Eric Rescorla wrote:
>     I think David, made this point as well: tcpinc is charter for case 1,
>     that means there MUST be a kernel implementation.
>
>
> I don't think this follows at all. The charter doesn't say anything about kernel
> "The protocol must not require any authentication or configuration", but neither

Okay, you are right, I was using 'kernel implementation' as a synonym for 
'stand-alone implementation' or 'whole system implementation' as you just 
named it and that's wrong; sorry. And I was also naturally assuming that we 
sooner or later want to provide a kernel implementation here. But that's a 
different story.

However, the point is that the second option where tcpinc would rely on an 
implementation in the app as written in you draft is not an option for tcpinc:

"   o  Implement just the TCP-TLS negotiation option in the operating
       system kernel with an interface to tell the application that TCP-
       TLS has been negotiated and therefore that the application must
       negotiate TLS."

>
> Another concrete scenario (which is attractive for a TLS implementation) is to

In don't really see how to deploy this, because than you have a kernel 
implementation that requires a certain lib to be installed. In this case you 
probably should implement the lib in the kernel right away.

> interoperate with a system-wide implementation (scenario 1) using solely an

If you mean a user-space implementation as provided by tcpcrypt, where you 
redirect TCP traffic back into user-space (and all tcpinc is implemented in 
user space without kernel modifications), then yes that's okay.

At this point it is important to have a full and stand-alone implementation 
that can be used with any app to show the feasibility and check that the 
given specification is clear and complete.

However, this can, from my point of view, only be a intermediate solution to 
enable faster deployment, where the final goal would still be a kernel 
implementation. But that's my personal point of view here.

Mirja

---

From: David Mazieres <[email-masked]>
Date: Thu, 22 Oct 2015 19:49:33 -0700

Eric Rescorla <[email-masked]> writes:

> I don't think this follows at all. The charter doesn't say anything
> about kernel implementations. It says "The protocol must be usable by
> unmodified applications"...

> Another concrete scenario (which is attractive for a TLS
> implementation) is to use a minimal kernel component (or a divert
> socket) to do the ENO options with a modified libc to actually do the
> TLS negotiation and data handling.  This would also provide
> system-wide support but would not be in the kernel.  I don't see
> anything in the charter which prohibits this.

The libc implementation won't work with unmodified applications, because
it will break when sharing/passing/inheriting file descriptors across
processes, a common pattern for Unix servers.

It will probably be best to take a two-pronged strategy, where a
rock-solid user-level daemon implementation gets us deployment in places
where people want to secure network storage protocols, database
connections, etc.  But then that adoption creates pressure to upstream
the kernel implementation.  My experience from tcpcrypt is that cloud
providers are interested in the functionality but very skittish about
any kernel mods.

David

---

From: Eric Rescorla <[email-masked]>
Date: Thu, 22 Oct 2015 21:30:03 -0700

> processes, a common pattern for Unix servers.

Hmm... I've seen designs where this should work, for instance where
you dup the fds to point them to some intermediate location.

-Ekr

---

From: David Mazieres <[email-masked]>
Date: Thu, 22 Oct 2015 22:19:45 -0700

> you dup the fds to point them to some intermediate location.

I'd like to see such a design.  I'm sure you can get something to work
with some application, but if the goal is all applications, then it's
going to be pretty tricky.

"dup the fds to point them to some intermediate location" sounds pretty
dubious to me.  For one thing the dup system call doesn't change what an
fd points to.  Now, if you mean point the file descriptors to some
intermediary daemon, then you are getting closer to a daemon
implementation, and by the time you fix it up, that's what you will
have.

But anyway not all applications are written in languages that use libc.
Not all applications are dynamically linked.  And not all C
implementations use libc--the standard recognizes both "hosted" and
"freestanding" implementations.  A big potential use case for TCPINC is
network file systems, which tend to be implemented with a freestanding C
compiler and supply their own libraries.  A daemon implementation would
encrypt NFS traffic, while a libc implementation likely would not.

This is not to say there isn't some valuable library-level use case for
TCP-ENO.  (In fact, that's partly why we left the door open to static
ENO options with multiple suboptions from host B, about which you are
skeptical.)  I just don't think such an implementation will satisfy
TCPINC.

David