On 11/19/15 11:46 PM, David Mazieres wrote:
>  C5. Leave it to individual encryption specs to make TCP-SO work
>      automatically.  For DH-based specs, there may be an easy trick.
>      However, for public-key-based specs--such as those relying on RSA
>      or post-quantum crypto--this would even for non-SO more than double
>      computational cost at passive openers and add an extra round trip
>      to client-speaks-first protocols.  (This is what Bryan has been
>      advocating, at least for ECDH.)

You misrepresent what I'm advocating.  I've already pointed out at least
twice how tcpcrypt could readily be made to support public-key-based
exchange and support SO without ever failing open, and without either
doubling the computational cost or adding an extra round trip in the
common case.

To summarize one way of doing this cleanly:

Assume TCP-ENO works more-or-less as currently specified, such that each
endpoint picks 'p' and 'b' bits and the 'pb' combination serves as a
priority that can be used for tiebreaking - BUT, the TCP-ENO protocol
doesn't just give up (and either fail open or abandon) if both
endpoints' pb values happen to end up equal.  Instead, TCP-ENO simply
passes the negotiated pair of pb values - e.g., as 'local_pb' and
'remote_pb' - to the negotiated protocol (e.g., USE-TLS or tcpcrypt),
which can then decide how to use them.  Maybe some negotiated protocols
(e.g., USE-TLS) will still need to bail if local_pb == remote_pb, but
let's say we want tcpcrypt to handle all cases gracefully.

Each endpoint's public-key-based tcpcrypt key exchange follows something
like this pseudocode:

local_symkey := 0x00...00 // all-zero symmetric key of appropriate size
remote_symkey := 0x00...00
if (local_pb >= remote_pb) { // active or equal role
        send local_pubkey
}
if (remote_pb >= local_pb) { // passive or equal role
        receive remote_pubkey
        local_symkey = pick_random_key()
        encrypt_and_send(remote_pubkey, local_symkey)
}
if (local_pb >= remote_pb) { // active or equal role
        remote_symkey = receive_and_decrypt(local_prikey)
}
master_local_to_remote := derive_master(local_symkey, remote_symkey)
master_remote_to_local := derive_master(remote_symkey, local_symkey)

Each endpoint then uses 'master_local_to_remote' to encrypt and append
MACs to traffic it sends to the other endpoint, and
'master_remote_to_local' to decrypt and integrity-check traffic it
receives.  Once these master secrets are derived, everything else in the
protocol can be entirely oblivious to whether the endpoints are
operating in active/passive or symmetrical roles.

Notice that whenever TCP-ENO's 2-bit tiebreaking mechanism succeeds and
produces different values (local_pb != remote_pb), the above pseudocode
yields exactly the same protocol exchange as the optimized one you like,
namely:

  A -> B:  SYN(ENO)
  B -> A:  SYN-ACK(ENO)
  A -> B:  (ENO) PKA
  B -> A:  {NB}_PKA
  B -> A:  data
  A -> B:  data

In this case, at each endpoint either local_symkey or remote_symkey will
be an all-zero key, but that's OK because the other one is fresh and
protected in transit by public-key encryption.  And I think we all can
agree that TCP-ENO's tiebreaking mechanism *should* work *almost* all
the time in practice, given that SO is uncommon in the first place and
even when it happens (intentionally or not) TCP-ENO still provides a
50-50 chance of successful tiebreaking via the low-order b bit.

In the rare case that the tiebreaking mechanism doesn't succeed, all of
the if statements in the above pseudocode will evaluate to true at both
endpoints, yielding a perfectly operational symmetric version of the
same key exchange.  In this case, local_symkey and remote_symkey end up
being nonzero at both endpoints, but everything still just works.  This
situation will incur that doubling of computational cost and perhaps an
extra round trip, but I don't think we care about if this is expected to
be such an uncommon case.

Finally, notice that the above pseudocode doesn't add any code specific
to SO - i.e., there are no SO-specific statements that we should worry
is unlikely ever to be tested, apart from the conditionals themselves.
This approach adds only one conditional that might not already be needed
anyway in your asymetric-only version of the protocol, namely the second
if (local_pb >= remote_pb) test.  And it eliminates any role-specific
conditionals you might currently have elsewhere in tcpcrypt after key
exchange.

So are there any other reasons that it would be extremely burdensome to
avoid breaking SO and potentially introduce unnecessary fail-open risks?

Bryan

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

_______________________________________________
Tcpinc mailing list
Tcpinc@ietf.org
https://www.ietf.org/mailman/listinfo/tcpinc

Reply via email to