Bug 64614 - tomcat doesn't work with JSSE FIPS-compliant with NSS
Summary: tomcat doesn't work with JSSE FIPS-compliant with NSS
Alias: None
Product: Tomcat 9
Classification: Unclassified
Component: Connectors (show other bugs)
Version: 9.0.x
Hardware: PC Linux
: P2 normal (vote)
Target Milestone: -----
Assignee: Tomcat Developers Mailing List
Depends on:
Reported: 2020-07-20 08:03 UTC by jfclere
Modified: 2020-09-08 10:28 UTC (History)
1 user (show)

Possible patch for the issue. (1.31 KB, patch)
2020-07-20 08:12 UTC, jfclere
Details | Diff
improved? patch. (1.42 KB, patch)
2020-07-21 12:54 UTC, jfclere
Details | Diff
patch for the issue. (824 bytes, patch)
2020-07-21 15:05 UTC, jfclere
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description jfclere 2020-07-20 08:03:49 UTC
When configured with FIPS with NSS The connector gives the following exception:
20-Jul-2020 09:11:03.863 SEVERE [main] org.apache.catalina.util.LifecycleBase.handleSubClassException Failed to initialize component [Connector[HTTP/1.1-8443]]
        org.apache.catalina.LifecycleException: Protocol handler initialization failed
                at org.apache.catalina.connector.Connector.initInternal(Connector.java:1042)
                at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
                at org.apache.catalina.core.StandardService.initInternal(StandardService.java:533)
                at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
                at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:1057)
                at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:136)
                at org.apache.catalina.startup.Catalina.load(Catalina.java:690)
                at org.apache.catalina.startup.Catalina.load(Catalina.java:712)
                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                at java.lang.reflect.Method.invoke(Method.java:498)
                at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:302)
                at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:472)
        Caused by: java.lang.IllegalArgumentException: FIPS mode: only SunJSSE KeyManagers may be used
                at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:99)
                at org.apache.tomcat.util.net.AbstractJsseEndpoint.initialiseSsl(AbstractJsseEndpoint.java:71)
                at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:216)
                at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1141)
                at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:1154)
                at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:581)
                at org.apache.coyote.http11.AbstractHttp11Protocol.init(AbstractHttp11Protocol.java:74)
                at org.apache.catalina.connector.Connector.initInternal(Connector.java:1039)
                ... 13 more
        Caused by: java.security.KeyManagementException: FIPS mode: only SunJSSE KeyManagers may be used
                at sun.security.ssl.SSLContextImpl.chooseKeyManager(SSLContextImpl.java:154)
                at sun.security.ssl.SSLContextImpl.engineInit(SSLContextImpl.java:71)
                at javax.net.ssl.SSLContext.init(SSLContext.java:282)
                at org.apache.tomcat.util.net.jsse.JSSESSLContext.init(JSSESSLContext.java:61)
                at org.apache.tomcat.util.net.SSLUtilBase.createSSLContext(SSLUtilBase.java:246)
                at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:97)
                ... 20 more
Comment 1 jfclere 2020-07-20 08:10:52 UTC
To configure I did the following:

modutil -create -dbdir /home/jfclere/db
touch /home/jfclere/db/secmod.db (for what?).
modutil -fips true -dbdir /home/jfclere/db
modutil -list -dbdir /home/jfclere/db (looks OK)
modutil -changepw "NSS FIPS 140-2 Certificate DB" -dbdir /home/jfclere/db (-list to get the tokens)
modutil -changepw "NSS Certificate DB" -dbdir /home/jfclere/db (when no fips!).
certutil -S -k rsa -n jbossweb  -t "u,u,u" -x -s "CN=localhost, OU=MYOU, O=MYORG, L=MYCITY, ST=MYSTATE, C=MY" -d /home/jfclere/db

Add the providers in jre/lib/security/java.security

security.provider.4=com.sun.net.ssl.internal.ssl.Provider SunPKCS11-NSSfips

security.provider.10=sun.security.pkcs11.SunPKCS11 /usr/lib/jvm/java-1.8.0-openjdk-

I have in jre/lib/security/nss.cfg:
name = NSSfips
nssLibraryDirectory = /usr/lib64
nssSecmodDirectory = /home/jfclere/db
nssDbMode = readWrite
nssModule = fips
attributes = compatibility
handleStartupErrors = ignoreMultipleInitialisation
I have in server.xml
    <Connector port="8443" protocol="HTTP/1.1"
               maxThreads="150" SSLEnabled="true" >
        <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
            <Certificate certificateKeystorePassword="Adelina2020!"
                         certificateKeystoreProvider="SunPKCS11-NSSfips" />
Comment 2 jfclere 2020-07-20 08:12:10 UTC
Created attachment 37364 [details]
Possible patch for the issue.

Patch that fixes the issue.
Comment 3 Mark Thomas 2020-07-20 12:39:00 UTC
Doesn't the patch defeat the point of using Tomcat's JSSEKeyManager thereby breaking the use cases that required it in the first place?
Comment 4 Remy Maucherat 2020-07-20 12:59:17 UTC
Yes, it would prevent using a key alias, which was the only reason for the wrapper. So I get FIPS mode prevents creative key manager uses then ?

Idea: maybe don't use a wrapper if there's no key alias set ?

This is still pretty bad overall since some configurations becomes broken :(
Comment 5 jfclere 2020-07-20 17:23:39 UTC
I need to investigate a little I will come with a better patch later this week.
Comment 6 jfclere 2020-07-21 09:32:46 UTC
    <Connector port="8443" protocol="HTTP/1.1"
               maxThreads="150" SSLEnabled="true"
               sslImplementationName="org.apache.tomcat.util.net.jsse.JSSEImplementation" >
        <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
            <Certificate certificateKeystorePassword="Adelina2020!"
                         certificateKeystoreProvider="SunPKCS11-NSSfips" />

Note the ciphers list is needed for FIPS.
Comment 7 jfclere 2020-07-21 12:54:15 UTC
Created attachment 37367 [details]
improved? patch.

Check for FIPS to prevent regressions...
Comment 8 Christopher Schultz 2020-07-21 13:02:09 UTC
Seems like an awful hack.

Perhaps instead we should have a configuration attribute like dontWrapKeyManager="true|false" and them simply do not wrap in the first place. Or is the wrapping required for other things?
Comment 9 Remy Maucherat 2020-07-21 14:23:53 UTC
(In reply to Christopher Schultz from comment #8)
> Seems like an awful hack.
> Perhaps instead we should have a configuration attribute like
> dontWrapKeyManager="true|false" and them simply do not wrap in the first
> place. Or is the wrapping required for other things?

If there's really a need to avoid wrapping when FIPS is used, then it should be done here:
(using a new abstract method to detect FIPS JSSE)
But there's probably no need for new explicit configuration, if it won't work.
And log something if wrapping was desired but cannot be done due to FIPS.

So context.getProvider().getInfo().indexOf("FIPS") != -1 is a 100% correct way to test for FIPS ?
Comment 10 jfclere 2020-07-21 14:37:13 UTC
kmf.getProvider().getInfo() also gives
"Sun JSSE provider (FIPS mode, crypto provider SunPKCS11-NSSfips"
so indexOf("FIPS") != -1 would also work there.
Comment 11 jfclere 2020-07-21 15:05:34 UTC
Created attachment 37368 [details]
patch for the issue.
Comment 12 Christopher Schultz 2020-07-22 14:30:52 UTC
Aren't we just "always wrapping" because it was simpler than only wrapping when necessary? Why don't we "only" wrap when we must? I think the wrapper is only for certain scenarios. Why not detect THOSE instead of trying to detect the cases where un-wrapping is necessary?
Comment 13 jfclere 2020-07-23 06:10:58 UTC
Something like no alias no wrapping and alias and FIPS warning and no wrapping?
Comment 14 jfclere 2020-08-06 17:03:25 UTC
https://github.com/apache/tomcat/pull/334 as the best I can get ;-)
Comment 15 Mark Thomas 2020-09-08 10:28:04 UTC
PR applied.