You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2026/10/15 19:45:23 UTC

(tomcat) 20/25: Report a configuration error for PEM certificates with a FIPS key manager

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

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

commit affff7f3e5eb184678f38e97a42524176fe0f92b
Author: opencode <re...@apache.org>
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 e32edc2b9b..6f8f3190f2 100644
--- a/java/org/apache/tomcat/util/net/LocalStrings.properties
+++ b/java/org/apache/tomcat/util/net/LocalStrings.properties
@@ -201,6 +201,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 0c1c666ef2..b88da6ffa0 100644
--- a/java/org/apache/tomcat/util/net/SSLUtilBase.java
+++ b/java/org/apache/tomcat/util/net/SSLUtilBase.java
@@ -354,6 +354,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 520dcce974..6bfd41e421 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: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org