Bug 56027 - Unable to use TCN on RHEL6 boxes if box is booted in fips mode
Unable to use TCN on RHEL6 boxes if box is booted in fips mode
Status: REOPENED
Product: Tomcat Native
Classification: Unclassified
Component: Library
1.1.30
All Linux
: P2 normal (vote)
: ---
Assigned To: Tomcat Developers Mailing List
:
Depends on:
Blocks:
  Show dependency tree
 
Reported: 2014-01-17 13:48 UTC by Rob Sanders
Modified: 2014-07-02 14:26 UTC (History)
1 user (show)



Attachments
Proposed patch against Tomcat-trunk (4.38 KB, patch)
2014-01-17 17:49 UTC, Christopher Schultz
Details | Diff
Patch against Tomcat trunk (8.44 KB, patch)
2014-03-19 14:36 UTC, Christopher Schultz
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Rob Sanders 2014-01-17 13:48:54 UTC
There are two problems here.

#1) A RHEL6 box can be configured to boot in FIPS 140 mode automatically, and the underlying openssl packages will detect this when they initialize.  If Tomcat is configured to use the APR listener with 'FIPSMode="on"' set, then the APRLifecycleListener in initializeSSL calls down to TCN to explicitly do a fipsModeSet.  However, *if* a RHEL box is configured to be in fips mode at boot then this call will fail in the openssl libraries, where it claims that fips mode is already set. Looking at the openssl source (openssl-1.0.0-27.el6.src.rpm) the FIPS_mode_set() call does not allow for being 'set' more than once.  Putting a check in TCN src/ssl.c in the fipsModeCheck() to see if the mode is already set solves this one.

#2) Second issue is in the SSL_TMP_KEYS_INIT macro (called from the TCN src/ssl.c initialize() method) looks like it trying to pre-initialize a 512 bit RSA key.  This key appears to be invalid (the underlying ssl_tmp_key_init_rsa() call fails), and this winds up with the entire initialize code throwoing an error about this platform having an unsupported function and exiting.  Deleting the 512 RSA init line solves this one.

Not sure the best solution for #2.  Discussing with a few folks here indicated that a 512 bit RSA key is invalid for FIPS mode, so perhaps this call needs to be wrapped in a 'if (FIPS_Mode()==0)' check.  Out of my depth there on the best solution.

My initial debug wound up exposing the FIPS_Mode() call thru JNI so the AprLifecycleListner class could check this and display an intelligent message, but this would involve changes to both TC6/7(/8?) as well as TCN, and may not be worth that extra involvement.
Comment 1 Rob Sanders 2014-01-17 13:50:15 UTC
Marked as major due to a customer requirement to have their RHEL6 boxes running in FIPS mode at boot.  They are temporarily relaxing this while we have worked on determining the problem.
Comment 2 Christopher Schultz 2014-01-17 16:29:01 UTC
I'm putting this back to "normal". While your customer may consider this high-priority, and while one of the Tomcat team may fix this quickly, "major" would probably be considered a bug that would require an immediate fix-and-release.
Comment 3 Christopher Schultz 2014-01-17 16:33:10 UTC
This bug will likely require (at least) two separate patches: one for avoiding double-entry into FIPS mode, one for changing the key sizes used, and possibly one for creating a native-wrapper around the FIPS_mode function call so Java can inspect the current status and take appropriate action.

I think the best situation would be to allow the user to specify more than simply "on" versus "off" for the FIPSmode configuration attribute: it would be nice to use something like "on" to enable FIPS mode by calling FIPS_mode_set if necessary, "require" to require that FIPS mode already be enabled (or throw an exception and refuse to start the connector), or maybe a third option like "enter" which would attempt to enter FIPS mode and fail if FIPS mode were already enabled (this is the current behavior).
Comment 4 Rob Sanders 2014-01-17 16:40:50 UTC
Looking at the openssl source for my box a double call to FIPS_mode_set to *enable* FIPS triggers an error - including setting the internal fips_selftest_fail flag to 1 indicating a failure.

Understood on the severity change - somewhat surprised that I can't find any real reports of this failure in general web searches or on RH's pages.

Some additional comments...
 
Looking for a boot entry does appear to be a RHEL 'addition', but the source also indicates you can set an environment variable to accomplish the same thing (OPENSSL_FORCE_FIPS_MODE). This is in the source code of crypto/o_init.c (after applying RH patches).  The /proc/sys/crypto/fips_enabled trigger file is checked in this file also.

Looking deeper at the AprLifecycleListener initializeSSL code it does call the TCN SSL.initialize code, which drops down into some of the openssl calls that look like bounce through the various init routines including the code in o_init.c that does the FIPS startup.  So *if* the underlying platform has the fs/env check a call to FIPS_Mode() prior to calling FIPS_mode_set() in  TCN fipsModeSet() should detect this.

Proposed fix - in TCN src/ssl.c fipsModeSet() routine, call FIPS_mode() before calling FIPS_mode_set() to see if we're already in fips mode.  If so, just return 1, otherwise attempt to set to FIPS mode.  There is no way that I know of to get an intelligent message back through the JNI without other changes, so if a status messages of "Already in FIPS mode" would be desirable the FIPS_mode() routine will need to be exposed through JNI and checked from the AprLifecycleListener code before calling fipsModeSet.
Comment 5 Christopher Schultz 2014-01-17 16:44:16 UTC
(In reply to Rob Sanders from comment #4)
> Proposed fix - in TCN src/ssl.c fipsModeSet() routine, call FIPS_mode()
> before calling FIPS_mode_set() to see if we're already in fips mode.  If so,
> just return 1, otherwise attempt to set to FIPS mode.

See my comment above for the behavior I'd like to see, which is incompatible with this proposal.

> There is no way that
> I know of to get an intelligent message back through the JNI without other
> changes, so if a status messages of "Already in FIPS mode" would be
> desirable the FIPS_mode() routine will need to be exposed through JNI and
> checked from the AprLifecycleListener code before calling fipsModeSet.

This was my plan.
Comment 6 Christopher Schultz 2014-01-17 16:54:28 UTC
Added fipsModeGet JNI implementation in both tcnative trunk and tcnative 1.1.x branch. Will be in tcnative 1.1.30.
Comment 7 Rob Sanders 2014-01-17 16:58:15 UTC
Concur on comment 3 - had dueling edits going on.
For our customer at the moment I'm implementing the TCN only fix.  Once the next TC6 and TCN releases are out we'll move to them.

Thanks Chris.
Comment 8 Christopher Schultz 2014-01-17 17:49:03 UTC
Created attachment 31226 [details]
Proposed patch against Tomcat-trunk

Feel free to adapt this patch for Tomcat 6.
Comment 9 Ben Mason 2014-03-10 22:33:46 UTC
(In reply to Christopher Schultz from comment #8)
> Created attachment 31226 [details]
> Proposed patch against Tomcat-trunk
> 
> Feel free to adapt this patch for Tomcat 6.

Chris-

I am having the same issue as I need to boot my SLES 11 box in FIPS mode. I am using Tomcat 7.0.52. Can you tell in which, if any, Tomcat 7 release this patch will be included?

Thanks.
-Ben
Comment 10 Christopher Schultz 2014-03-19 14:25:13 UTC
We need a tcnative release before Tomcat itself can be patched.

If you grab the current tcnative 1.1.x branch, it will have what you need. If you then apply this patch to 7.0.52 (which is quite easy to re-compile yourself, actually) and deploy the two, you should be good to go.

I'm about to update the Java patch a bit to fix a minor bug and to address some of the concerns raised by some other devs. You might want to apply the new patch instead.
Comment 11 Christopher Schultz 2014-03-19 14:36:06 UTC
Created attachment 31406 [details]
Patch against Tomcat trunk

Updated patch with improved documentation and a small bug fix for ensuring that FIPS mode was successfully entered.
Comment 12 Ben Mason 2014-03-19 20:39:39 UTC
(In reply to Christopher Schultz from comment #10)
> We need a tcnative release before Tomcat itself can be patched.
> 
> If you grab the current tcnative 1.1.x branch, it will have what you need.
> If you then apply this patch to 7.0.52 (which is quite easy to re-compile
> yourself, actually) and deploy the two, you should be good to go.
> 
> I'm about to update the Java patch a bit to fix a minor bug and to address
> some of the concerns raised by some other devs. You might want to apply the
> new patch instead.

Thanks, Chris. I can surely do that. However, that will not fix problem #2, correct? I am seeing that on SLES 11 as well. Do you need someone to contribute a fix for #2, or is someone working on that?
Comment 13 Christopher Schultz 2014-03-20 19:09:31 UTC
(In reply to Ben Mason from comment #12)
> ...that will not fix problem #2,
> correct? I am seeing that on SLES 11 as well. Do you need someone to
> contribute a fix for #2, or is someone working on that?

I'm out of my element, there. If you've got a proposal and are willing to work on a patch, please do so. The assertion that 512-bit RSA is not valid for FIPS mode certainly seems reasonable. AFAIK, there's nothing in FIPS that established an *upper* limit on key size, or that the implementation must actually use clearly inferior algorithms.
Comment 14 Rob Sanders 2014-03-20 20:11:58 UTC
I remember reading some of the SSL docs that certain key lengths may be invalid for regular use, they are valid for key agreement/establishment.  Quoting from the somewhat confusing section 2.6.2 of the OpenSSL FIPS140 Userguide (v2.0) PDF:

===
Algorithms Available in FIPS Mode
Only the algorithms listed in tables 4a and 4b of the Security Policy are allowed in FIPS mode.
Note that Diffie-Hellman and RSA are allowed in FIPS mode for key agreement and key establishment even though they are “Non-Approved” for that purpose. RSA for sign and verify is “Approved” and hence also allowed, along with all the other Approved algorithms listed in that table
===

Rather than hardcode in TCN what approved keys are, is there a way to ask the underlying openssl implementation what *it* thinks are acceptable?  I don't have an answer for that.  What I did to make things work back in January was comment out the 512 bit RSA key generation in TCN before building (along with adding a check to see if FIPS mode was already set).
Comment 15 Rob Sanders 2014-04-11 18:57:54 UTC
As per request I've filed a new bug for the failure to init the RSA 512 bit temporary key (https://issues.apache.org/bugzilla/show_bug.cgi?id=56396).
Comment 16 Christopher Schultz 2014-04-15 21:54:27 UTC
Fixed in Tomcat trunk in r1587378, r1587379, and r1587723. Will be included in Tomcat 8.0.6 and later.
Fixed in Tomcat 7.0 branch in r1587378, r1587661, and r1587734. Will be included in Tomcat 7.0.54 and later.
Proposed for Tomcat 6.
Comment 17 Konstantin Kolinko 2014-04-27 04:18:15 UTC
Follow-ups in Tomcat 8 in r1590300 r1590339 (8.0.6), r1590340 (7.0.54).
Updated patch was proposed for Tomcat 6.
Comment 18 Konstantin Kolinko 2014-05-10 13:14:17 UTC
Fixed in Tomcat 6 by r1593696 and will be in 6.0.40.
Comment 19 Simon Mijolovic 2014-06-25 16:56:29 UTC
Still running into this issue where the APR library won't load when in fips mode using the FIPS validated OpenSSL library.

CentOS 6.5 with OpenSSL 1.0.1e-16..el6_5.x86_64, and /boot/grub/grub.conf has fips=1 (prelink disabled, dracut -f, reboot shows "cat /proc/sys/crypto/fips_enabled" = 1)

Tomcat 7.0.54 running, and compiled the tcnative APR lib with:
./configure --with-apr=`which apr-1-config` --with-java-home=/usr/java/jdk1.8.0_05 --with-ssl=yes --prefix=/usr/share/apache-tomcat-7.0.54

Setenv.sh:
#!/bin/bash
umask 0026
LD_LIBRARY_PATH=/usr/share/apache-tomcat-7.0.54/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH

Server.xml:
 <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />

Connector.xml:
<Connector
  clientAuth="false"
  port="9443"
  protocol="HTTP/1.1"
  SSLEnabled="true"
  scheme="https"
  secure="true"
  SSLCertificateFile="/etc/private/rsacert.pem"
  SSLCertificateKeyFile="/etc/private/rsakey.pem"
  SSLCipherSuite="ECDH+AESGCM:ECDH+AES256:ECDH+AES128:RSA+AES:!aNULL:!MD5:!DSS"
  SSLDisableCompression="true"
  SSLHonorCipherOrder="true"
  SSLVerifyClient="optional"
  SSLProtocol="TLSv1"
  server="Prism Server"
  connectionTimeout="60000"
  keepAliveTimeout="60000"
  maxKeepAliveRequests="100"
  maxThreads="150"
  maxPostSize="2097152"
  maxHeaderCount="50"
  maxHttpHeaderSize="8190"
  allowTrace="false"
/>

Starting services:
service tomcat start
Using CATALINA_BASE:   /usr/share/apache-tomcat-7.0.54
Using CATALINA_HOME:   /usr/share/apache-tomcat-7.0.54
Using CATALINA_TMPDIR: /usr/share/apache-tomcat-7.0.54/temp
Using JRE_HOME:        /usr/java/jdk1.8.0_05/jre
Using CLASSPATH:       /usr/share/apache-tomcat-7.0.54/bin/bootstrap.jar:/usr/share/apache-tomcat-7.0.54/bin/tomcat-juli.jar
Tomcat started.

logs/catalina.2014-06-12.log:

Jun 12, 2014 1:30:20 PM org.apache.catalina.core.AprLifecycleListener init
INFO: Loaded APR based Apache Tomcat Native library 1.1.30 using APR version 1.3.9.
Jun 12, 2014 1:30:20 PM org.apache.catalina.core.AprLifecycleListener init
INFO: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true
].
Jun 12, 2014 1:30:20 PM org.apache.catalina.core.AprLifecycleListener lifecycleEvent
SEVERE: Failed to initialize the SSLEngine.
org.apache.tomcat.jni.Error: 70023: This function has not been implemented on this platform
	at org.apache.tomcat.jni.SSL.initialize(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.ja
va:43)
	at java.lang.reflect.Method.invoke(Method.java:483)
	at org.apache.catalina.core.AprLifecycleListener.initializeSSL(AprLifecycleListene
r.java:270)
	at org.apache.catalina.core.AprLifecycleListener.lifecycleEvent(AprLifecycleListen
er.java:124)
	at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.j
ava:117)
	at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90
)
	at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:402)
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:99)
	at org.apache.catalina.startup.Catalina.load(Catalina.java:638)
	at org.apache.catalina.startup.Catalina.load(Catalina.java:663)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.ja
va:43)
	at java.lang.reflect.Method.invoke(Method.java:483)
	at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:280)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:454)

Jun 12, 2014 1:30:20 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-apr-9443"]
Jun 12, 2014 1:30:20 PM org.apache.coyote.AbstractProtocol init
SEVERE: Failed to initialize end point associated with ProtocolHandler ["http-apr-9443"]
java.lang.Exception: Unable to create SSLContext. Check that SSLEngine is enabled in the AprLifecycleListener, the AprLifecycleListener has initialised correctly and that a valid SSLProtocol has been specified
	at org.apache.tomcat.util.net.AprEndpoint.bind(AprEndpoint.java:503)
	at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:640)
	at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:434)
	at org.apache.catalina.connector.Connector.initInternal(Connector.java:978)
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
	at org.apache.catalina.core.StandardService.initInternal(StandardService.java:559)
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
	at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:813)
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
	at org.apache.catalina.startup.Catalina.load(Catalina.java:638)
	at org.apache.catalina.startup.Catalina.load(Catalina.java:663)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.ja
va:43)
	at java.lang.reflect.Method.invoke(Method.java:483)
	at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:280)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:454)
Caused by: java.lang.Exception: Invalid Server SSL Protocol (error:140A90F1:SSL routines:SSL_CTX_new:unable to load ssl2 md5 routines)
	at org.apache.tomcat.jni.SSLContext.make(Native Method)
	at org.apache.tomcat.util.net.AprEndpoint.bind(AprEndpoint.java:498)
	... 16 more

Jun 12, 2014 1:30:20 PM org.apache.catalina.core.StandardService initInternal
SEVERE: Failed to initialize connector [Connector[HTTP/1.1-9443]]
org.apache.catalina.LifecycleException: Failed to initialize component [Connector[HTTP/1.1
-9443]]
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:106)
	at org.apache.catalina.core.StandardService.initInternal(StandardService.java:559)
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
	at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:813)
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
	at org.apache.catalina.startup.Catalina.load(Catalina.java:638)
	at org.apache.catalina.startup.Catalina.load(Catalina.java:663)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.ja
va:43)
	at java.lang.reflect.Method.invoke(Method.java:483)
	at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:280)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:454)
Caused by: org.apache.catalina.LifecycleException: Protocol handler initialization failed
	at org.apache.catalina.connector.Connector.initInternal(Connector.java:980)
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
	... 12 more
Caused by: java.lang.Exception: Unable to create SSLContext. Check that SSLEngine is enabled in the AprLifecycleListener, the AprLifecycleListener has initialised correctly and that a valid SSLProtocol has been specified
	at org.apache.tomcat.util.net.AprEndpoint.bind(AprEndpoint.java:503)
	at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:640)
	at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:434)
	at org.apache.catalina.connector.Connector.initInternal(Connector.java:978)
	... 13 more
Caused by: java.lang.Exception: Invalid Server SSL Protocol (error:140A90F1:SSL routines:SSL_CTX_new:unable to load ssl2 md5 routines)
	at org.apache.tomcat.jni.SSLContext.make(Native Method)
	at org.apache.tomcat.util.net.AprEndpoint.bind(AprEndpoint.java:498)
	... 16 more

When I remove fips=1 from grub.conf, reboot, and add FIPSMode="on" to the AprLifecycleListener in server.xml, the Engine works and FIPSMode shows it's set to "on".  What is up with the OpenSSL library with the kernel running in FIPS mode that keeps displaying the error: java.lang.Exception: Invalid Server SSL Protocol (error:140A90F1:SSL routines:SSL_CTX_new:unable to load ssl2 md5 routines)?
Comment 20 Christopher Schultz 2014-06-27 19:24:07 UTC
I believe the "SSL2 MD5" routines problem is different from this issue, which was to allow Tomcat to start up with OpenSSL already in FIPS mode (e.g. don't choke and die if we're already in FIPS mode).

Next, Tomcat tries to initialize the SSL endpoint with a list of ciphers and I think it request too many ciphers (and violates FIPS requirements). I'm not sure why this fails when already in FIPS mode versus working when explicitly entering FIPS mode first. I thought this failure had been reported elewhere but I can't seem to find the reference right now.
Comment 21 Ben Mason 2014-07-02 13:52:03 UTC
I am still getting this error as well. Is this the key length issue? It is unclear in this thread whether that was ever fixed. Rob Sanders said he filed another bug, but it appears it was deleted.


(In reply to Christopher Schultz from comment #20)
> I believe the "SSL2 MD5" routines problem is different from this issue,
> which was to allow Tomcat to start up with OpenSSL already in FIPS mode
> (e.g. don't choke and die if we're already in FIPS mode).
> 
> Next, Tomcat tries to initialize the SSL endpoint with a list of ciphers and
> I think it request too many ciphers (and violates FIPS requirements). I'm
> not sure why this fails when already in FIPS mode versus working when
> explicitly entering FIPS mode first. I thought this failure had been
> reported elewhere but I can't seem to find the reference right now.
Comment 22 Konstantin Kolinko 2014-07-02 14:26:11 UTC
(In reply to Ben Mason from comment #21)
> Is this the key length issue? It is
> unclear in this thread whether that was ever fixed. Rob Sanders said he
> filed another bug, but it appears it was deleted.

Key length issue is bug 56396, should be fixed in TCNative 1.1.31. (r1587896)