Recent Java upgrade causes TLS handshake failure with elliptic curve server certificate? - java

On October 19th, I upgraded to OpenJDK Java 1.8.0_232 and my Java processes started failing to connect to a service fronted by stunnel using an EC server certificate. I have an EC client certificate that I would present to the server if the initial handshake would succeed, but it's not getting that far.
I was unable to obtain the version number of the previous version of Java that was running -- I had a long-running process on the client that was able to connect to the service successfully. Java has been upgraded but that client hadn't been restarted since the upgrade. I restarted the client and it, too, began to fail.
I'm about to start reading the announcement to see if there is anything in there that would suggest a "fix" to something, but I believe I have everything configured correctly on both client and server. My current thinking is that this is a bug in the JVM.
Using ssltest, I have been able to confirm that I can handshake with the server using multiple cipher suites when providing the correct client certificate, as long as I use Java 1.8.0_181 or Java 11.0.3 (these are the two versions I happened to have laying around on my laptop for testing). Using the same files, command-line, etc. fails when using Java 1.8.0_232.
Has anyone seen anything like this?
UPDATE
I have downloaded x86-64 OpenJDK versions 8u222 and 8u232 from here and I can confirm that version 8u222 will connect and 8u232 will not connect.
UPDATE
Downgrading to the previous version of OpenJDK has solved my problem for the time being. I'm using Debian Stretch, and I was able to downgrade with this command:
$ sudo apt-get install openjdk-8-jdk-headless=8u222-b10-1~deb9u1 openjdk-8-jre-headless=8u222-b10-1~deb9u1
Note that I only have the "headless" packages installed, so I only downgraded the "headless" packages.
UPDATE
I can confirm that the client certificate is a red herring, here. I relaxed the requirements on my server to not require the client certificate and the initial TLS handshake still fails. I'm trying to narrow this down to the simplest test case I can get.
UPDATE
Still trying to diagnose the problem, here. I have a test server where I can launch it under various configurations and see what happens. I have determined that while Java 8u222 supports the secp256k1 curve, Java 8u232 does not, and I get the handshake failure.

The secp256k1 curve has been disabled with jdk 8u232 (see https://java.com/en/download/faq/release_changes.xml). It can be re-enabled with the java system property jdk.tls.namedGroups.
The example on the faq lists a few other Obsolete NIST EC Curves that are disabled as well. The curves listed there are sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1 and secp256k1. The system property jdk.tls.namedGroups takes a comma separated list of those names.

Related

Java 11 + Chrome/Firefox = TLS decrypt error

I'm currently migrating some server software from Java 8 to Java 11. Everything works fine except for the fact that TLS connections are refused when my server runs on Java 11 (and only 11). I.e., everything works when running on up to and including Java 10. As soon as I switch to Java 11 (with absolutely no code changes inbetween, of course) I get a TLS decrypt error. My application works fine otherwise when I disable SSL/TLS or when I use IE/Edge to connect to my server (via TLS). When using Chrome 70 or Firefox 62 I get ERR_SSL_PROTOCOL_ERROR or SEC_ERROR_BAD_SIGNATURE, respectively.
I tried to analyze this using WireShark (see my dump). My conclusion is that Java 11 and Chrome/Firefox negotiate a bad cipher suite (rsa_pss_rsae_sha256), which somehow doesn't work with Java 11. Java 8 and IE/Edge seem to negotiate a different cipher suite (rsa_pkcs1_sha256), which works.
Does someone know how to fix this problem or at least work around it for the moment (other than disabling SSL/TLS or using IE/Edge, of course)? Thanks in advance.
This is likely to be a compatibility failure with the new PSS algorithms in TLS 1.3. You can read a good explanation for the reasoning behind the introduction of PSS here.
Until it's fixed you can prevent your server from negotiating TLS 1.3 by editing lib/security/java.security and adding TLSv1.3 to the jdk.tls.disabledAlgorithms property.

ClientKeyExchange does not happen after ServerHelloDone

I have two laptops running the same project on them. Both instances are configured to use Java JDK 6 (same minor version). However one machine is not able to connect to a remote REST service. By running applications with -Djavax.net.debug=all option I came to the conclusion that the issue is with the ClientKeyExchange step as this step does not happen on the problematic laptop.
A post in the IBM developer community suggests that "hardware crypto device being used is not on the supported list". However I have no understanding about "hardware crypto devices".
What I can tell is that "enabled cipher suites", "excluded cipher suites", "cipher suites have been set to" lists printed by means of -Djavax.net.debug=all are the same on both machines.
Using JDK cacerts.
Found the solution. Project is using JAX-RS so calls to external service happened through that framework and because of that I could not dig to the problem since there were no errors. So I tried different approach: tried to access the service by using simple javax.net.ssl.HttpsURLConnection which showed me java.lang.NoClassDefFoundError: Could not initialize class javax.crypto.SunJCE_b and therefore I changed my local_policy.jar and US_export_policy.jar files (thanks to #Charlie Could not initialize class javax.crypto.SunJCE_b)
I think I had changed policy jars on first laptop and forgot to do this on the new laptop.

JDK 1.6 and SSL connection

My java version is 1.6 and connect to a server over ssl using axis 2 stub; all used to work fine. It seems like they did some upgrade (apache2.4) and the ssl handshake doesn't happen anymore. I receive javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake error. Just for testing purpose, I locally installed jdk 8 and tested it works fine. Is there any way to make this work using jdk1.6? It is not possible to upgrade jdk now.
It is hard to tell without more details but I guess that the server either requires a TLS version unsupported by JDK 6 (e.g. TLS 1.1 or TLS 1.2) or uses ciphers which are not supported by JDK 6 yet. Another option might be that the server needs SNI (server name indication) which is not supported by JDK 6. If the problem is any of these things you are unfortunately out of luck with JDK 6.
I suggest you check with SSLLabs to get more details about the problem. They show also compatibility information regarding various JDK versions.
You could try using a 3rd party JCE provider, Bouncy Castle comes into mind:
https://www.bouncycastle.org

TLSv1 handshake failure

(Disclaimer: I am by no stretch of the imagination a security expert nor a windows expert for that matter)
Setup:
server on our end: java 1.6 (already added bouncycastle to the security file) on windows 2003 server
third party client: windows 2008 server with biztalk
all renegotiation system properties introduced due to the renegotiation attack are "enabled" on the server side (not safe I know)
Ideally we want to fix this at our end but it is possible to propose a fix to the client if necessary.
The client server has to connect to our server over a HTTPS connection but it always fails, wireshark shows the following conversation:
> TLSv1: Client Hello
< TLSv1: Alert (21): Unexpected Message
As per the RFC (http://www.ietf.org/rfc/rfc2246.txt) the alert(21) refers to a failed decryption and from what I can see in wireshark, none of the ciphers proposed by the client are actually supported by JRE 1.6 (as per http://docs.oracle.com/javase/6/docs/technotes/guides/security/SunProviders.html#SupportedCipherSuites)
In an effort to reproduce the error to be able to examine it closer, I tested with some other software:
wfetch on windows xp with "https" selected will perform the initial client handshake in SSLv2, the server will switch to TLSv1 to answer, this works
wfetch on windows xp with configured to use "TLSv1" for the initial handshake will fail in the same way as the biztalk server
wfetch on windows 2008 with configured "https" will use "TLSv1" for the initial handshake and fail in the same way as the biztalk server
IE (on windows xp) will initially try a TLSv1 handshake with the same failed result but immediately tries again using SSLv3 which works
(at this point I figure all microsoft software uses a central configuration available at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel)
firefox uses SSLv3 for the entire conversation, so no problem there
OpenSSL performs an initial handshake in SSLv2, and the server switches to TLSv1 when it answers, no problem there
OpenSSL can be forced to do the initial handshake in TLSv1 as well, it offers a list of 27 ciphers (as opposed to the 11 ciphers proposed by windows-based software) and can connect without a problem
To my untrained eye this reinforces the idea that an incompatible cipher proposition is the root cause where windows only supports cipher suites that are not supported by JVM (for TLSv1).
I have installed bouncy castle as an additional provider in the java.security file to no avail.
I have searched high and low and only found a reference that maybe websphere supports the windows ciphers for TLSv1 but no way of downloading a standalone provider to test it.
JRE 1.7 is not supported by the software we run on our JVM, so upgrading is not an option (perhaps the security provider can be downgraded safely? I haven't found a download for it yet though)
I have found no way to add a cipher to windows short of writing c++ code (I've played around with the above mentioned registry settings without effect).
So in conclusion I wonder if one of the following things would fix it and how they should be accomplished:
add a provider to the jvm that can work with the ciphers for TLSv1 that are proposed by windows
somehow force the client to do the initial handshake in SSLv3 (preferably not SSLv2) or at least retry if the TLSv1 handshake fails
somehow add a JVM-supported cipher for TLSv1 to the client windows
Any other solutions are of course also appreciated.
EDIT
The Java version is Java version (64 bit): 1.6.0_19-b04.
The list of proposed ciphers is:
TLS_RSA_WITH_RC4_128_MD5
TLS_RSA_WITH_RC4_128_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_DES_CBC_SHA
TLS_RSA_EXPORT1024_WITH_RC4_56_SHA
TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA
TLS_RSA_EXPORT_WITH_RC4_40_MD5
TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
TLS_DHE_DSS_WITH_DES_CBC_SHA
TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA
The unlimited strength cryptography policy files are installed. I have tried to set javax.net.debug=all and started the server from the console, no additional output appeared. I have set sun.security.ssl.allowUnsafeRenegotiation=true to no avail.
EDIT 2
It turns out the software we are using uses a custom stack for HTTPs instead of the default. A fix was issued which seems to solve the problem though I don't know exactly which part of the TLS request triggered the error (seeing as most TLSv1 handshakes did succeed).
Thanks for the feedback, it has been an interesting if futile search. Live and learn.
It turns out the software we are using uses a custom stack for HTTPs instead of the default. A fix was issued which seems to solve the problem though I don't know exactly which part of the TLS request triggered the error (seeing as most TLSv1 handshakes did succeed).
Thanks for the feedback, it has been an interesting if futile search. Live and learn.
You could read my article on detecting cipher strength (just to make sure you installed the jce ciphers correctly) . In your question you say you installed unlimited ciphers but then you reference 128 and 40-bit keys. So, I am confused by what you have. Also, could you check the cipher strength on the SSL cert you are trying to connect to and let us know what it is and what the algorithm is? Also, make sure your policy file for JDK has the proper rights to allow unlimited strength.
Finally, can you connect to a "known good" SSL site to verify your client handshakes correctly? (Gmail web for example)

SOAP request in Java works locally but not on server

I have a webapp that sends a SOAP request to a 3rd party server. When the request is made on my local computer it works without a problem, but when I deploy my application to my server I get an error with the following causes:
com.sun.xml.messaging.saaj.SOAPExceptionImpl: java.security.PrivilegedActionException: com.sun.xml.messaging.saaj.SOAPExceptionImpl: Message send failed
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: algorithm check failed: MD2withRSA is disabled
I've searched around but I can't find anything relevant to my situation. It's probably worth noting that the request I'm making is to an https url. My computer is running Windows XP and the server is running Slackware Linux. Any ideas what might be causing the server to reject the request?
Check your Java versions on your local machine, and your server.
From here, it seems the jvm 6u17 disabled MD2 as it is insecure, and whatever you connect to is using MD2
MD2withRSA is highly vulnerable and therefore deactivated in Sun... aeh Oracle's JVM. You should ask the owner of the remote service, whether his server supports more secure encryption methods (I think, older Apache HTTPd versions do offer MD2withRSA by default...). In order to resolve this problem without forcing the provider to change the method, you may use your own implementation of the X509TrustManager that accepts the old method.
A Google search on "MD2withRSA" showed this URL as the first hit, that seems to point to a change in a certain Java version. Probably the verasiuons on your local computer and the server do not match.
Newer Java 7 (version 1.7) allows re-enabling MD2 via $JAVA_HOME/jre/lib/security/java.security file. Download and install Java 7 and modify java.security file in text editor as follows
1) Remove MD2 from following property
jdk.certpath.disabledAlgorithms= # MD2
2) Ensure following property is commented out
# jdk.tls.disabledAlgorithms=MD5, SHA1, DSA, RSA keySize < 2048
3) Restart java application
Warning: MD2 is disabled by default in Jdk 7 because it is insecure. However, it can be enabled as described above to support older deployments.

Categories

Resources