We've been having trouble starting a Java application due to handshake failures. Upon inspection, we've discovered that the application can't connect to the server because the server expects a specific cipher suite (TLS_RSA_WITH_AES_256_CBC_SHA256), but the client doesn't have it in its hello message.
I would like to know if there's a way to enable the cipher suite for the client to use it in its hello. I'm not much of an expert in SSL/TLS, what would I need to understand to tackle this?
java -version:
openjdk version "11.0.22" 2024-01-16 LTS
OpenJDK Runtime Environment (Red_Hat-11.0.22.0.7-1) (build 11.0.22+7-LTS)
OpenJDK 64-Bit Server VM (Red_Hat-11.0.22.0.7-1) (build 11.0.22+7-LTS, mixed mode, sharing)
java.security jdk.tls.disabledAlgorithms entry:
jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
include jdk.disabled.namedCurves
java.security jdk.disabled.namedCurves entry:
jdk.disabled.namedCurves = secp112r1, secp112r2, secp128r1, secp128r2, \
secp160k1, secp160r1, secp160r2, secp192k1, secp192r1, secp224k1, \
secp224r1, secp256k1, sect113r1, sect113r2, sect131r1, sect131r2, \
sect163k1, sect163r1, sect163r2, sect193r1, sect193r2, sect233k1, \
sect233r1, sect239k1, sect283k1, sect283r1, sect409k1, sect409r1, \
sect571k1, sect571r1, X9.62 c2tnb191v1, X9.62 c2tnb191v2, \
X9.62 c2tnb191v3, X9.62 c2tnb239v1, X9.62 c2tnb239v2, X9.62 c2tnb239v3, \
X9.62 c2tnb359v1, X9.62 c2tnb431r1, X9.62 prime192v2, X9.62 prime192v3, \
X9.62 prime239v1, X9.62 prime239v2, X9.62 prime239v3, brainpoolP256r1, \
brainpoolP320r1, brainpoolP384r1, brainpoolP512r1
java.security crypto.policy entry:
crypto.policy=unlimited
I've made a standalone Java class that prints all the supported ciphers and protocols (client-side):
try {
SSLContext sslContext = SSLContext.getDefault();
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
System.out.println("Supported Ciphers:");
for (String cipher: sslSocketFactory.getSupportedCipherSuites()) {
System.out.println(cipher);
}
System.out.println("\nSupported Protocols:");
for (String protocol: sslContext.getSupportedSSLParameters().getProtocols()) {
System.out.println(protocol);
}
} catch (Exception e) {
e.printStackTrace();
}
This is the output:
Supported cipher suites:
TLS_AES_256_GCM_SHA384
TLS_AES_128_GCM_SHA256
TLS_CHACHA20_POLY1305_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_DHE_RSA_WITH_AES_256_CBC_SHA
TLS_DHE_RSA_WITH_AES_128_CBC_SHA
TLS_EMPTY_RENEGOTIATION_INFO_SCSV
TLS_RSA_WITH_NULL_SHA256
TLS_ECDHE_ECDSA_WITH_NULL_SHA
TLS_ECDHE_RSA_WITH_NULL_SHA
SSL_RSA_WITH_NULL_SHA
Supported protocols:
TLSv1.3
TLSv1.2
TLSv1.1
TLSv1
SSLv3
SSLv2Hello
As you can see, there's no mention of "TLS_RSA_WITH_AES_256_CBC_SHA256". How could I enable that specific cipher suite? A few days ago, I don't know how, but the cipher suite appeared on the list, I really don't know what we did, so, I know its possible. Now it doesn't appear because we changed the Java installation (but anyways, both were Java 11).
So, I solved the issue, and yes, it had to do with the Java Distribution I was using.
I was using Red Hat Inc.'s Java Distribution, installed via Red Hat's repositories with yum, but, apparently, RH's Java doesn't support the cipher suite I was looking for. @g00se's comment kinda helped me there when they mentioned 'licensing'. So, based on the comments I got on my question, I went and downloaded an .rpm for Java, but this time Oracle's.
With that, I installed it on my RHEL server:
rpm -ivh jdk-11.0.21_linux-x64_bin.rpm
And then ran my class to check if any new cipher suites were added, and sure enough, there it was, 'TLS_RSA_WITH_AES_256_CBC_SHA256'.
From there, I just specified in my service file (the one that runs the application that was having the handshake failure) to use the Oracle's Java, like this:
ExecStart=/usr/lib/jvm/jdk-11-oracle-x64/bin/java ...other options... -jar "application.war"
And everything worked fine, no more errors!
Thanks for all your comments, they really helped me out :)