New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Jetty on JDK11 SSL Handshake failure with PKIX KMF algorithm and valid SAN DNS Name used as FQDN #7691
Comments
On startup of the Jetty server, enable the "Dump After Start" boolean to true and report back the server dump. Your server configuration is important to know now. Do you require the other PKIX configurations to work? The most common reason for "no cipher suites in common" is that you either have a misconfiguration of the protocols/cipher suites on the server side, or some overlooked server certificate detail is being trapped by a JVM security policy that prevents the certificate from matching an available cipher suite. (eg: RSA at 2048 bits was at the low end of the JVM security policy back when JDK 11 was released, it wouldn't surprise me if your JDK 11.0.14 is now preventing your certificates from being used properly) Keep an eye on the Java Crypto Roadmap Finally, be aware of the bugs in the JVM and BouncyCastle when it comes to combination of PKIX and SNI ... You might need to implement a custom |
Hi @joakime , Thanks for the details, I will share some updates soon based on the pointers that you provided. |
Hello @joakime , Find some updates as below based on my verification with different Jetty versions:
|
Tried the custom X509ExtendedKeyManager as indicated in above test. Its working fine with that workaround. However, still trying to understand the differences between 9.4.40 and 9.4.41 indicated in the previous comment. Thanks. |
In the "failed" log you have ...
In the success log you have ...
They appear to be similar. In both, you only have 2 cipher suites enabled.
Which basically means your configuration only support key exchanges with ECDH256. With a default Jetty install, on OpenJDK 11.0.12 you have ...
Which has all of the following Cipher Suites enabled ...
Did you mean to configured your |
Also, both failed and success show ...
Your configuration seems to not be using a keystore/truststore.
This kind of setup is possible, but it would require you to use Bouncycastle to create a |
The relevant change is the SNI alias matching fix as part of #6099 - in 9.4.40 it would often select the wrong alias, either it would be first one, or it would pick a default one (if the hostnames are reported to Jetty as mangled, see JVM bug linked in that issue, along with explanation by @sbordet ) |
Also, your bouncycastle jars are incorrect for your JVM.
See https://www.bouncycastle.org/latest_releases.html Since you are using "OpenJDK Runtime Environment Zulu11.54+24-SA (build 11.0.14+9-LTS)", that |
Thanks @joakime for detailed analysis. Please find below the responses:
Yeah, ciphhers are applied as below from a configurable list. So, this is not an issue.
I have the JRE embedded in my product and
Using FIPS variant of BC jars, so should be good
I went through the related JDK ticket, it reads the alias is manipulated from what's in the keystore (for example, "jetty") to an internal format such as "N.0.jetty" . So, I understand the workaround. Also the affected version seems to be Java 14.x, but may or may not be applicable to 11.x, so leave that. What I'm still not able to understand is, with same Java + BouncyCastle version, and same SSL certificate with single alias having only RSA key, why would jetty 9.4.41+ should fail? As per the explanation, it should have been failing since 9.4.31 or so..which is not the case, even without overriding X509ExtendedKeyManager. Doesn't it mean some working behavior was broken while fixing the usecase of multi-key certificates in 9.4.41? |
The affected version is how the baseline normal JDK behaves.
The algorithm to select a certificate was wrong prior to 9.4.41. |
Still need to call That technique of setting the first/default provider and hoping/praying it works everywhere in all situations is not considered best practice, and only applies to a limited number of scenarios, of the 5 JVM APIs we mentioned in an earlier comment on this issue, only 2 will work the way you expect with that technique (the KeyManagerFactory and TrustManagerFactory). As far as BC and FIPS is concerned, you have 2 providers. As
or in code ... Security.addProvider(new BouncyCastleFipsProvider());
Security.addProvider(new BouncyCastleJsseProvider(“fips:BCFIPS”)); That's what's recommended by Bouncycastle documentation. In either approach above (java.security or code) you are still expected to configure Jetty's SslContextFactory.Server serverSslFactory = new SslContextFactory.Server();
// This requirement will skip internal behaviors in SslContextFactory.Server attempting to create an SSLContext using JVM defaults.
// This will properly setup Jetty, the SSLContext, and SSLEngine it uses for BouncyCastle.
// It will also skip all of the internal behaviors based on JVM default assumption.
// (a requirement if you use anything but the JVM default providers, eg: Bouncycastle, or the IBM JDK)
// Past Jetty users of Bouncycastle report that this is not optional and required for success.
// Without this change, the SslContextFactory.Server will stomp on your Security.setProperty() settings in ways
// that counteract your desired end goal.
SSLContext fipsContext = SSLContext.getInstance("TLS", "BCJSSE");
serverSslFactory.setSslContext(fipsContext);
// more SslContextFactory.Server configuration here ...
// This will allow certificate handling and random number generation to use Bouncycastle specific behaviors, not JVM default behaviors.
// This is optional, but past Jetty users of Bouncycastle report this as necessary for their behaviors.
// What was seen in the past was a mix of usage between the certificate handling and the protocols and the cipher suites.
// Some behaviors were non-BC provider, some were BC, some were BCJSSE.
// Aligning the providers for each produced better and more consistent behavior.
// But again, this is technically optional.
serverSslFactory.setProvider("BCJSSE");
// the rest of the init of your ServerConnector / SslConnectionFactory
ServerConnector sslConnector = new ServerConnector(server,
new SslConnectionFactory(serverSslFactory, HttpVersion.HTTP_1_1.asString()),
new HttpConnectionFactory(httpsConfig)); |
Thanks @joakime , its more clear now. Closing the ticket as all the queries have been answered. |
Jetty version(s)
9.4.45.v20220203
Java version/vendor
(use: java -version)
OS type/version
Set up
I have a Jetty server running on JRE 11 with BouncyCastle JCE provider and Sun JSSE provider.
The ssl.KeyManagerFactory.algorithm is set to PKIX.
The configured SSL certificate has below configuration
RSA 2048 bit key size,
SHA-256 with RSA signature algorithm
Multiple DNS Names under SAN attributes and appropriate KeyUsage, ExtendedKeyUsage and other extensions.
Description
When I use a valid DNS Name entry as the FQDN for accessing the jetty server, SSL handshake fails with errors that does not make sense. Below is the snippet of the java ssl handshake log showing the error.
Known Workarounds
Making any of the below changes will make it work (with caveat):
ssl.KeyManagerFactory.alorithm=SunX509
(This is not what we need, especially if configured with FIPS mode)Log
Attached excerpt from Java SSL debug log for reference
qtp373342545-25-scrub.log
How to reproduce?
The text was updated successfully, but these errors were encountered: