Monday, November 23, 2015

An overview of GnuTLS 3.4.x

This April GnuTLS 3.4.0 was released, as our stable-next  branch, i.e., the branch to replace the current stable branch of GnuTLS (which as of today is the 3.3.x branch). During that time, we also moved our development infrastructure from gitorious to gitlab.com, a move that has improved the project management significantly. We now have automated builds (on servers running on an Openstack system supplied by Red Hat), continuous integration results integrated to the development pages, as well as simple to use milestone and issue trackers. For a project which as it stands is mostly managed by me, that move was godsend, as we can have several new development and management features with considerable less effort. That move unfortunately was not without opposition, but at the end a decision had to be taken, which is driven by pragmatism.

Assessing the last 12 months we had quite a productive year. Several people offered fixes and enhancements, and I still remain the main contributor -though I would really like for that to change.

Anyway, let me get to the overview of the GnuTLS 3.4.x feature set. For its development we started with a basic plan describing the desired features (it still be seen at this wiki page), and we also allowed for features which did not threaten backwards compatibility to be included during in the first releases. These were tracked using the milestone tracker.

As we are very close to tag the current release as stable, I'll attempt to summarize the new features and enhancements in the following paragraphs, and describe our vision for the future of the library.
  •  New features:
    • Added a new and simple API for authenticated encryption. The new API description can be seen in the manual. The idea behind that change was to make programming errors in encryption / decryption routine usage as difficult as possible. That was done by combining encryption and tagging, as well as decryption and verification of the tag (MAC). That is of course taking advantage of the AEAD cipher constructions and currently can be used by the following AEAD ciphers: AES-GCM, AES-CCM, CAMELLIA-GCM, and CHACHA20-POLY1305.
    • Simplified the verification API. One of the most common complains on TLS library APIs is their involved complexity to perform a simple connection. To our defense part of that complexity is due to specifications like PKIX which forwards the security decisions to application code, but partly also because the APIs provided are simply too complicated. In that particular case we needed to get rid the need for elaborate callbacks to perform certificate verification checks, and include the certificate verification in the handshake process. That means, to move the key purpose, and hostname verification to the handshake process.  For that we simplified the current API by introducing gnutls_session_set_verify_cert() and gnutls_session_set_verify_cert2(), when a key purpose is required. The call of the former function instructs GnuTLS to verify the peer's certificate hostname as part of the handshake, hence eliminating the need for callbacks. An example of a session setup with the new API can be seen in the manual. If we compare the old method and the new, we can see that it reduces the minimum client size by roughly 50 lines of code.
    • Added an API to access system keys. Several operating systems provide a system key store where private keys and certificates may be present. The idea of this feature was to make these keys readily accessible to GnuTLS applications, by using a URL as a key identifiers (something like system:uuid=xxx). Currently we support the windows key store. More information can be seen at the system keys manual section.
    • Added an API for PKCS #7 structure generation and signing. Given that PKCS #7 seems to be the format of choice for signing kernel modules and firmware it was deemed important to provide such an API. It is currently described in gnutls/pkcs7.h and can be seen in action in the modsign tool.
    • Added transparent support for internationalized DNS names. Internationalized DNS names require some canonicalization prior to being compared or used. Previous versions of GnuTLS didn't support that, disallowing the comparison of such names, but this is the first version which adds support for the RFC6125 recommendations.
  •  TLS protocol updates:
    • Added new AEAD cipher suites. There are new ciphersuites being defined for the TLS protocol, some for the Internet of Things profile of TLS, and some which involve stream ciphers like Chacha20. This version of TLS adds support for both of these ciphersuites, i.e., AES-CCM, AES-CCM-8, and CHACHA20-POLY1305.
    • Added support for Encrypt-then-authenticate mode for CBC. During the last decade we have seen several attacks on the CBC mode, as used by the TLS ciphersuites. Each time there were mitigations for the issues at hand, but there was never a proper fix. This version of GnuTLS implements the "proper" fix as defined in rfc7366. That fix extends the lifetime of the CBC ciphersuites.
    • Included Fix for the triple-handshake attack. An other attack on the TLS protocol which required a protocol fix is the triple handshake attack. This attack took advantage of clients not verifying the validity of the peer's certificate on a renegotiation. This release of GnuTLS implements the protocol fix which ensures that the applications which rely on renegotiation are not vulnerable to the attack.
    • Introduced support for fallback SCSV. That is provide the signaling mechanism from RFC7507 so that applications which are forced to use insecure negotiation can reasonably prevent downgrade attacks.
    • Disabled SSL 3.0 and RC4 in default settings. Given the recent status on attacks on both the SSL 3.0 protocol, and the RC4 cipher, it was made apparent that these no longer are a reasonable choice for the default protocol and ciphersuite set. As such they have been disabled.

That list summarizes the major enhancements in the 3.4.x branch. As you can see our focus was not to only add new security related features, but to also simplify the usage of the currently present features. The latter is very important, as we see in practice that TLS and its related technologies (like PKIX) are hard to use even by experts. That is partially due to the complexity of the protocols involved (like PKIX), but also due to very flexible APIs which strive to handle 99% of the possible options allowed by the protocols, ignoring the fact that 99% of the use cases found in the Internet utilize a single protocol option. That was our main mistake with the verification API, and I believe with the changes in 3.4.x we have finally addressed it.

Furthermore, a long time concern of mine was that the stated protocol complexity for PKIX and TLS, translates to tens of thousands lines of code, hence to a considerable probability for the presence of a software error. We strive to reduce that probability, for example by using fuzzying or static analyzers like coverity and clang, and audit, but it cannot be eliminated. No matter how low the probability of an error per line of code is, it will become certainty in large code bases. Thus my recommendation for software which can trade performance for security, would be to consider designs where the TLS and PKIX protocols are confined in sandboxed environments like seccomp. We have tested such a design on the openconnect VPN server project and we have noticed no considerable obstacles or significant performance reduction. The main requirement in such an environment is IPC, and being able to pack structures in an efficient way (i.e., check protocol-buffers). For such environments, we have added a short text in our manual describing the system calls used by GnuTLS, to assist with setting up filters, and we welcome comments for improving that text or the approach.

In addition, to allow applications to offer, a multi-layer security, involving private key isolation, we continue to enhance, the strong point of GnuTLS 3.3.x. That is, the transparent support for PKCS #11. Whilst sometimes it overlooked as a security feature, PKCS #11 can provide an additional layer of security by allowing to separate private keys from the applications using them. When GnuTLS is combined with a Hardware Security Module (HSM), or a software security module like caml-crush, it will prevent the leak of the server's private key even if the presence of a catastrophic attack which reveals the server's memory (e.g., an attack like heartbleed).

Hence, a summary of our vision for the future, would be to be able to operate under and contribute to multi-layer security designs. That is, designs where the TLS library isn't the Maginot line, after which there is no defense, but rather where the TLS library is considered to be one of the many defense layers.

So, overall, with this release we add new features to simplify the library, modernize its protocol support but also enhance GnuTLS in a way to be useful in security designs where multiple layers of protection are implemented (seccomp, key isolation via PKCS #11). If that is something that you are interested at, we welcome you to join our development mailing list, visit our development pages at gitlab, and help us make GnuTLS better.