RFC 8548: Cryptographic Protection of TCP Streams (Tcpcrypt)
tools.ietf.org
tools.ietf.org
So the goals of the tcpcrypt project back then were 1) solve the performance problem by making it practical to encrypt essentially all TCP traffic, 2) make undetectable widespread eavesdropping impractical, 3) provide a pathway for insecure applications to achieve high network security with minimal effort, and 4) avoid the traps applications commonly experience such as low-quality pseudo-random seeds, or leaking session keys through memory errors.
We solved #1 by carefully constructing the protocol to minimize public key overhead on the server and allow optimized server authentication. In particular, with low-exponent RSA (popular at the time), the server-side computation was only encryption (which is much, much cheaper than decryption). Moreover, for strong security (with server-side authentication), servers could perform batch signing in which a single signature could be amortized over many connections. The result was dramatically better performance for the original version of tcpcrypt, which you can see described here:
http://www.scs.stanford.edu/~dm/home/papers/bittau:tcpcrypt....
We solved #2 by encrypting everything, and providing a mechanism to tie authentication to that encryption. So if an ISP systematically mounted a man-in-the-middle attack, they would cause authentication to fail. Moreover, it would be easy to run tests by, for instance, logging session IDs at connections between various endpoints and comparing them after the fact. That still meant ISPs could violate the privacy of unauthenticated connections, but then at least we would know about it and could decide, as a society, whether we wanted this kind of eavesdropping.
#3 was really the ultimate goal--strong security everywhere even with insecure legacy protocols. The problem with legacy protocols is that they didn't all contain a way to add a "STARTTLS" verb. So what we did was give tcpcrypt an "Application-aware" bit that would allow out-of-band signaling that the application knows about tcpcrypt. This bit would allow legacy application maintainers to shoe-horn in stronger security in a completely backwards-compatible way, and if the project really took off could then ultimately disable the insecure old unauthenticated protocol.
Finally, #4 was handled by keeping session keys in the kernel (so they can't leak in core-dumps, uninitialized data, buffer errors, etc.), and providing a fresh session ID that can be authenticated even without a good source of randomness.
As time went on, the performance argument (#1) became much less relevant, with the result that tcpcrypt now uses ECC crypto instead of RSA. (Though the batch-authentication optimization is still available.) However, #2 actually became more relevant (at least in 2013), and #4 even more so with all these catastrophic bugs (like heartbleed, or Debian disabling randomness in OpenSSL). It's also still much, much harder than it should be to write software that encrypts network traffic, particularly where one doesn't just want the standard anonymous-client to server-with-X.509-certificate setup. If people adopt tcpcrypt, setting up an authenticated, encrypted TCP connection will become comparable to checking a unix password--just a few lines of code.
A lot of this is clearer if you read the companion TCP-ENO RFC, rather than tcpcrypt. The goals and rationale and overall negotiation mechanism were broken out into a separate document to allow better upgradability to future encryption protocols: https://tools.ietf.org/html/rfc8547
What am I missing here? An active attacker will just terminate the connection on both ends. There will be 2 authenticated session IDs at L3. At L7, how will an application authenticate the L3 ID in such a way as to discover a MITM? Even if it can, there needs to be a new ioctl (or similar) for the application to learn the L3 ID. That's rough for the large legacy of applications that might otherwise benefit from this.
I'm sure I'm missing it, since this has been 10 years in the making, authored by well known folks. The referenced USENIX paper discusses how both ends of the tcpcrypt connection can know there's no MITM. However, in the case of intercept, the other end of the connection is the MITM.
Because tcpcrypt uses ephemeral public keys, there's no L7 identity proof, such as is offered by TLS (as far as it can). This further permits MITM.
An active attacker can also just strip the TCP-ENO bits from the SYN. If [just] one side insists, the attacker can strip it just from the other side, for performance.
In particular, it is possible to use a zero knowledge protocol where a MITM attacker cannot determine if authentication were actually used or not except via changes in user behavior if there are any. For protocols which have a mixture of authed and non-authed usage, this can create a significant risk of discovery for an active attacker.
In any case, authentication is inherently tied up with "identity" which is significant UI and application specific considerations which simply do not exist for ephemeral encryption. TCPcrypt achieves an appropriate layering which separates these concerns while killing content observation by passive attack and increasing the risk of detection otherwise.
Re: stripping, again-- how to handle the absence of encryption is also an application relevant decision. TCPcrypt provides sufficient tools for applications to set appropriate policies.
> In particular, it is possible to use a zero knowledge protocol where a MITM attacker cannot determine if authentication were actually used or not except via changes in user behavior if there are any.
I'd love for you to expand more on this. What I can't think of is a realistic scenario where it's possible to validate the session id in a secure way, but there is also some reason that we couldn't just use TLS with client certificates.
TLS with client certificates requires securely getting and certifying the certificates. Somehow. Yet many alternatives exist.
For some applications keys might exist in dns-- but in others no dnssec or names could be assumed.
For some applications the endpoints can be assumed to have a shared password, so some SPAKE can be used to authenticate.
For some applications an identity exists in some external consensus system that the other side can provide proof from, but which doesn't fit into the x509 model. (For example, if you wanted to use keys registered in namecoin to authenticate your identity).
For some applications you would like to use an anonymous group signature: "This user is on the authorized list, but beyond that, I don't want to know what user this is."
For some applications each party should be cryptographically unidentified, anonymous, and indistinguishable to from any other party unless both of their keys match, because otherwise you could track the parties around the internet from IP to IP. TLS/client cert lets you achieve this for one side-- you can decline to send the client cert if the server identity isn't to your liking, but you can track the server's identity around.
None of these examples fit nicely into the TLS/x509 model. All of them, including something functionally equivalent to TLS+x509clientcerts can be implemented on top of TCPcrypt.
An example would be if you don't have a certificate. Maybe you just have a pre-shared secret or a kerberos ticket. Or worse, maybe you just have a password, and so need to use a PAKE protocol or something to authenticate the session. Or maybe you are using an RPC protocol, like NFS, that doesn't let you add TLS in a backwards-compatible way, but where the client and server do share some secret file handle.
Given that letsencrypt exists, I don't see why you wouldn't have a cert.
> Maybe you just have a pre-shared secret or a kerberos ticket.
The pre-shared secret could be a cert which would work with TLS.
> Or worse, maybe you just have a password, and so need to use a PAKE protocol or something to authenticate the session.
I can't think of a realistic example of such a protocol. What protocol uses PAKE, but doesn't support encryption, but will verify a session id? It seems like using TLS would be simpler.
> Or maybe you are using an RPC protocol, like NFS, that doesn't let you add TLS in a backwards-compatible way, but where the client and server do share some secret file handle.
Such a scenario still requires modifications to the NFS server and client software, which, if done, isn't clear why it would be better than just layering TLS onto the protocol.
That makes an enormous number of assumptions-- that you have a domain name, that you accept inbound connections, and that "gee some server connected to my name and got me once" is a remotely acceptable criteria for identity in your application.
[1]. From Section 8: "... tcpcrypt does not protect against active network attackers unless applications authenticate the session ID. If it can be established that the session IDs computed at each end of the connection match, then tcpcrypt guarantees that no man-in-the-middle attacks occurred ..."
Past cryptographic network transports have committed the sin of layer violation by conflating stream management with correspondent authentication. Authenticating that you are talking to whom you think you're talking to is a complex, highly application specific process which in many cases even requires its own UI.
The code to implement authentication is complex and has (e.g. x509 parsing) frequently been a source of vulnerabilities, making it unattractive for implementation in network stacks. Witness the use of TLS for non-webby applications where there aren't readily user provided domain names and things don't fit nicely into a one-side-authenticated server/client model-- they often turn into key management nightmares.
TCPcrypt handles the stream encryption and integrity in the network layer where it can do so seamlessly. It hands up the stack the required hooks so that authentication can be performed in whatever way makes sense for the application. As a bonus, even when authentication isn't used applications are protected against dragnet passive content surveillance.
Assuming you know in advance of your connection a correct public key for the corespondent. How you got it, how you know it's correct is ... left up to you. Yet it isn't secure if its not done exactly right.
This is like arguing that a one time pad provides for unbreakable encryption. True in one sense, often not true in practice.
So, like, the protection against passive listeners is nice. But, what I don't understand is a specific example of where using tcpcrypt would be better than just using a widely used TLS library.
Which is still useful in that it prevents organizations from simply 'tapping glass'.
I'll take the imperfect security of forcing various agencies to expend resources to go after me personally (which is a small chance of happening) versus the ease of them simply vacuuming up all the bits.
It's why I also think that unauthenticated encryption is useful even if it doesn't protect against active attacks: the extra resources needed for the active component forces the adversary to make choices on who to target.
On the one hand: protection against passive monitoring is a clear win. On the other hand, in my opinion, saying something like: "which is a small chance of happening" is kinda problematic: you don't need that security, and if some agency targeted you, like, maybe there is a minor chance of personal embarrassment. However, there are also people in the world that when they are targeted, they could face prison time or worse. And the people with the most to lose, are also the most likely to be targeted. So, IMO, it would be somewhat irresponsible to rely on tcpcrypt - it gives people that don't really need protection protection that they don't need, but leaves everyone that does out to dry.
The thing is - I just can't think of a use case where it makes sense. HTTP is often used with TLS - and TLS offers protection against active attackers. Many new protocols are based on HTTP - right or wrong, that generally means they get TLS with whatever library they use. DNS is moving toward DoT and DoH. SMTP has STARTTLS already which does the same thing. FTP has been replaced by SFTP / SCP. Telnet is replaced by SSH. Instant messaging protocols have built in security.
What protocol and who would actually benefit from this?
All of them.
We could have encrypted HTTP back in 2000 if HTTP Upgrade had been more widely deployed:
* https://en.wikipedia.org/wiki/HTTP/1.1_Upgrade_header
How much of the stuff that the NSA (and others) did that Snowden exposed could have been made impossible, or at least more difficult, if there was more encrypted traffic to deal with?
Sure, there wouldn't have been little padlock icons, and active attacks could still be done, but it wouldn't have been as much wholesale surveillance.
Instead, between 2000 and (say) 2016—when Let's Encrypt/ACME went live—we had selective encryption only for 'important' sites where people thought it worth the cost/hassle of getting a cert and going HTTPS.
Even now, there are plenty of legacy HTTP-only sites: why not have an Apache module available that does opportunistic encryption, even if the end-user doesn't get a padlock icon.
The main promise IMO is providing transparent encryption to old applications and protocols that use TCP without their own encryption layer.
It is not possible to provide transparent authenticated encryption to everyone without some sort of CA system for IPs, but we should still provide the strongest privacy available by default, which is protection against passive eavesdropping.
Can anyone enlighten me about what it's for? How does it fit in compared on the one hand to TLS and on the other hand to things like WireGuard.