Significant SSL/TLS improvements in Java 8

The next generation of the Java runtime, version 8, is around the corner, with the first production release planned for this month (March 2014). The new runtime brings a slew of language improvements and it’s actually proving to be quite an exciting release.

If you ask me, Java 8 also brings many security improvements that are as important as the new language features. Of particular interest are the improvements to the TLS stack, implemented in the Java Secure Socket Extension (JSSE) component. Why? Because Java 7 and earlier do not give you enough control over TLS termination (details below). As a result, it was simply not possible to terminate TLS at the Java level and achieve sufficient security.

The deficiencies have been addressed in Java 8. Several other key improvements ensure that Java now provides a very good TLS stack. Many of the changes will take effect as you change the JRE, even with older applications. However, for some, we will have to wait (hopefully a short time) until programs take advantage of the new APIs.

Server Cipher Suite Preference

Java 8 allows TLS servers to decide which is the best suite to use from those supported by user agents. In earlier versions, the first supported suite is selected. The old behaviour is a serious problem because you can’t rely on user agents to do the right thing. For example, without server-side control, it’s not possible to deploy Forward Secrecy consistently, nor use some old suites (e.g., RC4 and 3DES) for backup purposes only. For me, the inability to control cipher suite order was always a showstopper, forcing me to terminate TLS elsewhere, for example at the Apache level.

To enable server cipher suite preference, use the SSLParameters.setUseCipherSuiteorder() method. Because of the API change, this feature will require application-level support. For Tomcat, you can track the progress here.

Strong Server Ephemeral Diffie-Hellman Parameters

Java 8 makes it possible to deploy TLS servers with strong ephemeral Diffie-Hellman parameters. In Java 7, DH parameters are hard-coded to 768 bits (excluding export suites, which use 512 bits, but such suites should not be used anyhow), and that's just plain insecure. To preserve security, when using TLS on Java 7 you must disable all DHE suites. As a result, you lose Forward Secrecy with some user agents that do not support ECDHE.

In Java 8, DHE parameters are set at 1024 bits by default, which is passable (considering each connection is independently protected), but not great. However, it’s possible to increase the strength to 2048 bits in configuration, by using the jdk.tls.ephemeralDHKeySize system property.

Authenticated (GCM) Suites

In the new version, JSSE supports authenticated (AEAD) GCM cipher suites, which is the best TLS can currently offer. This improvement is not as significant as the previous two, but ensures you can have best security in Java’s TLS stack. [JEP 115]

Hardware Acceleration on Intel and AMD processors

Starting with Java 8, the Java Runtime Environment (JRE) supports hardware acceleration of cryptographic operations when running on capable Intel and AMD processors. [JEP 164]

Server-Side SNI Support

Server support for the Server Name Extension (SNI), which allows for virtual SSL hosting, is finally available in Java 8. This feature allows hosting of multiple SSL sites on the same IP address (without having to share certificates). Virtual SSL hosting should become feasible soon, which means that this improvement comes at a very good time. (SNI support on the client side had been introduced in Java 7.) [JEP 114]

Ability to disable client-initiated renegotiation

Client-initiated renegotiation is a TLS protocol feature no one needs, yet it can sometimes be abused to make Denial of Service (DoS) easier. I prefer to disable this feature in order to reduce the attack surface. In Java 8, there is an undocumented system property jdk.tls.rejectClientInitiatedRenegotiation that controls client-initiated renegotiation.

TLS 1.2 enabled by default in client mode

Java added support for TLS 1.2 in version 7, but had it enabled by default only when in server mode; clients use TLS 1.0 as their best protocol by default. This is changing in Java 8, with TLS 1.2 now available without having to explicitly enable it.

Clients support Ephemeral DH over 1024 bits.

In Java 8, ephemeral DH parameters are no longer limited to 1024 bits when in client mode, as is the case in Java 7 and earlier versions. These days, 1024-bit DH parameters are considered weak and some operators prefer to increase DH strength to 2048 bits. The limit means that some Java clients are not able to negotiate any DHE suites with servers that use stronger parameters. (TLS has a design flaw in that it does not have a way for clients to advertise their DH capabilities.) This is not a big problem, given that you can use server-side preference to negotiate (the faster) ECDHE with Java clients, but it’s still nice to see the limit removed. Somewhat less positively, the new limit is 2048 bits.

Conclusion

With these changes, Java is again a viable platform for TLS termination. Not all necessary features are there, however. Notably absent is support for OCSP stapling, which can be used to give a performance boost to your TLS sites.

The other thing to be aware of is that the Java ecosystem has been slow to support SPDY, possibly because this protocol relies on TLS for bootstrapping and JSSE des not provide support for the Next Protocol Negotiation (NPN) extension. Two significant new protocols are currently being developed (HTTP/2.0 and TLS 1.3), and it will be interesting to see how quickly Java will adopt them.

For more information, visit the following links: