Is Change Possible?

TLS has succeeded in becoming the universal transport encryption protocol universally supported across multiple different operating systems, language environments, and programs throughout the Internet.

If TLS has been such a success, why should we change? Is there a real, legitimate need to start over from scratch, re-evaluate our principles, and come up with a better plan in every regard to the protocol's design, or should we try to fix TLS instead, identifying problems in the protocol's design, attempting to fix them, and publishing new versions of TLS with the changes?

If we're starting over, where do we stop? Is TLS flawed as a protocol? What about X.509 certificates? Do those need to be replaced too? Do we need ASN.1 to die in a fire? Should we try to start over fresh and wash it all away?

We ask you to, for a brief moment, suspend any disbelief that TLS is irreplacable and try to imagine a future where everyone's TCP sessions are encrypted with a protocol better than TLS which uses a certificate format better than X.509, a format that's simple, human readable, and describable via a context-free grammar. We know we're talking ponies and unicorns here, but is that really so bad?

The Status Quo

Transport Layer Security is presently the foremost method of encryption used on the Internet today, with multiple different implementations by different vendors:

  • OpenSSL: The most popular TLS implementation, maintained by Google security boffins Ben Laurie and Adam Langley who are doing some pretty top notch work salvaging it. Widely regarded by the security community as an enormous steaming pile of poo with a byzantine API and surrealist implementation. Just got popped by Heartbleed, a trivial coding error which has now been shown to leak private keys. Previously subject to even worse bugs, like a remote code execution vulnerability.
  • NSS: The original transport encryption library which dates all the way back to Netscape, used by Firefox. Widely regarded by the security community as an enormous stinking pile of poo with a byzantine API and surrealist implementation. Was popped in 2013 by a remote code execution vulnerability.
  • GnuTLS: An alternative TLS library created by the GNU project. Makes some moderate improvements in the space of TLS APIs, by decoupling encryption from the I/O layer. Was recently popped by a certificate validation bug and in 2008 was vulnerable to a remote code execution vulnerability.
  • SecureTransport: A TLS implementation most notable for being written by Apple and goto fail

Heartbleed has received an awful lot of attention recently, described by a certain prominent security researcher as 11 on a scale from 1 to 10. Yet if we look back, we actually find worse vulnerabilities both in OpenSSL and other major TLS implementations. We also find patterns of confusing APIs, confusion around return values, and overall poor code quality. Here is an example from the OpenSSL codebase:

https://github.com/openssl/openssl/blob/master/ssl/ssl_lib.c#L1054

int SSL_shutdown(SSL *s)
        {
        /* Note that this function behaves differently from what one might
         * expect.  Return values are 0 for no success (yet),
         * 1 for success; but calling it once is usually not enough,
         * even if blocking I/O is used (see ssl3_shutdown).
         */
           

Whaaaaaaaaaaaaaaaaaaaaa???

A similarly confusing API was implicated in the recent GnuTLS certificate validation bug which was reminiscient of Apple's recent goto fail bug for bypassing TLS certificate validation.

Is it really that bad?

The status quo does not instill confidence about the future security of the Internet. We can also observe some common themes about the cause of the problems:

  • Lack of memory safety: resulted in the remote code execution bugs prevalent throughout multiple TLS stacks and the recent Heartbleed bugs which disclosed TLS private keys and encrypted conversations.
  • Confusing conventions (or lack thereof): when language conventions like returning a 0 or -1 vs 1 or 0 to indicate success or failure are used simultaneously, programmers can become confused as to whether given operations are succeeding or failing, which has lead to bugs in practice such as the recent SecureTransport and GnuTLS certificate validation vulnerabilities. How can any reasonable security hardening take place in an environment where people can't agree on whether 0 means success or failure?
  • Confusing code: The goto fail bug was caused by confusing language syntax, namely the lack of braces in an if statement. Ideally this shouldn't be possible.

We can note similar problems with the X.509 certificate format, which was was designed without a proper understanding of the security applications of formal language theory making the format difficult to work with:

The complexities of the X.509 certificate format were recently illustrated by a paper on Frankencerts, certificates automatically assembled from fragments of other TLS certificates which exposed a number of bugs in TLS certificate validation implementations across multiple stacks.

We could continue to embrace TLS and X.509, and create a new TLS implementation in a memory safe systems programming like Rust, however this overlooks the fact that TLS is black fucking magic and producing a new, interoperable TLS implementation could only be done by wizards of such black magic. We would argue that it's better to start over because TLS is a fractal of bad design.

Last, but not least, we might bring up the fact that "Transport Layer Encryption" doesn't work on the OSI transport layer (layer 4), but in fact works on the session layer (layer 5) and presentation layer (layer 6). Despite the fact SSL was renamed to TLS, when they did the renaming they even got that wrong. TLS is wrong at every level.

Sketches of a Better Future

Designing a new transport encryption protocol from scratch is an absurdly difficult undertaking. It's possibly the hardest type of cryptographic protocol to design, and many attempts by amateurs to design such a protocol immediately fall victim to a number of attacks, like replay attacks, timing attacks, and various other information oracles like padding oracles.

Let's say we want to throw the baby out with the bathwater in regard to TLS, but don't want to start completely from scratch when designing a next generation transport encryption protocol. Where should we look?

CurveCP, designed by Daniel J. Bernstein (djb), provides a glimpse into the future of transport protocols, as does the more recent MinimaLT. These protocols provide encrypted transport atop the UDP protocol, in hopes of defeating attacks on TCP's availability, by using things like RST packets.

Unfortunately, the modern Internet does not look favorably upon UDP. Preliminary benchmarks of CurveCP showed nearly complete packet loss in the face of TCP congestion which is arguably a problem with CurveCP's decongestion algorithm but much more likely an intractable problem with trying to do bulk transfers with UDP. While djb has his heart in the right place, his vision of a DoS-proof UDP-based transport encryption protocol probably isn't a particularly practical one on the modern Internet.

The newly formed Tcpcrypt group is working on approaches to actually encrypt the transport layer (i.e. layer 4) and, as much as possible, the network layer too. They are also decoupling their efforts from key authentication schemes, immediately pursuing opportunistic encryption which is, by default, susceptible to Man-in-the-Middle (MitM) attacks.

However, Tcpcrypt is being designed so it can integrate with authenticated key exchange mechanisms, including TLS. This provides a nice layering of concerns: true transport layer encryption is decoupled from the way in which keys are authenticated. It also prevents blanket sureveillance without active MitM (although a likely outcome of a widescale deployment would be nation state adversaries upping the ante and performing more active MitM)

We wish the Tcpcrypt group the best of luck and hope they can accomplish this audacious goal (seriously, not sarcastically)! This seems like a great goal to pursue.

Can we build a better CurveCP?

CurveCP seems like a reasonable basis for a minimalistic transport encryption protocol with forward secrecy. There are already many TCP-based variants of CurveCP, however they all target particular use cases. The two most notable:

  • CurveZMQ: CurveCP adapted to be the message encryption format for the 0MQ brokerless messaging system. CurveZMQ also specifies an SSH-inspired certificate format which is formally described by an ABNF grammar.
  • Nitro: a messaging system similar to 0MQ which uses a CurveCP inspired protocol atop TCP for encryption. Alas, they dropped forward secrecy from the handshake, making it somewhat inferior to the CurveCP and CurveZMQ (as well as TLS ECDHE) handshakes.

Unfortunately, these are the two cloest things to a usable CurveCP implementation, and they are special cased to messaging protocols. This means these protocols can't provide the same sort of generalized encryption for TCP streams that TLS provided.

CurveCP isn't the be-all and end-all of key agreement protocols either. There are other places we can and should be looking:

Can we make a better certificate format?

X.509. ASN.1. I'm sure just by saying that some of you are ready to to claw your own eyeballs out.

Is it so much to ask for certificates to be human-readable? If there were, would there other potential benefits? What if certificates were described in terms of context free grammars instead of a byzantine binary code with a proliferation of formats and "weird machine" parsing properties? Could we make a more LANGSEC friendly certificate format that would simultaneously make certificates easier to reason about?

Perhaps we could dig through the history of Internet standards and examine such crazy things as HTTP, MIME, and URIs as ways of representing resources and messages, and deviate away from the "certificate is an opaque blob until I run it through openssl x509" approach to figuring out what's going on.

So do we burn it all down and start over or not?

One way or another, we need encryption for TCP streams that we can trust. A lot of work has gone into making TLS as successful as it is, and any solution that seeks to replace it will likewise be a lot of work that could just as well be spent trying to fix the problems with TLS.

Starting over or not is a difficult question. But it's one worth discussing.

Join Our Mailing List Join Tcpcrypt Mailing List