question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

NettyNioAsyncHttpClient not respecting replacements of JSSE Providers (e.g. Bouncy Castle FIPS) by using own CipherSuites

See original GitHub issue

Hey everyone! I am currently setting up the AWS SDK to run with SQS and S3. However my service is running in a FIPS-compliant, standardised Docker environment. Unfortunately, this also means exchanging used Security Providers (OpenSSL is excluded from the classpath through Gradle) under the Hood of JVM and thus also the SDK.

The problem occurs when trying to spin up an SdkAsyncHttpClient with a corresponding NettyNioAsyncHttpClient as I am running in Spring Boot with Netty already for other operations and I want to keep things consistend and non-blocking.

Describe the bug

When trying to establish the connection via Netty in the SDK to AWS Services, Ciphers cannot be negotiated correctly and the SSL Handshake fails.

{"@timestamp": "2020-11-23T16:28:40.471+0000", "level": "INFO", "class": "org.bouncycastle.jsse.provider.ProvTlsServer", "description": "Server raised fatal(2) handshake_failure(40) alert: Failed to process record org.bouncycastle.tls.TlsFatalAlert: handshake_failure(40) 
at org.bouncycastle.tls.AbstractTlsServer.getSelectedCipherSuite(Unknown Source) 
at org.bouncycastle.jsse.provider.ProvTlsServer.getSelectedCipherSuite(Unknown Source) 
at org.bouncycastle.tls.TlsServerProtocol.generateServerHelloMessage(Unknown Source) 
at org.bouncycastle.tls.TlsServerProtocol.handleHandshakeMessage(Unknown Source)}

Expected Behavior

I was expecting a successful handshake with the AWS Server performed with using Cipher Suites common to both the Bouncy Castle FIPS Library responsible for TLS (JSSE) through Netty which under the Hood usually defaults to the correct SSL Settings if configured through the JVM.

Whenever trying to establish a connection, a cipher that is compatible should be negotiated and the TLS Handshake completed. I can replicate a successful handshake with a Netty Client spun up by myself in my service and negotiating with a different non-aws service (e.g. A MySQL through Hikari):

Client notified of selected protocol version: TLSv1.2 Client notified of selected cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384

I am using the same default SSL Context and Provider that I am expecting to be drawn in to the SDK from the JVM as well.

Current Behavior

in the case of the above failure, I was accessing us-west-2.queue.amazonaws.com

According to the SSL Analysis here: https://www.ssllabs.com/ssltest/analyze.html?d=us-west-2.queue.amazonaws.com

and my SSL Configuration below

Protocols SSLContext.getDefault().getDefaultSSLParameters().getProtocols() [TLSv1.2, TLSv1.1, TLSv1] CipherSuites SSLContext.getDefault().getDefaultSSLParameters().getCipherSuites() [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA]

From my limited knowledge (I am not exactly a security expert), there should be several ciphers listed that are supported for both my client and server for negotiation, indicating an issue in the SDK

What I am seeing however, is the following: [id: OMITTED] REGISTERED [id: OMITTED] CONNECT Client raised warning(1) user_canceled(90) alert: User canceled handshake Client raised warning(1) close_notify(0) alert: Connection closed [id: OMITTED, L:/OMITTED- R:sqs.us-west-2.amazonaws.com/OMITTED:443] USER_EVENT: SslHandshakeCompletionEvent(java.lang.IllegalStateException: No usable cipher suites enabled)

Steps to Reproduce

The JVM is setup like this in a Dockerfile

ENV JAVA_OPTS --show-version \ -XshowSettings:vm \ -XX:+DisableExplicitGC \ -Dfile.encoding=UTF-8 \ -Dorg.bouncycastle.fips.approved_only=true \ -Xbootclasspath/a:/PATHTOJARS/bc-fips-${BC_VERSION}.jar \ -Xbootclasspath/a:/PATHTOJARS/bctls-fips-${BC_TLS_VERSION}.jar"

I am using these Options to generate my Keystore

ENV KEYTOOL_OPTS "-storetype BCFKS \ -providerpath /PATHTOJARS/bc-fips-${BC_VERSION}.jar \ -providerclass org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider"

and some changes to the java.security file for setting up the JVM correctly.

RUN sed -i 's/\(security\.provider\.[0-9]\+\)=\(.*\)/##\1=\2/g' java.security
RUN sed -i 's/\(ssl\.KeyManagerFactory\.algorithm\)=.*/\1=PKIX/g' java.security
RUN sed -i 's/\(securerandom\.source\)=.*/\1=file:\/dev\/urandom/g' java.security
RUN sed -i 's/\(securerandom\.strongAlgorithms\)=.*/\1=NativePRNGNonBlocking:SUN,DRBG:SUN/g' java.security
RUN printf '\nsecurity.provider.1=BCFIPS\nsecurity.provider.2=BCJSSE fips:BCFIPS\nsecurity.provider.3=SUN\n' >> java.security

as well as

-Dio.netty.handler.ssl.noOpenSsl=true \ -Djavax.net.ssl.trustStoreProvider=BCFIPS \ -Djavax.net.ssl.trustStoreType=BCFKS \ -Djavax.net.ssl.trustStorePassword=changeit \ -Djavax.net.debug=ssl,handshake \

If you want to configure the providers by Code you can use this:

compile group: 'org.bouncycastle', name: 'bc-fips', version: '1.0.2'
compile group: 'org.bouncycastle', name: 'bctls-fips', version: '1.0.10'
private static void makeOurServiceFIPSCompliant() {
        Security.insertProviderAt(new BouncyCastleFipsProvider(),1); // basic encryption provider
        Security.insertProviderAt(new BouncyCastleJsseProvider(),2); // tls
        Security.removeProvider("SunRsaSign");
        Security.removeProvider("SunJSSE");
    }

for your Runtime you can probably replicate the issue just like I have. It is important to fully change out the backing security implementation and also access Netty with JDK and not OpenSSL. Due to security concerns, I will not be able to share the full Dockerfile with you but please mention if there is anything in particular you are interested in.

Possible Solution

Support native readout of Netty Security Context (SSLContext) and thus usability of an adapted JSSE through the JDK Provider instead of OpenSSL. Unfortunately I am lacking the insight on where this is currently problematic or wether I am missing a configuration of some sort.

Context

I am trying to achieve full FIPS compliance through AWS and am currently failing at achieving full compliancy due to the Handshake error.

Your Environment

  • AWS Java SDK version used: 2.15.34 implementation("software.amazon.awssdk:s3:${awsSdkVersion}") api("software.amazon.awssdk:sqs:${awsSdkVersion}")

  • JDK version used: openjdk 11.0.9 2020-10-20 OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.9+11) OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.9+11, mixed mode)

  • Operating System and version: Red Hat Enterprise Linux 7

  • Additional Info: ARG BC_VERSION=1.0.2 ARG BC_TLS_VERSION=1.0.10

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
cenedhryncommented, Nov 26, 2020

@jakobmoellersap We’ll add support for FIPS compliant algorithms to the Netty client and are tracking this issue internally.

0reactions
github-actions[bot]commented, Jan 19, 2021

It looks like this issue hasn’t been active in longer than a week. In the absence of more information, we will be closing this issue soon. If you find that this is still a problem, please add a comment to prevent automatic closure, or if the issue is already closed please feel free to reopen it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Legion of the Bouncy Castle Inc. Java (D)TLS API and JSSE ...
The BCJSSE provider has a FIPS mode which helps restricts the provider to cipher suites and parameters that can be offered in a...
Read more >
BouncyCastle JSSE and BCTLS No Credentials for Cipher
This error prevented all subsequent TLS connections with my application. I tried below two approaches for this. Setting -Dorg.bouncycastle.jsse.
Read more >
Blog - BouncyCastle Keystore Security - Cryptosense
Here we'll take a look at what's offered by BouncyCastle, a widely-used open-source alternative. Like the Oracle provider, keystores in BC ...
Read more >
[dev-crypto] List of Ciphers supported by Bouncy Castle FIPS ...
[next in thread] List: bouncycastle-crypto-dev Subject: RE: [dev-crypto] List ... We tried to run JSSE in FIPS mode by using the JSSE Provider...
Read more >
Bouncy Castle provider problems - Oracle Communities
I tried to roll back my changes to see what step broke everything but even when I remove the bouncy castle jar from...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found