Re: [tcpinc] Review of draft-bittau-tcpinc-tcpeno-01

David Mazieres <> Sun, 23 August 2015 16:26 UTC

Return-Path: <>
Received: from localhost ( []) by (Postfix) with ESMTP id 3D8921A92E4 for <>; Sun, 23 Aug 2015 09:26:49 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: 1.99
X-Spam-Level: *
X-Spam-Status: No, score=1.99 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, HK_RANDOM_ENVFROM=0.001, HK_RANDOM_FROM=1, J_CHICKENPOX_31=0.6, MANGLED_BACK=2.3, SPF_PASS=-0.001, T_RP_MATCHES_RCVD=-0.01] autolearn=no
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id L9MbamKuCxSr for <>; Sun, 23 Aug 2015 09:26:47 -0700 (PDT)
Received: from ( [IPv6:2001:470:806d:1::9]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by (Postfix) with ESMTPS id 2C7BE1A92E2 for <>; Sun, 23 Aug 2015 09:26:47 -0700 (PDT)
Received: from ( []) by (8.14.7/8.14.7) with ESMTP id t7NGQkeG016383; Sun, 23 Aug 2015 09:26:46 -0700 (PDT)
Received: (from dm@localhost) by (8.14.7/8.14.7/Submit) id t7NGQaJq022744; Sun, 23 Aug 2015 09:26:36 -0700 (PDT)
X-Authentication-Warning: dm set sender to using -f
From: David Mazieres <>
To: Eric Rescorla <>
In-Reply-To: <>
References: <> <> <>
Date: Sun, 23 Aug 2015 09:26:36 -0700
Message-ID: <>
MIME-Version: 1.0
Content-Type: text/plain
Archived-At: <>
Cc: tcpinc <>
Subject: Re: [tcpinc] Review of draft-bittau-tcpinc-tcpeno-01
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: "Discussion list for adding encryption to TCP." <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
X-List-Received-Date: Sun, 23 Aug 2015 16:26:49 -0000

Eric Rescorla <> writes:

> But, as I note, at the cost of a byte if you *ever* want to have >1. My
> experience
> is that things get more complicated, rather than less.

Well, I'd say TCP's experience is that option space gets more precious,
not less.  I think the most common case is going to be that the SYN
proposes a bunch of one-byte suboptions and the SYN-ACK contains a
single suboption that is either one byte or variable length.  That's
what TCP-ENO is optimized for.

The "things get more complicated" argument is valid because software
doesn't typically have weight-and-balance-style restrictions like
aircraft.  Yet the 40-byte option limit is just such a hard limit.

Anyway, I'm not sure we can usefully debate this point without more
data, so maybe this question should be deferred until later in the

> For instance, you can
>> just barely fit a P-256 or Curve25519 DH key exchange in TCP options
>> currently.  If TCPINC is wildly successful, we can imagine a future spec
>> that does that and squeezes the 8 most popular SYN options into a single
>> byte or something.  But if we waste even one more byte of option space,
>> we start closing a lot of doors along that front.
> It seems like if that actually happens, it's also reasonably likely that we
> will find some way to make the SYN bigger.

I think we will get large NON-SYN options long before we get large SYN
options, and even that does not appear to be particularly close to
happening.  I'm not sure you and I can usefully debate the future of
TCP.  However, if we get the extra SYN space, then the additional byte
won't matter.  That's why I'd rather ensure that at least one use of
TCP-ENO consumes minimal space, rather than optimize something that
probably won't conveniently fit in today's SYN segments anyway.  And I'd
like to leave the door open to a minimal ECDHE spec of the kind
suggested by Watson.

> That said, if you can provide an explicit example of why you might want
>> multiple variable-length suboptions, you could possibly convince us to
>> optimize for that case.
> I think it's a general issue of protocol hygiene, but with that said, this
> would allow you to have an optional long tiebreaker for NAT penetration.

That's too general to convince me.  I think we'll have to wait and see
some specs that use TCP-ENO.  If a non-simultaneous open scenario could
end up benefiting from multiple variable-length options in the SYN
segment, that might convince me.  But if only SYN-ACK segments need
variable length options, since they SHOULD send only one suboption, I
don't think we want to optimize for the multiple suboption case.

> bit to 1 at the endpoint with the lowest (public-IP-address,
>> public-port-number) pair.
> As you say elsewhere, this is common in cases of NAT penetration and
> generally in NAT penetration cases you don't know your IP address
> with certainty. For instance, say we have two devices with apparent
> addresses:
> A: (host), (srflx)
> B: (host), (srflx).
> Which one has the lower IP address?

Well, assuming the RFC5737 addresses are publicly routable, obviously B
has a lower IP address.

If the simultaneous open is happening in any kind of application, the
two sides will need to use STUN or some other service to figure out
their public IP addresses and determine that they are behind the
appropriate kind of NAT.  They will also need to communicate their IP
addresses to each other.  This logic is happening anyway.  We are adding
a requirement that applications use this information to set the "b" bit
appropriately, which is not a lot more work, but definitely not

See below for more cases where setting b is not application transparent
but does not require much work, either.

> In the case where that was worked out most carefully at IETF (RFC 5245),
> a much larger tiebreaker is used.

RFC5245 uses an 8-byte tie-breaker.  So to put our options in a table:

                   |              | application- |   option    |
                   |  works ever  | transparent  |   space     |
|drop simultaneous |      no      |      no      |      0      |
|open support      |              |              |             |
|TCP-ENO draft     |     yes      |      no*     |  0 / 1 bit  |
|TCP-use-TLS       |     yes      |      no*     | 0 / 48 bits |
|always-on RFC5245 |     yes      |     yes      |   48 bits** |

*TCP-ENO requires applications to break the tie, while TCP-use-TLS only
 requires applications to set a single bit indicating they are about to
 engage in a simultaneous open.

**RFC5245 uses 64 bits, but TCP-use-TLS shows you can do the same thing
  with only 48 bits.

If we agree on the table, then it's just a subjective question of how
much the working group values simultaneous open vs. option space.

> As it is, the b bit is an effort to find the knee in the cost-benefit
>> curve.  I.e., is it worth 4+ bytes of option space to make
>> simultaneous open work?  Hard to make that case.  But is it worth one
>> *bit* not to shut the door completely?  Quite possibly.
> This would be more convincing if you provided an example where it
> actually added value. In the case you suggest above, where the sides
> are independently able to break the symmetry, why not simply do so
> via signaling?

I'm not sure I know what you mean about signaling.  But suppose two
hosts are behind NATs and an application cannot use TCP between the two
hosts except through simultaneous open.  Here are three realistic
scenarios in which applications can easily be modified to break the
symmetry.  Again, this isn't transparent, but it's not a huge burden,

  * The applications use STUN to learn their public IP address and NAT
    type and communicate this to the other node or register it with a
    public rendezvous service.  The applications can then set b based on
    the public IP addresses and ports as previously discussed.

  * The applications are part of a DHT in which each node has a unique
    node ID.  In this case, the application can set b based on lowest
    node ID.

  * The simultaneous open is triggered by some external broker service
    that sends a message to both hosts, in which case the broker can
    assign the b bit to the two sides.

>> > I am unclear on why the active opener needs to have an ENO segment
>> > in his first ACK. Can you explain?
>> There are two reasons:
>> 1. Given the prevalence of asymmetric routes, it's highly likely that
>>    situations will arise where ENO options are stripped in one
>>    direction but not the other.  Therefore, both sides need to know
>>    not only that the other endpoint supports ENO, but that the other
>>    endpoint can receive ENO options.  If you remove the requirement
>>    for that ACK, a scenario such as Figure 7 would result in total
>>    failure of the TCP connection, not just failure to encrypt.  We
>>    definitely want to avoid that.
>> 2. Suboption data could involve parameters that are not universally
>>    supported, in which case the active opener may which to disable
>>    TCPINC based on the contents of the SYN-ACK segment.
> These seem like an argument for having the passive opener supply one
> in the SYN/ACK, not for having the active opener supply one in his first
> ACK.

Neither of the two examples I made will work if you do not require ENO
in the first ACK from each side (including the active opener--obviously
the SYN-ACK includes an ENO option).  To see this for my point #1 above,
let's look at the example from Figure 7:

        (1) A -> B:  SYN      ENO<X,Y>
        (2) B -> A:  SYN-ACK  ENO<X>    [ENO stripped by middlebox]
        (3) A -> B:  ACK

Now suppose B is not expecting an ENO option on flow 3.  B will enable
encryption, while A will not, and the whole TCP connection will fail
(not just fail to encrypt).  That's very bad.

To see this for #2, imagine Y is a variable-length suboption:

        (1) A -> B:  SYN      ENO<X,Y>
        (2) B -> A:  SYN-ACK  ENO<Y 123>
        (3) A -> B:  ACK                [A does not like parameter 123]

Here B chooses some sort of parameter 123 that A does not support.  123
might be a bitmask of B's supported public key ciphers, and the
designated set might not intersect with A's.  In TCP-ENO, A disables
encryption by not sending an ENO option in its ACK.  However, if B does
not expect the ENO option, B will already have committed to spec Y
encryption after flow 2 and again the whole TCP connection will fail.

>> One big challenge of simultaneous open is that each side must
>> acknowledge the other side's SYN before seeing the other side's SYN-ACK.
> Consider the version in the TCP-use-TLS draft where in the case of
> simultaneous
> open you have a large tiebreaker in both the SYN and the SYN/ACK. In that
> case, it's quite straightforward to determine who is is who. In that case,
> you
> can negotiate as I indicate above.

I understand how TCP-use-TLS does this, but at this point we are going
around in circles.  Ultimately this comes down to a question of
subjective design priorities.  I'd like to hear how you and other
working group members answer the following two questions a scale of 1 to

   A. How much do you care about conserving TCP option space?

   B. How much do you care about simultaneous open.

For me, I'd rate A a 9/10 and rate B a 5/10, which is why TCP-ENO looks
the way it does.

> Easiest would probably be to simply make the number somewhat
> smaller, e.g., 112 bits, which NIST has at about 2048 bits in FFDHE.

I think that probably works for us.

> I've read the charter, but I don't think it's actually that clear here. It's
> obvious that tcpinc doesn't supply PFS if you have a long-running
> connection and never re-key, so I think the question is what the
> desired properties are between connections. This language doesn't
> actually seem particularly helpful on this point. In any case, if
> part of the point of TCP-ENO is to allow for negotiating protocols
> defined outside of TCPINC, then this seems like an unnecessary
> restriction (as, in fact, do the rest of these).

Again, please don't confuse things by mentioning PFS, which is required
by neither the charter nor the TCP-ENO draft.  The charter contains the
following language:

        When encryption is enabled, then the protocol:
        - must always provide forward secrecy.

This is verbatim, no ellipsis or anything.  Seems pretty clear to me.
The TCP-ENO draft contains the following language:

   o  Specs MUST NOT allow the negotiation of encryption modes that do
      not provide forward secrecy.

I do not favor amending the charter to weaken confidentiality, but that
is a debate we can have.  However, given the current charter, it seems
beyond debate that TCP-ENO should ensure the same basic security
properties as TCPINC.  The whole point is that applications should be
forward-compatible with future methods of obtaining the same security
guarantees as TCPINC.

>> S 4.1.
>> > Given that session IDs are required to be unique, why bother with the
>> > spec-id prefix?
>> Precisely to guarantee this uniqueness.  If one spec uses SHA-256 for
>> session IDs and another uses Keccak, no standard cryptographic
>> assumption implies uniqueness without that tag byte.
> Can you unpack this some?

Let's say that we can compute two transcripts, A and B, such that
SHA-256(A) == KECCAK-256(B).  This doesn't violate any standard
cryptographic assumptions.  Yet without the tag byte, it would be
devastating to TCP-ENO's security in the event that different specs use
different hash functions.


Since you mentioned RFC5245, maybe we should consider "controlling" and
"controlled" instead of A and B or initiator and responder.  But anyway,
let's debate terminology after we've got the more basic goals and
structure down.