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

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

commit 68485912ec146230b116eba0391e2e0c85b40606
Author: opencode <[email protected]>
AuthorDate: Thu Oct 15 14:46:02 2026 +0200

    Report a configuration error for PEM certificates with a FIPS key manager
    
    When the KeyManagerFactory is provided by a FIPS module, Tomcat passes the
    configured key store to the factory directly and skips the manipulation of
    key material that FIPS does not allow. PEM format certificates require that
    manipulation: the key and certificate chain are read from the PEM files and
    imported into an in memory key store.
    
    Previously, the FIPS code path used the configured key store without
    checking it. For a PEM based configuration there is no key store, so the
    factory was initialised with a null key store. Depending on the
    implementation, that either produced a key manager with no keys, allowing
    the connector to start but causing every TLS handshake to fail, or an
    unrelated error during start up.
    
    Now report the configuration error when no key store is available. The
    existing message is used when no certificate has been configured at all, as
    for a non-FIPS configuration. Otherwise, explain that PEM format
    certificate files require a key store when a FIPS key manager factory is in
    use.
    
    Tests: testFipsWithPemConfiguration and testFipsWithoutConfiguration cover
    both cases. Both previously failed because no error was reported.
---
 .../apache/tomcat/util/net/LocalStrings.properties |  1 +
 java/org/apache/tomcat/util/net/SSLUtilBase.java   | 10 +++++
 .../util/net/TestKeyManagerWrappingFips.java       | 46 ++++++++++++++++++++++
 3 files changed, 57 insertions(+)

diff --git a/java/org/apache/tomcat/util/net/LocalStrings.properties 
b/java/org/apache/tomcat/util/net/LocalStrings.properties
index b335750b7c..44c9810470 100644
--- a/java/org/apache/tomcat/util/net/LocalStrings.properties
+++ b/java/org/apache/tomcat/util/net/LocalStrings.properties
@@ -179,6 +179,7 @@ sslImplementation.cnfe=Unable to create SSLImplementation 
for class [{0}]
 sslUtilBase.active=The [{0}] that are active are : [{1}]
 sslUtilBase.aliasIgnored=FIPS enabled so alias name [{0}] will be ignored. If 
there is more than one key in the key store, the key used will depend on the 
key store implementation
 sslUtilBase.alias_no_key_entry=Alias name [{0}] does not identify a key entry
+sslUtilBase.fipsPemNotSupported=FIPS enabled so PEM format certificate files 
are not supported. Configure the certificate using a key store rather than the 
certificateFile attribute
 sslUtilBase.invalidTrustManagerClassName=The trustManagerClassName provided 
[{0}] does not implement javax.net.ssl.TrustManager
 sslUtilBase.keystore_load_failed=Failed to load keystore type [{0}] with path 
[{1}] due to [{2}]
 sslUtilBase.noCertFile=SSLHostConfig attribute certificateFile must be defined 
when using an SSL connector
diff --git a/java/org/apache/tomcat/util/net/SSLUtilBase.java 
b/java/org/apache/tomcat/util/net/SSLUtilBase.java
index 14243711d5..7c40846786 100644
--- a/java/org/apache/tomcat/util/net/SSLUtilBase.java
+++ b/java/org/apache/tomcat/util/net/SSLUtilBase.java
@@ -353,6 +353,16 @@ public abstract class SSLUtilBase implements SSLUtil {
             if (keyAlias != null) {
                 log.warn(sm.getString("sslUtilBase.aliasIgnored", keyAlias));
             }
+            if (ks == null) {
+                if (certificate.getCertificateFile() == null) {
+                    throw new 
IOException(sm.getString("sslUtilBase.noCertFile"));
+                }
+                // Importing PEM format certificates into an in memory key 
store
+                // requires the key manipulation that is avoided above. 
Passing a
+                // null key store to the factory would result in a key manager
+                // with no keys and every TLS handshake would then fail.
+                throw new 
IOException(sm.getString("sslUtilBase.fipsPemNotSupported"));
+            }
             kmf.init(ksUsed, keyPassArray);
             return kmf.getKeyManagers();
         }
diff --git a/test/org/apache/tomcat/util/net/TestKeyManagerWrappingFips.java 
b/test/org/apache/tomcat/util/net/TestKeyManagerWrappingFips.java
index 3f1e9e2e31..7b2928f570 100644
--- a/test/org/apache/tomcat/util/net/TestKeyManagerWrappingFips.java
+++ b/test/org/apache/tomcat/util/net/TestKeyManagerWrappingFips.java
@@ -18,6 +18,7 @@
 package org.apache.tomcat.util.net;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.Socket;
@@ -74,6 +75,51 @@ public class TestKeyManagerWrappingFips {
         getKeyManagers();
         Assert.assertTrue(DummyKeyStoreSpi.wrappingOccurred);
     }
+
+
+    @Test
+    public void testFipsWithPemConfiguration() throws Exception {
+        Security.addProvider(new DummyKeyManagerFactoryProvider(FIPS_PROVIDER,
+                "Sun JSSE provider (FIPS mode, crypto provider 
SunPKCS11-NSSfips", DUMMY_ALGORITHM));
+
+        SSLHostConfigCertificate certificate = getCertificate();
+        certificate.setCertificateFile("server.crt");
+
+        try {
+            new JSSEUtil(certificate).getKeyManagers();
+            Assert.fail("PEM format certificates are not supported with a FIPS 
key manager factory");
+        } catch (IOException ioe) {
+            // Before the FIPS branch checked for a key store, the key manager
+            // factory was initialised with a null key store. That produced a 
key
+            // manager with no keys which failed every TLS handshake with an
+            // unrelated error rather than reporting the configuration error.
+            Assert.assertTrue(ioe.getMessage(), 
ioe.getMessage().contains("PEM"));
+        }
+    }
+
+
+    @Test
+    public void testFipsWithoutConfiguration() throws Exception {
+        Security.addProvider(new DummyKeyManagerFactoryProvider(FIPS_PROVIDER,
+                "Sun JSSE provider (FIPS mode, crypto provider 
SunPKCS11-NSSfips", DUMMY_ALGORITHM));
+
+        try {
+            new JSSEUtil(getCertificate()).getKeyManagers();
+            Assert.fail("A certificate configuration is required");
+        } catch (IOException ioe) {
+            // Ignore. This is the standard error for a missing certificate 
file.
+            Assert.assertFalse(ioe.getMessage(), 
ioe.getMessage().contains("PEM"));
+        }
+    }
+
+
+    private SSLHostConfigCertificate getCertificate() {
+        SSLHostConfig hostConfig = new SSLHostConfig();
+        hostConfig.setKeyManagerAlgorithm(DUMMY_ALGORITHM);
+        return new SSLHostConfigCertificate(hostConfig, 
SSLHostConfigCertificate.Type.UNDEFINED);
+    }
+
+
     private void getKeyManagers() throws Exception {
         Security.addProvider(new DummyKeyStoreProvider(KEYSTORE_PROVIDER, "", 
DUMMY_KEYSTORE));
         SSLHostConfig hostConfig = new SSLHostConfig();


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to