Four weeks ago I posted about some of the cryptography in clearskies. I didn't mention the cryptography I am planning on using for the transport protocol because I had chosen an existing TLS mode, which I figured was an easily defensible position.
As is explained in the earlier post, ClearSkies relies on pre-shared AES keys to encrypt the transport. Since it's unlikely that users will have a secure channel to share the keys, the protocol supports access codes, which are both temporary and single-use. The access code is used as a pre-shared key to create a channel to exchange the full AES pre-shared key.
Since the access code will be shared insecurely such as over IM or SMS, it's important that the key exchange happen with perfect forward secrecy. That is to say, even if the access code is later compromised, the pre-shared key should stay secret.
Finally, to make it easy to share, the access code should be as short as possible. In essence, it should function more like a token to prove identity and less like an encryption key.
The most obvious attack vector is that someone who completely controls the access code exchange medium can perform a man-in-the-middle attack. For example, they could intercept the outgoing IM and replace the access code with their own access code, and then be able to stand in between the peers and record all data.
If they have live read-only access to the access code, they can beat the peer to the connection.
I consider these to be reasonable security/usability trade-offs for this system, but would welcome suggestions to overcome them.
RFC 4279 has a mode that neatly provides
for all of the requirements,
TLS_DHE_PSK_WITH_AES_128_CBC_SHA. It uses an
ephemeral Diffie–Hellman key exchange, which gives it perfect forward security,
and supports pre-shared keys. As long as clients limit the TLS mode to only
this mode, we don't have to do any more work. I also like that this limits the
size of the clearskies protocol spec and the surface area of a security audit.
The problem is that crypto APIs almost universally don't support this mode. It's missing in OpenSSL (at the time of writing), although the version without DHE exists. It's also missing in the Win64 API and the Apple Crypto API.
It's present in gnutls, but ruby doesn't have any bindings for gnutls. This is only relevant because the reference implementation is being written in ruby, so it's inconvenient that OpenSSL (which is part of the ruby standard library), doesn't provide support.
The easiest solution for now will be to create a binding for gnutls. gnutls seems to be widely installed on the Linux machines I have access to, but not on OS X.
Another solution would be to emulate the
mode by creating a similar protocol in the spec (but skipping things specific
to TLS such as cipher negotiation). This would add quite a bit of stuff to the
core spec (which is already far too long), but it would make things
straightforward for people who cannot use gnutls for whatever reason. The
biggest weakness with this approach is that it will increase the surface for
security vulnerabilities greatly.
Yet another approach be to patch openssl to support the mode and then ship the patched library with the program.
Finally, we could implement the relevant parts of TLS in ruby (using OpenSSL as a backing library for the crypto primitives.)