elastic/elasticsearch · critical · SslConfigException

failed to load the system PKCS#11 truststore

Error message

failed to load the system PKCS#11 truststore

What it means

Thrown as SslConfigException by DefaultJdkTrustConfig.getSystemTrustStore when the system is configured to use a PKCS#11 token as its SSL trust store (javax.net.ssl.trustStoreType=PKCS11) and loading the PKCS#11 KeyStore fails. The password for the PKCS#11 token is read from javax.net.ssl.trustStorePassword. The underlying GeneralSecurityException or IOException is the cause.

Source

Thrown at libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/DefaultJdkTrustConfig.java:86

            throw new SslConfigException("failed to initialize a TrustManager for the system keystore", e);
        }
    }

    /**
     * When a PKCS#11 token is used as the system default keystore/truststore, we need to pass the keystore
     * password when loading, even for reading certificates only ( as opposed to i.e. JKS keystores where
     * we only need to pass the password for reading Private Key entries ).
     *
     * @return the KeyStore used as truststore for PKCS#11 initialized with the password, null otherwise
     */
    private KeyStore getSystemTrustStore() {
        if (isPkcs11Truststore(systemProperties) && trustStorePassword != null) {
            try {
                KeyStore keyStore = KeyStore.getInstance("PKCS11");
                keyStore.load(null, trustStorePassword);
                return keyStore;
            } catch (GeneralSecurityException | IOException e) {
                throw new SslConfigException("failed to load the system PKCS#11 truststore", e);
            }
        }
        return null;
    }

    private static boolean isPkcs11Truststore(BiFunction<String, String, String> systemProperties) {
        return systemProperties.apply("javax.net.ssl.trustStoreType", "").equalsIgnoreCase("PKCS11");
    }

    private static char[] getSystemTrustStorePassword(BiFunction<String, String, String> systemProperties) {
        return systemProperties.apply("javax.net.ssl.trustStorePassword", "").toCharArray();
    }

    @Override
    public Collection<Path> getDependentFiles() {
        return List.of();
    }

View on GitHub (pinned to db6a809a66)

Solutions

  1. Verify the PKCS#11 provider is registered in java.security (e.g. security.provider.N=SunPKCS11 /path/to/config).
  2. Confirm the HSM/token is connected and unlocked with the correct PIN (javax.net.ssl.trustStorePassword).

Example fix

// before — PKCS11 truststore type set but provider unconfigured
-Djavax.net.ssl.trustStoreType=PKCS11

// after — configure the SunPKCS11 provider with a valid config file
-Djavax.net.ssl.trustStoreType=PKCS11
-Djava.security.properties==pkcs11.properties
// pkcs11.properties contains:
//   security.provider.1=SunPKCS11 /etc/pkcs11/sunpkcs11.cfg
Defensive patterns

Strategy: try-catch

Try / catch

try {
    X509ExtendedTrustManager tm = defaultJdkTrustConfig.createTrustManager();
} catch (SslConfigException e) {
    // cause is GeneralSecurityException or IOException from PKCS11 KeyStore.load
    log.error("PKCS11 trust store load failed: {}", e.getMessage(), e.getCause());
    // verify SunPKCS11 provider config, token presence, and PIN correctness
}

Prevention

When it happens

Trigger: System property javax.net.ssl.trustStoreType is set to 'PKCS11' (case-insensitive), javax.net.ssl.trustStorePassword is non-null, and KeyStore.getInstance("PKCS11").load(null, password) throws. Causes include: PKCS#11 provider not configured, wrong PIN/password, hardware token not inserted, or provider config file missing.

Common situations: Running Elasticsearch with an HSM or smart-card-backed trust store on a host where the SunPKCS11 provider is not properly configured (missing provider config via -Djava.security.properties or security.provider entries). Also when the token PIN is wrong or the token is physically absent. Common in FIPS-compliant or enterprise PKI deployments.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/346fbaac64346041. Report an issue: GitHub.