Subject: [tcpinc] Revised version of TCP-ENO

From: David Mazieres <[email-masked]>
Date: Mon, 10 Aug 2015 05:45:17 -0700

We have revised the TCP-ENO draft and posted a new version that
addresses feedback we have received so far.  The biggest change we made
was to split the document in two.  TCP-ENO itself specified is specified
in an experimental status document, as before:

  * https://datatracker.ietf.org/doc/draft-bittau-tcpinc-tcpeno/

The API changes are now specified in a new informational status document
that could potentially form the basis of the working group's API
document if people like it:

  * https://datatracker.ietf.org/doc/draft-bittau-tcpinc-api/

We'd appreciate feedback on these two new drafts.

Thanks,
David

---

From: Kyle Rose <[email-masked]>
Date: Tue, 11 Aug 2015 18:04:15 -0400

My comments so far:

> Once the two sides have exchanged SYN segments, the _negotiated spec_
> is the first valid spec identifier in the SYN segment of host B (that
> is, the passive opener in the absence of simultaneous open).  In
> other words, the order of suboptions in host B's SYN segment
> determines spec priority, while the order of suboptions in host A's
> SYN segment has no effect.  Hosts must disable TCP-ENO if there is no
> valid spec in host B's SYN segment.

> When possible, host B SHOULD send only one spec identifier (suboption
> in the range 0x20-0xff), and SHOULD ensure this option is valid.
> However, sending a single valid spec identifier is not required, as
> doing so could be impractical in some cases, such as simultaneous
> open or library-level implementations that can only provide a static
> TCP-ENO option to the kernel.

What is the meaning of "first valid spec identifier"? This allowance
for multiple spec identifiers sent by host B makes sense if the chosen
spec is "the first spec identifier also among those spec identifiers
that host A sent", but otherwise there's no difference between host B
sending a single static identifier or multiple: if host A supports the
first in host B's static list, that would get used; otherwise TCP-ENO
negotiation would fail.

You seem to imply the meaning above in figure 8, in which case I think
the text should be clarified.

3.3:

> A TCP segment MUST
> include at most one suboption whose high nibble is 0.

Does this mean "A TCP SYN segment including the TCP-ENO option MUST..."?

4.1: Do you want to add the additional requirement that session IDs be
public, i.e., not be secret to endpoints/applications?

Kyle

On Mon, Aug 10, 2015 at 8:45 AM, David Mazieres
<[email-masked]> wrote:
> _______________________________________________
> Tcpinc mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/tcpinc

---

From: David Mazieres <[email-masked]>
Date: Wed, 12 Aug 2015 17:08:28 -0700

Kyle Rose <[email-masked]> writes:

> that host A sent",

That is the intent.  In other words, if A and B have multiple compatible
spec identifiers, the negotiated spec is the one at the lowest byte
offset in B's SYN segment.

> but otherwise there's no difference between host B

That's right.  So that's why if possible B should send only one.  But in
the case of simultaneous open, both A and B may want to send multiple
supported identifiers, since they don't know what the other side
accepts.  In that case the priority is determined by B.

> the text should be clarified.

I think the confusion is that if you are creating a SYN-ACK in response
to a SYN, there is no reason to include more than one spec identifier.
It's just that we wanted to leave room for the possibility that B' SYN
doesn't depend on A's SYN, either because of simultaneous open, or for
implementation reasons.

Does what I wrote in this email make sense, and if so, can you identify
more precisely the source of the confusion, or suggest a specific edit?

> Does this mean "A TCP SYN segment including the TCP-ENO option MUST..."?

Yes.  Would the following wording help:  "A TCP segment MUST include at
most one ENO suboption whose high nibble is 0."

> public, i.e., not be secret to endpoints/applications?

This was the intent of the following bullet in section 4.1:

   o  The session ID MUST NOT contain any confidential data (such as
      data permitting the derivation of session keys).

We didn't use the word "public" because that almost sounds like there's
a requirement to disclose the session ID.  But if the existing wording
is not clear, we are certainly open for suggestions.

Thanks for the feedback.

David

---

From: Daniel Kahn Gillmor <[email-masked]>
Date: Thu, 13 Aug 2015 16:50:29 -0400

> is not clear, we are certainly open for suggestions.

We almost certainly want endpoints/applications to treat the session ID
as sensitive information -- leaked knowledge of the session ID would
allow someone to impersonate the other party if any authentication was
bootstrapped off of the session ID.

The point of the text David highlights above is to ensure that an
endpoint/application can't learn anything about the cryptographic
secrets through the session ID interface -- that is, it defends the
cryptographic layer from breakage by the client.  But we shouldn't
encourage clients to break the layer that is accessible to them (the
session ID) by publishing their data either.

        --dkg

---

From: Kyle Rose <[email-masked]>
Date: Thu, 13 Aug 2015 17:05:38 -0400

> session ID) by publishing their data either.

This can't be the case if, for instance, the session IDs are signed in
batches as proposed in the tcpcrypt paper.

The session ID is a channel binding identifier, not a cryptographic
secret. Woe betide anyone who bootstraps authentication outside of the
context of the encrypted session using a session ID it had seen
sometime in the past under the assumption it was secret.

This is why I like the original wording of "public", because it
clearly implies you can throw one around at will as its knowledge will
do no good to anyone not in control of one of the endpoints of the
connection.

David, I'll hopefully address the rest of your reply tonight, when I
have some free cycles.

Kyle

---

From: Daniel Kahn Gillmor <[email-masked]>
Date: Thu, 13 Aug 2015 17:27:16 -0400

> batches as proposed in the tcpcrypt paper.

You seem to be assuming that peer authentication will happen by an
cryptographic public-key signature over the session id.  In this case, i
agree that the session id could be published without a problem.

But this isn't necessarily the only mechanism that could be used to
authenticate the peer.

> sometime in the past under the assumption it was secret.

I'm not talking about anything outside of the encrypted session, or any
sort of past data linkage.

> do no good to anyone not in control of one of the endpoints of the

If we really want to limit ourselves to authentication mechanisms that
don't break if the session ID is public, then i agree we should call it
"public".  But i personally haven't evaluated the full bestiary of
PAKE/SRP/PSK/all possible uni- or bi-directional authentication
mechanisms that one might want to use.  So i'm not confident that we can
safely treat the session ID as a public variable in all cases.

But I'm happy to hear arguments in that direction, if you've got 'em.

At the very least, publication/leakage of the session ID could indicate
that two endpoints were probably talking to each other (if they both
announce that they've seen the same session ID).  Do we want to
encourage that kind of metadata leakage by saying they should be
"public"?

    --dkg

---

From: "Everhart, Craig" <[email-masked]>
Date: Thu, 13 Aug 2015 21:37:04 +0000

>But this isn't necessarily the only mechanism that could be used to

I was looking forward to sending something like an HMAC of the signature
value, myself.

		Craig

---

From: David Mazieres <[email-masked]>
Date: Thu, 13 Aug 2015 15:11:23 -0700

> But this isn't necessarily the only mechanism that could be used to

So I think this conversation is convincing me of Kyle's point of view
that we should use the word public, to convey intended usage.  What
about something along the lines of:

    * Specs should assume the session ID will be made public and ensure
      that it contains no confidential data (such as data permitting the
      derivation of session keys).

    * However, unless the application at either end of a connection
      takes steps to disclose the session ID, specs should ensure that a
      network eavesdropper has a negligible advantage in differentiating
      the collision-resistant hash in a session ID from uniform random
      bytes.

Whether you are using Public keys to sign session IDs, or HMAC to
authenticate them, or some PAKE thing dependent on the session ID, it
shouldn't matter that the session ID is public.  You don't have to make
it public, but the formula for generating it should assume it will be
made public.

That said, one could imagine a fringe use case where an application
wants to prove that two anonymous TCP connections belong to the same two
processes, in which case the session ID of the first connection might be
used as a MAC key to authenticate the session ID of the second.  So you
don't want the session ID to be predictable, even if making it public
doesn't hurt TCPINC itself.

What do you think?

David

---

From: Ted Hardie <[email-masked]>
Date: Thu, 13 Aug 2015 15:19:05 -0700

> doesn't hurt TCPINC itself.
​I don't think I understand this use case.  To whom does the application
want to prove this?

regards,

Ted​

---

From: David Mazieres <[email-masked]>
Date: Thu, 13 Aug 2015 15:22:53 -0700

>       the collision-resistant hash in a session ID from uniform random

Just wordsmithing a bit, I now propose:

* Unless and until applications disclose information about the session
  ID, all but the first byte MUST be computationally indistinguishable
  from random bytes to a network eavesdropper.

* Applications MAY chose to make session IDs public.  Therefore, specs
  MUST NOT place any confidential data in the session ID (such as data
  permitting the derivation of session keys).

David

---

From: Martin Thomson <[email-masked]>
Date: Thu, 13 Aug 2015 15:43:03 -0700

>   from random bytes to a network eavesdropper.

Don't call out the first byte.  The whole thing is what will matter
here.  As long as two session IDs are indistinguishable from each
other, I think that we're OK.

---

From: Daniel B Giffin <[email-masked]>
Date: Thu, 13 Aug 2015 16:23:52 -0700

> other, I think that we're OK.

david is just exempting the negotiated "spec identifier"
that TCP-ENO prepends to the collision-resistant hash of
connection information.

that byte indicates what encryption protocol was negotiated,
and of course will be easily distinguishable from random.

---

From: David Mazieres <[email-masked]>
Date: Thu, 13 Aug 2015 16:42:26 -0700

> other, I think that we're OK.

Well, currently the first byte is the particular encryption spec you are
using, and the length of the whole thing is also dependent on the spec.
That's of course open to debate, but currently we can't require any two
session IDs to be indistinguishable.  More fundamentally, though,
comparing session IDs with each other will lead to a much more
complicated security definition for a property that's much harder to use
in other proofs.

Given that specs will almost certainly be generating the session ID from
a PRF like HKDF anyway, why do we need to allow lower-entropy session
IDs?

David

---

From: David Mazieres <[email-masked]>
Date: Thu, 13 Aug 2015 16:55:35 -0700

> ​I don't think I understand this use case.  To whom does the application

Again, it's pretty fringe, but here's a contrived application.  I'm
running some kind of legacy protocol over TCPINC that involves a
long-running TCP connection, but at least one end is anonymous.  Maybe
it's a chat application like IRC.  But now I want to run a newer control
protocol that connects to the same server and proves it is associated
with the previous connection.  It can do so by using the previous
session ID as a MAC key.

Also, if we want the 32+-byte hash size to mean anything, we kind of
need the session ID to make use of all the bits anyway.

Finally, when you're trying to prove things, pseudo-random quantities
are often nice to work with.

So that's three kind of mediocre reasons to have pseudo-random session
IDs, vs. zero reasons to permit lower-entropy/predictable ones.  We
hadn't previously required it, but this brief discussion has made me
inclined to require pseudo-random session IDs.

David

---

From: Kyle Rose <[email-masked]>
Date: Thu, 13 Aug 2015 20:54:29 -0400

> offset in B's SYN segment.

I missed the definition for "valid" in 3.2. That resolves my confusion.

> most one ENO suboption whose high nibble is 0."

Yes, that is more precise.

Kyle

---

From: Kyle Rose <[email-masked]>
Date: Thu, 13 Aug 2015 21:13:15 -0400

> doesn't hurt TCPINC itself.

I'm starting to come around to dkg's viewpoint that it doesn't
necessarily *have* to be public: batch signing of session IDs is one
suggested use case, but authentication protocols that don't do that
could potentially make use of the session ID being private.

I think maybe guidance about when it is appropriate to consider them
public vs. private belongs in section 4.1 of this doc, or in the API
doc if a section there is added on batch signing. Strictly speaking,
the current wording ("The session ID MUST NOT contain any confidential
data (such as data permitting the derivation of session keys)") is
probably right.

Kyle

---

From: Stephen Farrell <[email-masked]>
Date: Fri, 14 Aug 2015 12:51:24 +0100

Hiya,

A couple of points on the session ID stuff:

> doesn't hurt TCPINC itself.

I tend to agree with the above.

As an FYI, I'm a co-author of an MPLS WG draft that has a
similar concept [1] (which should be no surprise:-) so I'd
like to try make sure those two things end up being similar
to the extent we can. I'll likely just copy what's done here
as much as possible.

I think we might want to also consider that one thing that
might happen is that loads and loads of these values (or
values derived from them) could end up being accumulated and
eventually end up really public. Just for safety's sake I'd
probably prefer that what might end up public is not the same
set of bits used as the session ID during the session though.
For example, using the same bits might enable later correlations
between log files that we'd prefer not be possible - say between
some client-host-firewall log reported via telemetry and an
application server log. So there might be benefits in defining
a way to do that so that application developers don't get
it badly wrong. In [1] we talk about a witness value that
is different from a session ID. Not sure if that's useful
here (or there;-) or not though.

Lastly, we should check that whatever is done here is ok for
MTPCP.

Cheers,
S.

[1]
https://tools.ietf.org/html/draft-ietf-mpls-opportunistic-encrypt-00#section-7.1

---

From: Martin Thomson <[email-masked]>
Date: Fri, 14 Aug 2015 08:05:46 -0700

> a PRF like HKDF anyway, why do we need to allow lower-entropy session

I didn't suggest that you reduce entropy.  My point was that you are
creating a special carve-out for your current solution.  What if you
decide you want *two* bytes of discriminator?  My point is that all
you need is to have the session ID as a whole be hard to
guess.synthesize, etc...

---

From: David Mazieres <[email-masked]>
Date: Fri, 14 Aug 2015 10:25:22 -0700

> you need is to have the session ID as a whole be hard to

By our current solution, do you mean TCP-ENO?  It seems reasonable for
the TCP-ENO specification to include a special carve-out for itself.
Any other spec that needs a discriminator can just include the
discriminator in the collision-resistant hash input.  That's fine
because a spec knows what goes into the collision-resistant hash.

The problem is that TCP-ENO doesn't even know which cryptographic hash
functions specs will employ for the session ID.  If someday one of those
hashes turns out to be incredibly insecure, we want to make sure that if
*either* end of the connection disables the bad spec, the security
problem goes away.  The minimum you need for that is to
sign/MAC/etc. not just some hash but also something specifying how that
hash was computed, to avoid cross-spec collisions.  Given the way the
TCP-ENO spec is written, one byte is sufficient for that purpose.

There is another solution, which is to hard-code the hash function in
TCP-ENO.  It's not entirely elegant, either, but you could say all
32-byte session IDs are SHA-256 starting with the negotiation
transcript, and IANA can specify other lengths and hash functions down
the line.  So that's more elegant in that the whole session ID can be
made indistinguishable from random, but less elegant in that spec
authors might have to rely on two different hash functions.

So I can see arguments for 0 or 1 bytes not being indistinguishable from
random, but I can't see arguments for a two-byte discriminator, unless
you are also advocating more fundamental changes to ENO's negotiation
mechanism (which is of course still on the table at this point).

David

---

From: Martin Thomson <[email-masked]>
Date: Fri, 14 Aug 2015 10:46:17 -0700

Again, you are getting bogged down in the details.  What are the
properties you would expect from a session ID?  That it is unique to a
session and that it is hard to guess (with high probability).  Those
are the only properties that you need to require at this level of the
design.

To up-level a little, I think that TCP-ENO is going too far in terms
of specifying extra little bits.  This session ID stuff is a good
example of that.  If the purpose of the draft is to enable selection
of an encryption scheme, then it has far too much machinery.

I have problem with specifying requirements, which is part of what
Section 4 attempts to do.  But you'd be better off doing so in a
straightforward fashion.

---

From: David Mazieres <[email-masked]>
Date: Fri, 14 Aug 2015 10:49:23 -0700

> here (or there;-) or not though.

I think you raise several questions here.

First, should what TCP-ENO calls the session ID be traceable to a
particular connection by a passive eavesdropper?  A contrived scenario
here is that for some reason you run a bulletin board that logs messages
and session IDs.  I put your bulletin board under surveillance,
recording a complete packet transcript.  Now I don't like a particular
message.  From its session ID, can I tell which client connection posted
the message (assuming, say, that all messages are the same length and
that timing information is obscured by batching the messages at the
server).  As I said, this is a bit contrived, but if everyone uses the
same encryption spec, I do think there is value in this kind of privacy,
and it is achieved by requiring the session ID to be computationally
indistinguishable from random.

Second, instead of a single session ID, should we define two values with
this property, a "witness" and a "session ID", where the witness is
available for use by other transport-level RFCs (such as MPTCP) and the
session ID is for use by applications.  Or, generalizing, allow a whole
host of values indexed by an integer.  The advantage of this is that
domain separation ensures that whatever your application does will not
undermine, say MPTCP.  This is a valid argument, but it adds a lot of
complexity, so it might be nice to avoid, also.

> Lastly, we should check that whatever is done here is ok for

I assume you mean MPTCP?  If so, I agree, assuming by "ok" you mean a
subsequent update of MPTCP can easily integrate with TCP-ENO (as opposed
to TCP-ENO citing RFC6824 as a normative reference and directly
specifying how the two work together).

David

---

From: David Mazieres <[email-masked]>
Date: Fri, 14 Aug 2015 11:05:46 -0700

> are the only properties that you need to require at this level of the

I would also like it to be indistinguishable from random, modulo choice
of encryption spec, so that an attacker cannot correlate session IDs
with recorded packet transcripts.

> of an encryption scheme, then it has far too much machinery.

It's more than that.  It's trying to abstract away the details of the
spec for applications, so that an application written to use TCP-ENO can
work with any spec.

> Section 4 attempts to do.  But you'd be better off doing so in a

If we don't specify requirements for the session ID, then applications
will have to be knowledgeable about what encryption spec they are using.
That means if we get large SYN options down the line and massively
optimize TCPINC, applications won't be able to take advantage of it
automatically.

David

---

From: Martin Thomson <[email-masked]>
Date: Fri, 14 Aug 2015 11:15:09 -0700

> optimize TCPINC, applications won't be able to take advantage of it

Sorry, I missed an important word.  I have *no* problem with
specifying requirements; I just have a problem with specifying
mechanism with a requirement for that mechanism.

If you look at this in the abstract, how the session ID is acquired
and defined can (and should) be opaque to an application using this.
At some level, the requirement you want is an API one: the application
MUST be able to acquire an identifier that is unique for the session.

Also, given the other discussion, perhaps the model in RFC 5705 is the
right one to use: don't expose a unique id, but provide an application
the ability to extract a value, with the limitation that it be
specific to that application.

---

From: [email-masked]
Date: Fri, 14 Aug 2015 11:30:31 -0700

> mechanism with a requirement for that mechanism.

So what is your proposal?  Do you think TCP-ENO should specify the
mechanism or the requirement?  Right now, I think the draft is written
in an attempt to specify the requirements and leave the mechanism as
open-ended as possible.  I haven't seen any ideas on how to make it more
mechanism-agnostic.  Does this mean you'd favor dispensing with the
requirements and just specifying a mechanism?

> MUST be able to acquire an identifier that is unique for the session.

Exactly.

> specific to that application.

Well, I'd say RFC 5705 tends towards the mechanism end of the spectrum,
since it tells you exactly what to feed into your PRF.  I don't know if
we want to make such assumptions about TCP-ENO specs.

David

---

From: Stephen Farrell <[email-masked]>
Date: Fri, 14 Aug 2015 20:15:27 +0100

Hiya,

> complexity, so it might be nice to avoid, also.

Right. For the MPLS stuff, so far, we have two things, one a
key id (really a session id of sorts when you combine with
the other identifiers that exist in MPLS) and the 2nd a
witness value. Providing more outputs didn't seem useful. Note
I'm not claiming that split is great or should be copied, I'm
just describing what we've got in the current MPLS draft.

The RFC5705 approach could work here too I guess. Might be a
little odd to supply the application inputs like that to a
getsockopt call in an optval (are there others like that? I
forget) but I guess it could work.

> specifying how the two work together).

Correct.

Cheers,
S.

---

From: Martin Thomson <[email-masked]>
Date: Fri, 14 Aug 2015 12:23:37 -0700

On 14 August 2015 at 11:30,  <[email-masked]> wrote:
> Do you think TCP-ENO should specify the
> mechanism or the requirement?

Perhaps neither.  At one level, this need only negotiate what crypto
is in effect.

At this stage, not knowing what is going to happen where, bundling
things together doesn't help.

---

From: Kyle Rose <[email-masked]>
Date: Fri, 14 Aug 2015 15:53:19 -0400

Upon further reflection ("these are loafers"), I am returning to my
previous position.

I was conflating two issues: cipher spec and authentication. The problem
here is that the application doesn't by default choose the cipher spec(s),
so the session ID is what it is, which means it needs to be lowest common
denominator over all applications. That means "public", at least for all
default cipher specs.

Is it reasonable for a system like tcpinc to support specs available via
TCPENO_SPECS that have properties that allow naïve misconfiguration to
create vulnerabilities? Maybe the historical problem of people doing dumb
things with SSL_Ciphers is not an issue for TCP-ENO, with sane defaults.

Kyle

Kyle

---

From: David Mazieres <[email-masked]>
Date: Fri, 14 Aug 2015 13:33:59 -0700

> Perhaps neither.  At one level, this need only negotiate what crypto

Well, the charter requires TCPINC to have some kind of session ID or
other authentication mechanism.  If by neither you mean you don't want
that mechanism to be part of TCP-ENO, then TCP-ENO won't be very useful.
Strip out the session ID and you're mostly left with option kind
multiplexing, which could equally well be achieved through some simpler
RFC6994-like thing.  (The negotiation and aa bits can't be secured
without some sort of cross-spec requirements on the session ID.)

> things together doesn't help.

I don't understand this comment.  The whole point of TCP-ENO is to make
progress on knowing what is going to happen where, so as to facilitate
agreement on the crypto spec itself.  ENO can facilitate agreement on a
spec because it enables a spec-independent API.  Hence, if we
standardize TCPINC before TLS 1.3 or large options have been
standardized, we haven't given up the ability to leverage those other
technologies in the future.

Is your objection that this is the wrong goal (because there is no
useful spec-agnostic API), or that TCP-ENO fails to meet the goal
(because you envision specs unable to accommodate TCP-ENO's session ID
requirements), or that there's some better way to try to break the
working group deadlock (which I'd be glad to try)?

If you don't object to the basic premise of TCP-ENO, it would be helpful
if you could provide a specific suggestion for how you would like to see
the the draft changed.  Additionally, if you can cook up a specific
(albeit contrived) example that demonstrates the shortcomings of the
existing TCP-ENO draft (maybe with added computational
indistinguishability of session IDs in response to list feedback), this
would be quite helpful in framing the discussion.

Thanks,
David

---

From: Kyle Rose <[email-masked]>
Date: Sat, 15 Aug 2015 18:13:30 -0400

I took a closer look at the API document just now. The first thing
that jumps out at me is that since you are already providing part of a
socket interface (via getsockopt/setsockopt), it may be helpful for
interoperability to specify the errno values to be associated with
particular protocol-level failure modes. E.g., if the application
tries to set TCPENO_TIEBREAKER to 2, setsockopt should report EINVAL.

The section on automatic configuration may be useful, but is the
strategy outlined based either on data on general interference with
TCP traffic by middle boxes or on empirical investigation of TCP-ENO
itself across various types of networks?

I'm also assuming that if HMAC is an example of a PRF that the first
argument to PRF is the key material. Not sure whether this needs to be
spelled out.

Kyle

---

From: David Mazieres <[email-masked]>
Date: Sun, 16 Aug 2015 11:54:55 -0700

> tries to set TCPENO_TIEBREAKER to 2, setsockopt should report EINVAL.

I'm sort of agnostic on this point.  Some error return is obviously
important, but using existing error numbers encourages implementations
to lump together the various failure modes, where some day it might be
deemed useful to expose more information.  (E.g., EPROTONOSUPPORT when
the socket is connected without TCPINC, vs. ENOTCONN when it is too
early to ask for a session ID.  But I think the socket errnos tend to be
less consistent across operating systems than POSIX ones.)

> itself across various types of networks?

It's based on empirical experience with tcpcrypt.  But more improtantly,
it's based on the *desired* experiments for TCP-ENO, and the fact that
the experiments will be most useful if most people do the same thing.

> argument to PRF is the key material. Not sure whether this needs to be

Ah, good catch.  This is how it's typically written in the literature,
and indeed how it is used in, say, the HKDF RFC (RFC5869).  But I
realize that this is not specified in either RFC6234 or RFC2104, and
indeed that the example C code takes the arguments in the opposite order
(though it isn't quite comparable because there's a length argument,
too).

David