ALPN Support not disabled correctly when running with BCFIPS (BC JSSE FIPS Mode) 1.0.10 on JDK 11 (9+)
See original GitHub issueForgive me for any formal mistakes or if I missed something major, usually I am travelling a bit further upwards in the stack.
Expected behavior
Disable ALPN and HTTP/2 Support without throwing an error message that the AlpnSslUtils Class cannot be initialized. This is expected in this case, as the Security Provider does not support ALPN in FIPS Mode yet but can still be run in JDK 11 (e.g. in a Docker VM on AdoptOpenJDK with substituted java.security properties)
Actual behavior
After startup of a Netty Client with enforced OpenJDK Settings and letting it talk to either Non-ALPN or an ALPN Host (it should not matter), the error Unable to initialize JdkAlpnSslUtils, but the detected java version was: 11
is shown during Initialization of the TrustStoreManager. SSL Handshake can still happen and negotiation will be done as usual via non-ALPN Negotiation on HTTP 1.1.
Especially when using ApplicationProtocolConfig.DISABLED
this is not intended imo
Steps to reproduce
- Create a small Project with the FIPS libraries as dependencies (either as code - see right below or during init of the JVM, e.g. through java.security)
- Initialize the netty client without OpenSSL and try to negotiate with an SSL-protected Server
- Observe the Error once the the TrustManagerFactory is initialized and creates the TrustStore.
- Verify that the Handshake still completes with a FIPS compliant Cipher
compile group: 'org.bouncycastle', name: 'bc-fips', version: '1.0.2'
compile group: 'org.bouncycastle', name: 'bctls-fips', version: '1.0.10'
In case of available non-fips bc providers (e.g. through 3rd party deps)
implementation {
// FIPS validated libraries added to boot classpath in base image.
// NON-FIPS version of libraries must be excluded at compile time for compliancy
exclude group: 'org.bouncycastle', module: 'bcprov-jdk15on'
exclude group: 'org.bouncycastle', module: 'bcpkix-jdk15on'
}
Security.insertProviderAt(new BouncyCastleFipsProvider(),1); // basic encryption provider
Security.insertProviderAt(new BouncyCastleJsseProvider("fips:BCFIPS"),2); // tls
Security.removeProvider("SunRsaSign");
Security.removeProvider("SunJSSE");
Minimal yet complete reproducer code (or URL to code)
Setup the Context
SslContextBuilder.forClient()
.sslProvider(io.netty.handler.ssl.SslProvider.JDK)
.sslContextProvider(Security.getProvider(BouncyCastleJsseProvider.PROVIDER_NAME))
.keyManager(KeyManagerFactory.getInstance("PKIX", "BCJSSE"))
.trustManager(TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
.applicationProtocolConfig(ApplicationProtocolConfig.DISABLED)
.build()
Setup a small Client
public @NonNull HttpClient getSecuredHttpClient() {
return HttpClient.create().wiretap(true).secure(sslContextSpec ->
{
try {
sslContextSpec
.sslContext(buildSslContext());
} catch (SSLException e) {
log.error(e.getLocalizedMessage());
}
}
);
}
Use A Dockerfile based on a JVM Setup
FROM adoptopenjdk/openjdk:11
ARG BC_VERSION=1.0.2
ARG BC_TLS_VERSION=1.0.10
# Download the BC APIs from Maven or another Dist with a curl-alike
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\
-Djavax.net.ssl.trustStoreProvider=BCFIPS \
-Djavax.net.ssl.trustStoreType=BCFKS \
-Djavax.net.ssl.trustStorePassword=changeit \
-Dio.netty.handler.ssl.noOpenSsl=true \
-Djavax.net.debug=ssl,handshake \"
# You can use this to create a keystore and operate on it with keytool commands if available in the image
ENV KEYTOOL_OPTS "-storetype BCFKS \
-providerpath /PATHTOJARS/bc-fips-${BC_VERSION}.jar \
-providerclass org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider"
# You can use this to replace the standard keystore with a new FIPS compliant one
RUN keytool -importkeystore -noprompt \
-srckeystore cacerts -srcstorepass "changeit" \
-destkeystore cacerts.bcfks -deststorepass "changeit" \
-destprovidername BCFIPS -deststoretype BCFKS \
-providerpath /build/jars/bc-fips-${BC_VERSION}.jar \
-providerclass org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider
RUN ln -fs cacerts.bcfks cacerts
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
Netty version
4.1.49.Final
JVM version (e.g. java -version
)
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.9+11)
OS version (e.g. uname -a
)
RHEL7 Dockerfile-based
Issue Analytics
- State:
- Created 3 years ago
- Comments:18 (5 by maintainers)
Top GitHub Comments
Thanks @peterdettman. The root cause of this was because we were injecting to our Dockerfile the BC jars as
-Xbootclasspath
which is not supported by the JDK9 and above. After I change this injection, added the dependencies with Gradle and the code itself for setting up the providers order, it worked without the error message.Ok I will close this then… Thanks @peterdettman for the help!