You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2022/06/15 08:48:13 UTC

[tomcat] branch 10.0.x updated: Enable the use of Tomcat Native with OpenSSL 3 using the FIPS provider

This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 10.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/10.0.x by this push:
     new 39eb2f9127 Enable the use of Tomcat Native with OpenSSL 3 using the FIPS provider
39eb2f9127 is described below

commit 39eb2f912711ba0407ccba8a48d0970cff59ff71
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Wed Jun 1 15:33:02 2022 +0100

    Enable the use of Tomcat Native with OpenSSL 3 using the FIPS provider
---
 .../apache/catalina/core/AprLifecycleListener.java | 81 +++++++++++++++-------
 .../apache/catalina/core/LocalStrings.properties   |  2 +
 webapps/docs/changelog.xml                         |  5 ++
 webapps/docs/config/listeners.xml                  | 22 +++---
 4 files changed, 76 insertions(+), 34 deletions(-)

diff --git a/java/org/apache/catalina/core/AprLifecycleListener.java b/java/org/apache/catalina/core/AprLifecycleListener.java
index 795454cc60..ca92772ba5 100644
--- a/java/org/apache/catalina/core/AprLifecycleListener.java
+++ b/java/org/apache/catalina/core/AprLifecycleListener.java
@@ -76,6 +76,11 @@ public class AprLifecycleListener implements LifecycleListener {
 
     // ---------------------------------------------- Properties
 
+    private static int tcnMajor = 0;
+    private static int tcnMinor = 0;
+    private static int tcnPatch = 0;
+    private static int tcnVersion = 0;
+
     protected static String SSLEngine = "on"; //default on
     protected static String FIPSMode = "off"; // default off, valid only when SSLEngine="on"
     protected static String SSLRandomSeed = "builtin";
@@ -185,12 +190,7 @@ public class AprLifecycleListener implements LifecycleListener {
     }
 
     @SuppressWarnings("deprecation")
-    private static void init()
-    {
-        int major = 0;
-        int minor = 0;
-        int patch = 0;
-        int apver = 0;
+    private static void init() {
         int rqver = TCN_REQUIRED_MAJOR * 1000 + TCN_REQUIRED_MINOR * 100 + TCN_REQUIRED_PATCH;
         int rcver = TCN_RECOMMENDED_MAJOR * 1000 + TCN_RECOMMENDED_MINOR * 100 + TCN_RECOMMENDED_PV;
 
@@ -201,10 +201,10 @@ public class AprLifecycleListener implements LifecycleListener {
 
         try {
             Library.initialize(null);
-            major = Library.TCN_MAJOR_VERSION;
-            minor = Library.TCN_MINOR_VERSION;
-            patch = Library.TCN_PATCH_VERSION;
-            apver = major * 1000 + minor * 100 + patch;
+            tcnMajor = Library.TCN_MAJOR_VERSION;
+            tcnMinor = Library.TCN_MINOR_VERSION;
+            tcnPatch = Library.TCN_PATCH_VERSION;
+            tcnVersion = tcnMajor * 1000 + tcnMinor * 100 + tcnPatch;
         } catch (LibraryNotFoundError lnfe) {
             // Library not on path
             if (log.isDebugEnabled()) {
@@ -222,7 +222,7 @@ public class AprLifecycleListener implements LifecycleListener {
             log.warn(sm.getString("aprListener.aprInitError", t.getMessage()), t);
             return;
         }
-        if (major > 1 && "off".equalsIgnoreCase(SSLEngine)) {
+        if (tcnMajor > 1 && "off".equalsIgnoreCase(SSLEngine)) {
             log.error(sm.getString("aprListener.sslRequired", SSLEngine, Library.versionString()));
             try {
                 // Tomcat Native 2.x onwards requires SSL
@@ -233,7 +233,7 @@ public class AprLifecycleListener implements LifecycleListener {
             }
             return;
         }
-        if (apver < rqver) {
+        if (tcnVersion < rqver) {
             log.error(sm.getString("aprListener.tcnInvalid",
                     Library.versionString(),
                     TCN_REQUIRED_MAJOR + "." +
@@ -249,7 +249,7 @@ public class AprLifecycleListener implements LifecycleListener {
             }
             return;
         }
-        if (apver < rcver) {
+        if (tcnVersion < rcver) {
             initInfoLogMessages.add(sm.getString("aprListener.tcnVersion",
                     Library.versionString(),
                     TCN_REQUIRED_MAJOR + "." +
@@ -299,41 +299,66 @@ public class AprLifecycleListener implements LifecycleListener {
         method = clazz.getMethod(methodName, paramTypes);
         method.invoke(null, paramValues);
 
-        if (!(null == FIPSMode || "off".equalsIgnoreCase(FIPSMode))) {
+        // OpenSSL 3 onwards uses providers
+        boolean usingProviders = tcnMajor > 1 || (tcnVersion > 1233 && (SSL.version() & 0xF0000000L) > 2);
 
+        // Tomcat Native 1.x built with OpenSSL 1.x without explicitly enabling
+        // FIPS and Tomcat Native < 1.2.34 built with OpenSSL 3.x will fail if
+        // any calls are made to SSL.fipsModeGet or SSL.fipsModeSet
+        if (usingProviders || !(null == FIPSMode || "off".equalsIgnoreCase(FIPSMode))) {
             fipsModeActive = false;
-
             final boolean enterFipsMode;
             int fipsModeState = SSL.fipsModeGet();
 
             if(log.isDebugEnabled()) {
-                log.debug(sm.getString("aprListener.currentFIPSMode",
-                                       Integer.valueOf(fipsModeState)));
+                log.debug(sm.getString("aprListener.currentFIPSMode", Integer.valueOf(fipsModeState)));
             }
 
-            if ("on".equalsIgnoreCase(FIPSMode)) {
+            if (null == FIPSMode || "off".equalsIgnoreCase(FIPSMode)) {
                 if (fipsModeState == FIPS_ON) {
-                    log.info(sm.getString("aprListener.skipFIPSInitialization"));
+                    fipsModeActive = true;
+                }
+                enterFipsMode = false;
+            } else if ("on".equalsIgnoreCase(FIPSMode)) {
+                if (fipsModeState == FIPS_ON) {
+                    if (!usingProviders) {
+                        log.info(sm.getString("aprListener.skipFIPSInitialization"));
+                    }
                     fipsModeActive = true;
                     enterFipsMode = false;
                 } else {
-                    enterFipsMode = true;
+                    if (usingProviders) {
+                        throw new IllegalStateException(sm.getString("aprListener.FIPSProviderNotDefault", FIPSMode));
+                    } else {
+                        enterFipsMode = true;
+                    }
                 }
             } else if ("require".equalsIgnoreCase(FIPSMode)) {
                 if (fipsModeState == FIPS_ON) {
                     fipsModeActive = true;
                     enterFipsMode = false;
                 } else {
-                    throw new IllegalStateException(
-                            sm.getString("aprListener.requireNotInFIPSMode"));
+                    if (usingProviders) {
+                        throw new IllegalStateException(sm.getString("aprListener.FIPSProviderNotDefault", FIPSMode));
+                    } else {
+                        throw new IllegalStateException(sm.getString("aprListener.requireNotInFIPSMode"));
+                    }
                 }
             } else if ("enter".equalsIgnoreCase(FIPSMode)) {
                 if (fipsModeState == FIPS_OFF) {
-                    enterFipsMode = true;
+                    if (usingProviders) {
+                        throw new IllegalStateException(sm.getString("aprListener.FIPSProviderNotDefault", FIPSMode));
+                    } else {
+                        enterFipsMode = true;
+                    }
                 } else {
-                    throw new IllegalStateException(sm.getString(
-                            "aprListener.enterAlreadyInFIPSMode",
-                            Integer.valueOf(fipsModeState)));
+                    if (usingProviders) {
+                        fipsModeActive = true;
+                        enterFipsMode = false;
+                    } else {
+                        throw new IllegalStateException(sm.getString(
+                                "aprListener.enterAlreadyInFIPSMode", Integer.valueOf(fipsModeState)));
+                    }
                 }
             } else {
                 throw new IllegalArgumentException(sm.getString(
@@ -355,6 +380,10 @@ public class AprLifecycleListener implements LifecycleListener {
                 fipsModeActive = true;
                 log.info(sm.getString("aprListener.initializeFIPSSuccess"));
             }
+
+            if (usingProviders && fipsModeActive) {
+                log.info(sm.getString("aprListener.usingFIPSProvider"));
+            }
         }
 
         log.info(sm.getString("aprListener.initializedOpenSSL", SSL.versionString()));
diff --git a/java/org/apache/catalina/core/LocalStrings.properties b/java/org/apache/catalina/core/LocalStrings.properties
index 67fdf68951..bc9778aa87 100644
--- a/java/org/apache/catalina/core/LocalStrings.properties
+++ b/java/org/apache/catalina/core/LocalStrings.properties
@@ -75,6 +75,7 @@ aprListener.aprInitError=The Apache Tomcat Native library failed to load. The er
 aprListener.currentFIPSMode=Current FIPS mode: [{0}]
 aprListener.enterAlreadyInFIPSMode=AprLifecycleListener is configured to force entering FIPS mode, but library is already in FIPS mode [{0}]
 aprListener.flags=APR capabilities: IPv6 [{0}], sendfile [{1}], accept filters [{2}], random [{3}], UDS [{4}].
+aprListener.FIPSProviderNotDefault=The FIPS provider must be configured as the default provider when the AprLifecycleListener is configured with FIPS mode [{0}]
 aprListener.initializeFIPSFailed=Failed to enter FIPS mode
 aprListener.initializeFIPSSuccess=Successfully entered FIPS mode
 aprListener.initializedOpenSSL=OpenSSL successfully initialized [{0}]
@@ -89,6 +90,7 @@ aprListener.tcnVersion=An older version [{0}] of the Apache Tomcat Native librar
 aprListener.tooLateForFIPSMode=Cannot setFIPSMode: SSL has already been initialized
 aprListener.tooLateForSSLEngine=Cannot setSSLEngine: SSL has already been initialized
 aprListener.tooLateForSSLRandomSeed=Cannot setSSLRandomSeed: SSL has already been initialized
+aprListener.usingFIPSProvider=Using OpenSSL with the FIPS provider as the default provider
 aprListener.wrongFIPSMode=Unexpected value of FIPSMode option of AprLifecycleListener: [{0}]
 
 asyncContextImpl.asyncDispatchError=Error during asynchronous dispatch
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 4f1f3dbdc6..6466203bdc 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -122,6 +122,11 @@
         <code>org.apache.tomcat.util.net.Nio2Endpoint.handshake</code>) for TLS
         handshake failures. (markt)
       </add>
+      <add>
+        Enable the use of the FIPS provider for TLS enabled Connectors when
+        using Tomcat Native 1.2.34 onwards built with OpenSSL 3.0.x onwards.
+        (markt)
+      </add>
     </changelog>
   </subsection>
   <subsection name="Jasper">
diff --git a/webapps/docs/config/listeners.xml b/webapps/docs/config/listeners.xml
index 9018caecab..fb84d1611d 100644
--- a/webapps/docs/config/listeners.xml
+++ b/webapps/docs/config/listeners.xml
@@ -115,17 +115,23 @@
       </attribute>
 
       <attribute name="FIPSMode" required="false">
-        <p>Set to <code>on</code> to request that OpenSSL be in FIPS mode
-        (if OpenSSL is already in FIPS mode, it will remain in FIPS mode).
-        Set to <code>enter</code> to force OpenSSL to enter FIPS mode (an error
-        will occur if OpenSSL is already in FIPS mode).
+        <p>The behaviour of this attribute depends on whether Tomcat Native has
+        been compiled against OpenSSL 1.x or OpenSSL 3.x.</p>
+        <p>For OpenSSL 1.x: Set to <code>on</code> to request that OpenSSL be in
+        FIPS mode (if OpenSSL is already in FIPS mode, it will remain in FIPS
+        mode).
+        Set to <code>enter</code> to force OpenSSL to enter FIPS mode (an
+        error will occur if OpenSSL is already in FIPS mode).
         Set to <code>require</code> to require that OpenSSL <i>already</i> be
         in FIPS mode (an error will occur if OpenSSL is not already in FIPS
         mode).</p>
-        <p>FIPS mode <em>requires you to have a FIPS-capable OpenSSL library which
-        you must build yourself</em>.
-        If this attribute is set to any of the above values, the <b>SSLEngine</b>
-        must be enabled as well.</p>
+        <p>For OpenSSL 3.x: <code>on</code>, <code>enter</code> and
+        <code>require</code> all behave the same way. If the FIPS provider is
+        the default provider, it will be used. If the FIPS provider is not the
+        default provider, an error will occur.</p>
+        <p>FIPS mode <em>requires you to have a FIPS-capable OpenSSL library</em>.
+        If this attribute is set to anything other than <code>off</code>, the
+        <b>SSLEngine</b> must be enabled as well.</p>
         <p>The default value is <code>off</code>.</p>
       </attribute>
 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org