mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Yuriy Movchan
01.20.2022 4ed62ed003d9e18bc4ff04024f8e294a47395256
Add BCFKS FIPS key store type support (#247)

24 files modified
383 ■■■■ changed files
opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java 4 ●●●● patch | view | raw | blame | history
opendj-core/pom.xml 4 ●●●● patch | view | raw | blame | history
opendj-core/src/main/java/com/forgerock/opendj/util/FipsStaticUtils.java 62 ●●●● patch | view | raw | blame | history
opendj-core/src/main/java/com/forgerock/opendj/util/StaticUtils.java 10 ●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/ldap/TrustManagers.java 16 ●●●●● patch | view | raw | blame | history
opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/Requests.java 2 ●●● patch | view | raw | blame | history
opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties 8 ●●●● patch | view | raw | blame | history
opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CRAMMD5SASLBindRequestTestCase.java 2 ●●● patch | view | raw | blame | history
opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/DigestMD5SASLBindRequestTestCase.java 2 ●●● patch | view | raw | blame | history
opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GSSAPISASLBindRequestTestCase.java 2 ●●● patch | view | raw | blame | history
opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GenericBindRequestTestCase.java 2 ●●● patch | view | raw | blame | history
opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/PlainSASLBindRequestTestCase.java 2 ●●● patch | view | raw | blame | history
opendj-server-legacy/resource/config/config.ldif 22 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/quicksetup/SecurityOptions.java 28 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/Installer.java 48 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/quicksetup/util/Utils.java 2 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java 72 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/InstallDS.java 50 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/InstallDSArgumentParser.java 12 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/SSLConnectionFactory.java 6 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/util/CertificateManager.java 12 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/messages/org/opends/messages/quickSetup.properties 7 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/messages/org/opends/messages/tool.properties 6 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/messages/org/opends/messages/utility.properties 2 ●●● patch | view | raw | blame | history
opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java
@@ -851,6 +851,10 @@
            return new PromptingTrustManager(app, tm);
        }
        if (isFips) {
            return TrustManagers.checkUsingPkcs11TrustStore();
        }
        return tm;
    }
opendj-core/pom.xml
@@ -112,8 +112,8 @@
    <properties>
        <bc.fips.version>1.0.2.1</bc.fips.version>
        <bctls.fips.version>1.0.9</bctls.fips.version>
        <bc.fips.version>1.0.2.3</bc.fips.version>
        <bctls.fips.version>1.0.13</bctls.fips.version>
        <opendj.osgi.import.additional>
            com.sun.security.auth*;resolution:=optional
opendj-core/src/main/java/com/forgerock/opendj/util/FipsStaticUtils.java
@@ -4,30 +4,66 @@
import static com.forgerock.opendj.ldap.CoreMessages.INFO_BC_PROVIDER_REGISTER;
import static com.forgerock.opendj.ldap.CoreMessages.INFO_BC_PROVIDER_REGISTERED_ALREADY;
import static com.forgerock.opendj.ldap.CoreMessages.INFO_BC_FIPS_PROVIDER_NOT_EXISTS;
import static com.forgerock.opendj.ldap.CoreMessages.INFO_BC_FIPS_PROVIDER_REGISTER;
import static com.forgerock.opendj.ldap.CoreMessages.INFO_BC_PROVIDER_FAILED_TO_CREATE;
import java.security.Security;
public class FipsStaticUtils {
    private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
    /**
     * A zero-length byte array.
     */
    public static final byte[] EMPTY_BYTES = new byte[0];
    public static void registerBcProvider()
    {
    public static final String BC_PROVIDER_NAME = "BC";
    public static final String BC_FIPS_PROVIDER_NAME = "BCFIPS";
    private static final String BC_GENERIC_PROVIDER_CLASS_NAME = "org.bouncycastle.jce.provider.BouncyCastleProvider";
    private static final String BC_FIPS_PROVIDER_CLASS_NAME    = "org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider";
    public static void registerBcProvider(){
        if(!StaticUtils.isFips()) {
            return;
        }
        org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider bouncyCastleProvider
                = (org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider) java.security.Security.getProvider(org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider.PROVIDER_NAME);
        if (bouncyCastleProvider == null) {
            FipsStaticUtils.logger.info(INFO_BC_PROVIDER_REGISTER.get());
            bouncyCastleProvider = new org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider();
            java.security.Security.insertProviderAt(bouncyCastleProvider, 1);
        String providerName = BC_PROVIDER_NAME;
        String className = BC_GENERIC_PROVIDER_CLASS_NAME;
        boolean bcFipsProvider = checkBcFipsProvider();
        if (bcFipsProvider) {
            logger.info(INFO_BC_FIPS_PROVIDER_REGISTER);
            providerName = BC_FIPS_PROVIDER_NAME;
            className = BC_FIPS_PROVIDER_CLASS_NAME;
        } else {
            FipsStaticUtils.logger.info(INFO_BC_PROVIDER_REGISTERED_ALREADY.get());
            logger.info(INFO_BC_PROVIDER_REGISTER.get());
        }
        installBCProvider(providerName, className);
    }
    private static void installBCProvider(String providerName, String providerClassName) {
        java.security.Provider bouncyCastleProvider = Security.getProvider(providerName);
        if (bouncyCastleProvider == null) {
            try {
                bouncyCastleProvider = (java.security.Provider) Class.forName(providerClassName).getConstructor().newInstance();
                java.security.Security.insertProviderAt(bouncyCastleProvider, 1);
            } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException ex) {
                logger.error(INFO_BC_PROVIDER_FAILED_TO_CREATE.get());
            }
        } else {
            logger.info(INFO_BC_PROVIDER_REGISTERED_ALREADY.get());
        }
    }
    private static boolean checkBcFipsProvider() {
        try {
            // Check if there is BC FIPS provider libs
            Class.forName(BC_FIPS_PROVIDER_CLASS_NAME);
        } catch (ClassNotFoundException e) {
            logger.trace(INFO_BC_FIPS_PROVIDER_NOT_EXISTS.get(), e);
            return false;
        }
        return true;
    }
}
opendj-core/src/main/java/com/forgerock/opendj/util/StaticUtils.java
@@ -36,9 +36,6 @@
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import static com.forgerock.opendj.ldap.CoreMessages.INFO_BC_PROVIDER_REGISTER;
import static com.forgerock.opendj.ldap.CoreMessages.INFO_BC_PROVIDER_REGISTERED_ALREADY;
/**
 * Common utility methods.
 */
@@ -66,6 +63,11 @@
     */
    public static final String EOL = System.getProperty("line.separator");
    /**
     * A zero-length byte array.
     */
    public static final byte[] EMPTY_BYTES = new byte[0];
    /** The name of the time zone for universal coordinated time (UTC). */
    private static final String TIME_ZONE_UTC = "UTC";
@@ -784,6 +786,7 @@
            if (providers[i].getName().toLowerCase().contains("fips"))
                return true;
        }
        return false;
    }
@@ -792,4 +795,5 @@
           FipsStaticUtils.registerBcProvider();
       } catch (NoClassDefFoundError e) {}
    }
}
opendj-core/src/main/java/org/forgerock/opendj/ldap/TrustManagers.java
@@ -522,6 +522,22 @@
        throw new NoSuchAlgorithmException();
    }
    public static X509TrustManager checkUsingPkcs11TrustStore() throws GeneralSecurityException, IOException {
        final KeyStore keyStore = KeyStore.getInstance("PKCS11");
        keyStore.load(null, null);
        final TrustManagerFactory tmf =
                TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(keyStore);
        for (final TrustManager tm : tmf.getTrustManagers()) {
            if (tm instanceof X509TrustManager) {
                return (X509TrustManager) tm;
            }
        }
        throw new NoSuchAlgorithmException();
    }
    public static boolean isFips() {
        Provider[] providers = Security.getProviders();
        for (int i = 0; i < providers.length; i++) {
opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/Requests.java
@@ -17,7 +17,7 @@
package org.forgerock.opendj.ldap.requests;
import static com.forgerock.opendj.util.FipsStaticUtils.EMPTY_BYTES;
import static com.forgerock.opendj.util.StaticUtils.EMPTY_BYTES;
import static com.forgerock.opendj.util.StaticUtils.getBytes;
import java.util.Arrays;
opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
@@ -616,8 +616,12 @@
INFO_RESULT_OFFSET_RANGE_ERROR=Offset Range Error
INFO_RESULT_VIRTUAL_LIST_VIEW_ERROR=Virtual List View Error
INFO_RESULT_NO_OPERATION=No Operation
INFO_BC_PROVIDER_REGISTER=Registering Bouncy Castle Provider
INFO_BC_PROVIDER_REGISTERED_ALREADY=Bouncy Castle Provider was registered already
INFO_BC_PROVIDER_REGISTER=Attempting to install BC Provider
INFO_BC_FIPS_PROVIDER_REGISTER=Attempting to install BC FIPS provider
INFO_BC_FIPS_PROVIDER_NOT_EXISTS=BC FIPS provider is not available
INFO_BC_PROVIDER_REGISTERED_ALREADY=BC Provider was registered already
INFO_BC_PROVIDER_FAILED_TO_CREATE=Failed to create BC Provider
#
# Protocol messages
#
opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CRAMMD5SASLBindRequestTestCase.java
@@ -17,7 +17,7 @@
package org.forgerock.opendj.ldap.requests;
import static com.forgerock.opendj.util.FipsStaticUtils.EMPTY_BYTES;
import static com.forgerock.opendj.util.StaticUtils.EMPTY_BYTES;
import static com.forgerock.opendj.util.StaticUtils.getBytes;
import static org.fest.assertions.Assertions.assertThat;
opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/DigestMD5SASLBindRequestTestCase.java
@@ -17,7 +17,7 @@
package org.forgerock.opendj.ldap.requests;
import static com.forgerock.opendj.util.FipsStaticUtils.EMPTY_BYTES;
import static com.forgerock.opendj.util.StaticUtils.EMPTY_BYTES;
import static com.forgerock.opendj.util.StaticUtils.getBytes;
import static org.fest.assertions.Assertions.assertThat;
import static org.testng.Assert.assertEquals;
opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GSSAPISASLBindRequestTestCase.java
@@ -17,7 +17,7 @@
package org.forgerock.opendj.ldap.requests;
import static com.forgerock.opendj.util.FipsStaticUtils.EMPTY_BYTES;
import static com.forgerock.opendj.util.StaticUtils.EMPTY_BYTES;
import static com.forgerock.opendj.util.StaticUtils.getBytes;
import static org.fest.assertions.Assertions.assertThat;
import static org.testng.Assert.assertEquals;
opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GenericBindRequestTestCase.java
@@ -17,7 +17,7 @@
package org.forgerock.opendj.ldap.requests;
import static com.forgerock.opendj.util.FipsStaticUtils.EMPTY_BYTES;
import static com.forgerock.opendj.util.StaticUtils.EMPTY_BYTES;
import static com.forgerock.opendj.util.StaticUtils.getBytes;
import static org.fest.assertions.Assertions.assertThat;
opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/PlainSASLBindRequestTestCase.java
@@ -17,7 +17,7 @@
package org.forgerock.opendj.ldap.requests;
import static com.forgerock.opendj.util.FipsStaticUtils.EMPTY_BYTES;
import static com.forgerock.opendj.util.StaticUtils.EMPTY_BYTES;
import static com.forgerock.opendj.util.StaticUtils.getBytes;
import static org.fest.assertions.Assertions.assertThat;
opendj-server-legacy/resource/config/config.ldif
@@ -693,6 +693,17 @@
ds-cfg-enabled: false
ds-cfg-key-store-pin-file: config/keystore.pin
dn: cn=BCFKS,cn=Key Manager Providers,cn=config
objectClass: top
objectClass: ds-cfg-key-manager-provider
objectClass: ds-cfg-file-based-key-manager-provider
cn: BCFKS
ds-cfg-java-class: org.opends.server.extensions.FileBasedKeyManagerProvider
ds-cfg-enabled: false
ds-cfg-key-store-type: BCFKS
ds-cfg-key-store-file: config/keystore.bcfks
ds-cfg-key-store-pin-file: config/keystore.pin
dn: cn=Loggers,cn=config
objectClass: top
objectClass: ds-cfg-branch
@@ -1566,6 +1577,17 @@
ds-cfg-trust-store-type: PKCS12
ds-cfg-trust-store-file: config/truststore.p12
dn: cn=BCFKS,cn=Trust Manager Providers,cn=config
objectClass: top
objectClass: ds-cfg-trust-manager-provider
objectClass: ds-cfg-file-based-trust-manager-provider
cn: BCFKS
ds-cfg-java-class: org.opends.server.extensions.FileBasedTrustManagerProvider
ds-cfg-enabled: false
ds-cfg-trust-store-type: BCFKS
ds-cfg-trust-store-file: config/truststore.bcfks
ds-cfg-trust-store-pin-file: config/keystore.pin
dn: cn=Virtual Attributes,cn=config
objectClass: top
objectClass: ds-cfg-branch
opendj-server-legacy/src/main/java/org/opends/quicksetup/SecurityOptions.java
@@ -48,7 +48,9 @@
    /** Use an existing PKCS#11 key store. */
    PKCS11,
    /** Use an existing PKCS#12 key store. */
    PKCS12
    PKCS12,
    /** Use an existing BCFKS key store. */
    BCFKS
  }
  private CertificateType certificateType;
@@ -214,6 +216,30 @@
  }
  /**
   * Creates a new instance of a SecurityOptions using a BCFKS Key Store.
   *
   * @param keystorePath
   *          the path of the key store.
   * @param keystorePwd
   *          the password of the key store.
   * @param enableSSL
   *          whether SSL is enabled or not.
   * @param enableStartTLS
   *          whether Start TLS is enabled or not.
   * @param sslPort
   *          the value of the LDAPS port.
   * @param aliasesToUse
   *          the aliases of the certificates in the keystore to be used.
   * @return a new instance of a SecurityOptions using a PKCS#12 Key Store.
   */
  public static SecurityOptions createBCFKSCertificateOptions( String keystorePath, String keystorePwd,
          boolean enableSSL, boolean enableStartTLS, int sslPort, Collection<String> aliasesToUse)
  {
    return createOptionsForCertificatType(
            CertificateType.BCFKS, keystorePath, keystorePwd, enableSSL, enableStartTLS, sslPort, aliasesToUse);
  }
  /**
   * Creates a new instance of a SecurityOptions using the provided type Key
   * Store.
   *
opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/Installer.java
@@ -1370,7 +1370,14 @@
        configureKeyAndTrustStore(CertificateManager.KEY_STORE_PATH_PKCS11, CertificateManager.KEY_STORE_TYPE_PKCS11,
            CertificateManager.KEY_STORE_TYPE_JKS, sec);
        configureAdminKeyAndTrustStore(CertificateManager.KEY_STORE_PATH_PKCS11, CertificateManager.KEY_STORE_TYPE_PKCS11,
                CertificateManager.KEY_STORE_TYPE_JKS, sec, true);
        break;
      case BCFKS:
          configureKeyAndTrustStore(sec.getKeystorePath(), CertificateManager.KEY_STORE_TYPE_BCFKS,
                CertificateManager.KEY_STORE_TYPE_JKS, sec);
          configureAdminKeyAndTrustStore(sec.getKeystorePath(), CertificateManager.KEY_STORE_TYPE_BCFKS,
                  CertificateManager.KEY_STORE_TYPE_BCFKS, sec, true);
        break;
      default:
@@ -1403,24 +1410,35 @@
  }
  private void configureAdminKeyAndTrustStore(final String keyStorePath, final String keyStoreType,
      final String trustStoreType, final SecurityOptions sec) throws Exception
      final String trustStoreType, final SecurityOptions sec, boolean exportKeys) throws Exception
  {
    final String keystorePassword = sec.getKeystorePassword();
    final String trustStorePath = getPath2("admin-truststore");
    if (exportKeys) {
        final String exportTrustStorePath = getExportTrustManagerPath(trustStoreType);
    CertificateManager certManager = new CertificateManager(keyStorePath, keyStoreType, keystorePassword);
    for (String keyStoreAlias : sec.getAliasesToUse())
    {
      SetupUtils.exportCertificate(certManager, keyStoreAlias, getTemporaryCertificatePath());
      configureAdminTrustStore(trustStorePath, trustStoreType, keyStoreAlias, keystorePassword);
          configureAdminTrustStore(exportTrustStorePath, trustStoreType, keyStoreAlias, keystorePassword);
        }
    }
    // Set default trustManager to allow check server startup status
    final String trustStorePath = getPath2("truststore");
    if (com.forgerock.opendj.util.StaticUtils.isFips()) {
        String usedTrustStorePath = trustStorePath;
        String usedTrustStoreType = "JKS";
/*
        if (keyStoreType.equals(CertificateManager.KEY_STORE_TYPE_BCFKS)) {
            usedTrustStorePath = getTrustManagerPath(keyStoreType);
            usedTrustStoreType = keyStoreType;
        }
*/
        KeyStore truststore = null;
        try (final FileInputStream fis = new FileInputStream(trustStorePath))
        try (final FileInputStream fis = new FileInputStream(usedTrustStorePath))
        {
          truststore = KeyStore.getInstance(trustStoreType);
          truststore = KeyStore.getInstance(usedTrustStoreType);
          truststore.load(fis, keystorePassword.toCharArray());
        }
        catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e)
@@ -1496,6 +1514,10 @@
      addCertificateArguments(argList, null, aliasInKeyStore, "cn=PKCS11,cn=Key Manager Providers,cn=config",
          "cn=JKS,cn=Trust Manager Providers,cn=config");
      break;
    case BCFKS:
        addCertificateArguments(argList, sec, aliasInKeyStore, "cn=BCFKS,cn=Key Manager Providers,cn=config",
            "cn=BCFKS,cn=Trust Manager Providers,cn=config");
        break;
    case NO_CERTIFICATE:
      // Nothing to do.
      break;
@@ -4045,6 +4067,22 @@
  }
  /**
   * Returns the trustmanager path to be used for exported
   * certificate.
   *
   * @return the trustmanager path to be used for exporting
   *         certificate.
   */
  private String getExportTrustManagerPath(String type)
  {
      if (type.equals(CertificateManager.KEY_STORE_TYPE_BCFKS)) {
          return getPath2("truststore.bcfks");
      }
      return getPath2("admin-truststore");
  }
  /**
   * Returns the path of the self-signed that we export to be able to create a
   * truststore.
   *
opendj-server-legacy/src/main/java/org/opends/quicksetup/util/Utils.java
@@ -1285,6 +1285,8 @@
      return INFO_PKCS11_CERTIFICATE.get();
    case PKCS12:
      return INFO_PKCS12_CERTIFICATE.get();
    case BCFKS:
        return INFO_BCFKS_CERTIFICATE.get();
    default:
      throw new IllegalStateException("Unknown certificate options type: " + ops.getCertificateType());
    }
opendj-server-legacy/src/main/java/org/opends/server/tools/ConfigureDS.java
@@ -188,6 +188,7 @@
      + "ds-cfg-trust-store-type: JCEKS" + NEW_LINE
      + "ds-cfg-trust-store-file: config/truststore" + NEW_LINE;
  private static final String DN_ADMIN_TRUST_MANAGER = "cn=Administration,cn=Trust Manager Providers," + DN_CONFIG_ROOT;
  private static final String DN_ADMIN_KEY_MANAGER = "cn=Administration,cn=Key Manager Providers," + DN_CONFIG_ROOT;
  /** The DN of the configuration entry defining the LDAP connection handler. */
@@ -881,9 +882,6 @@
      putKeyManagerConfigAttribute(enableStartTLS, DN_LDAP_CONNECTION_HANDLER);
      putKeyManagerConfigAttribute(ldapsPort, DN_LDAPS_CONNECTION_HANDLER);
      putKeyManagerConfigAttribute(ldapsPort, DN_HTTP_CONNECTION_HANDLER);
      if (StaticUtils.isFips()) {
          putAdminKeyManagerConfigAttribute(ldapsPort, DN_ADMIN_KEY_MANAGER);
      }
      if (keyManagerPath.isPresent())
      {
@@ -900,6 +898,10 @@
          throw new ConfigureDSException(e, LocalizableMessage.raw(e.toString()));
        }
      }
      if (StaticUtils.isFips()) {
          putAdminKeyManagerConfigAttribute(keyManagerProviderDN, DN_ADMIN_KEY_MANAGER);
      }
    }
  }
@@ -923,13 +925,33 @@
    }
  }
  private void putAdminKeyManagerConfigAttribute(final Argument arg, final String attributeDN)
  private void putAdminKeyManagerConfigAttribute(final Argument keyManagerProviderDN, final String attributeDN)
      throws ConfigureDSException
  {
    if (arg.isPresent())
    if (keyManagerProviderDN.isPresent())
    {
      try
      {
        boolean isBcfks = keyManagerProviderDN.getValue().toLowerCase().startsWith("cn=bcfks");
        if (isBcfks) {
            updateConfigEntryWithAttribute(
                    attributeDN,
                    ATTR_KEYSTORE_TYPE,
                    CoreSchema.getDirectoryStringSyntax(),
                    "BCFKS");
            updateConfigEntryWithAttribute(
                      attributeDN,
                      ATTR_KEYSTORE_FILE,
                      CoreSchema.getDirectoryStringSyntax(),
                      keyManagerPath.getValue());
            updateConfigEntryWithAttribute(
                    attributeDN,
                    ATTR_KEYSTORE_PIN_FILE,
                    CoreSchema.getDirectoryStringSyntax(),
                    "config/keystore.pin");
        } else {
        updateConfigEntryByRemovingAttribute(attributeDN, ATTR_KEYSTORE_TYPE);
        updateConfigEntryByRemovingAttribute(attributeDN, ATTR_KEYSTORE_FILE);
@@ -949,6 +971,7 @@
                CoreSchema.getDirectoryStringSyntax(),
                "config/keystore.pin");
      }
      }
      catch (final Exception e)
      {
        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_KEYMANAGER_REFERENCE.get(e));
@@ -996,6 +1019,10 @@
      removeSSLCertNicknameAttribute(DN_HTTP_CONNECTION_HANDLER);
      removeSSLCertNicknameAttribute(DN_JMX_CONNECTION_HANDLER);
    }
    if (StaticUtils.isFips()) {
        putAdminTrustManagerConfigAttribute(trustManagerProviderDN, DN_ADMIN_TRUST_MANAGER);
    }
  }
  private void putTrustManagerAttribute(final Argument arg, final String attributeDN) throws ConfigureDSException
@@ -1017,6 +1044,41 @@
    }
  }
  private void putAdminTrustManagerConfigAttribute(final Argument trustManagerProviderDN, final String attributeDN)
      throws ConfigureDSException
  {
    if (keyManagerProviderDN.isPresent())
    {
      try
      {
        boolean isBcfks = keyManagerProviderDN.getValue().toLowerCase().startsWith("cn=bcfks");
        if (isBcfks) {
            updateConfigEntryWithAttribute(
                    attributeDN,
                    ATTR_TRUSTSTORE_TYPE,
                    CoreSchema.getDirectoryStringSyntax(),
                    "BCFKS");
            updateConfigEntryWithAttribute(
                      attributeDN,
                      ATTR_TRUSTSTORE_FILE,
                      CoreSchema.getDirectoryStringSyntax(),
                      keyManagerPath.getValue());
            updateConfigEntryWithAttribute(
                    attributeDN,
                    ATTR_TRUSTSTORE_PIN_FILE,
                    CoreSchema.getDirectoryStringSyntax(),
                    "config/keystore.pin");
        }
      }
      catch (final Exception e)
      {
        throw new ConfigureDSException(e, ERR_CONFIGDS_CANNOT_UPDATE_TRUSTMANAGER_REFERENCE.get(e));
      }
    }
  }
  private void updateCertNicknameEntry(final Argument arg, final String attributeDN,
      final String attrName, final List<String> attrValues) throws ConfigureDSException
  {
opendj-server-legacy/src/main/java/org/opends/server/tools/InstallDS.java
@@ -820,6 +820,11 @@
      certType = SecurityOptions.CertificateType.PKCS12;
      pathToCertificat = argParser.usePkcs12Arg.getValue();
    }
    else if (argParser.useBcfksArg.isPresent())
    {
      certType = SecurityOptions.CertificateType.BCFKS;
      pathToCertificat = argParser.useBcfksArg.getValue();
    }
    else
    {
      certType = SecurityOptions.CertificateType.NO_CERTIFICATE;
@@ -1592,6 +1597,12 @@
        createSecurityOptionsPrompting(SecurityOptions.CertificateType.PKCS11,
            enableSSL, enableStartTLS, ldapsPort);
    }
    else if (argParser.useBcfksArg.isPresent())
    {
      securityOptions =
        createSecurityOptionsPrompting(SecurityOptions.CertificateType.BCFKS,
            enableSSL, enableStartTLS, ldapsPort);
    }
    else if (!enableSSL && !enableStartTLS)
    {
      // If the user did not want to enable SSL or start TLS do not ask
@@ -1605,13 +1616,15 @@
      final int JCEKS = 3;
      final int PKCS12 = 4;
      final int PKCS11 = 5;
      final int[] indexes = {SELF_SIGNED, JKS, JCEKS, PKCS12, PKCS11};
      final int BCFKS = 6;
      final int[] indexes = {SELF_SIGNED, JKS, JCEKS, PKCS12, PKCS11, BCFKS};
      final LocalizableMessage[] msgs = {
          INFO_INSTALLDS_CERT_OPTION_SELF_SIGNED.get(),
          INFO_INSTALLDS_CERT_OPTION_JKS.get(),
          INFO_INSTALLDS_CERT_OPTION_JCEKS.get(),
          INFO_INSTALLDS_CERT_OPTION_PKCS12.get(),
          INFO_INSTALLDS_CERT_OPTION_PKCS11.get()
          INFO_INSTALLDS_CERT_OPTION_PKCS11.get(),
          INFO_INSTALLDS_CERT_OPTION_BCFKS.get()
      };
      final MenuBuilder<Integer> builder = new MenuBuilder<>(this);
@@ -1647,6 +1660,10 @@
          builder.setDefault(LocalizableMessage.raw(String.valueOf(PKCS12)),
              MenuResult.success(PKCS12));
          break;
        case BCFKS:
            builder.setDefault(LocalizableMessage.raw(String.valueOf(BCFKS)),
                MenuResult.success(BCFKS));
            break;
        default:
          builder.setDefault(LocalizableMessage.raw(String.valueOf(SELF_SIGNED)),
              MenuResult.success(SELF_SIGNED));
@@ -1705,6 +1722,13 @@
              SecurityOptions.CertificateType.PKCS11, enableSSL,
              enableStartTLS, ldapsPort);
      }
      else if (certType == BCFKS)
      {
        securityOptions =
          createSecurityOptionsPrompting(
              SecurityOptions.CertificateType.BCFKS, enableSSL,
              enableStartTLS, ldapsPort);
      }
      else
      {
        throw new IllegalStateException("Unexpected cert type: "+ certType);
@@ -1852,6 +1876,13 @@
              pwd);
          break;
          case BCFKS:
          certManager = new CertificateManager(
              path,
              CertificateManager.KEY_STORE_TYPE_BCFKS,
              pwd);
          break;
          default:
            throw new IllegalArgumentException("Invalid type: "+type);
        }
@@ -1873,6 +1904,9 @@
          case PKCS11:
            errorMessages.add(INFO_PKCS11_KEYSTORE_DOES_NOT_EXIST.get());
            break;
          case BCFKS:
              errorMessages.add(INFO_BCFKS_KEYSTORE_DOES_NOT_EXIST.get());
              break;
          default:
            throw new IllegalArgumentException("Invalid type: "+type);
          }
@@ -2000,6 +2034,15 @@
      }
      pathPrompt = INFO_INSTALLDS_PROMPT_PKCS12_PATH.get();
      break;
    case BCFKS:
        path = argParser.useBcfksArg.getValue();
        defaultPathValue = argParser.useBcfksArg.getValue();
        if (defaultPathValue == null)
        {
          defaultPathValue = lastResetKeyStorePath;
        }
        pathPrompt = INFO_INSTALLDS_PROMPT_BCFKS_PATH.get();
        break;
    default:
      throw new IllegalStateException(
          "Called promptIfRequiredCertificate with invalid type: "+type);
@@ -2095,6 +2138,9 @@
          certNicknames);
    case PKCS11:
      return SecurityOptions.createPKCS11CertificateOptions(pwd, enableSSL, enableStartTLS, ldapsPort, certNicknames);
    case BCFKS:
        return SecurityOptions.createBCFKSCertificateOptions(path, pwd, enableSSL, enableStartTLS, ldapsPort,
            certNicknames);
    default:
      throw new IllegalStateException("Called createSecurityOptionsPrompting with invalid type: " + type);
    }
opendj-server-legacy/src/main/java/org/opends/server/tools/InstallDSArgumentParser.java
@@ -79,6 +79,7 @@
  BooleanArgument   generateSelfSignedCertificateArg;
  StringArgument    hostNameArg;
  BooleanArgument   usePkcs11Arg;
  StringArgument   useBcfksArg;
  private FileBasedArgument directoryManagerPwdFileArg;
  private FileBasedArgument keyStorePasswordFileArg;
  IntegerArgument   ldapPortArg;
@@ -342,6 +343,13 @@
                    .buildArgument();
    addArgument(usePkcs11Arg);
    useBcfksArg =
            StringArgument.builder("useBcfksKeystore")
                    .description(INFO_INSTALLDS_DESCRIPTION_USE_BCFKS.get())
                    .valuePlaceholder(INFO_KEYSTOREPATH_PLACEHOLDER.get())
                    .buildArgument();
    addArgument(useBcfksArg);
    useJavaKeyStoreArg =
            StringArgument.builder("useJavaKeystore")
                    .description(INFO_INSTALLDS_DESCRIPTION_USE_JAVAKEYSTORE.get())
@@ -611,6 +619,10 @@
    {
      certificateType++;
    }
    if (useBcfksArg.isPresent())
    {
      certificateType++;
    }
    if (certificateType > 1)
    {
opendj-server-legacy/src/main/java/org/opends/server/tools/SSLConnectionFactory.java
@@ -40,6 +40,7 @@
import org.opends.server.extensions.BlindTrustManagerProvider;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.SSLContextBuilder;
import org.forgerock.opendj.ldap.TrustManagers;
import org.opends.server.util.CollectionUtils;
import org.opends.server.util.ExpirationCheckTrustManager;
import org.opends.server.util.SelectableCertificateKeyManager;
@@ -120,7 +121,12 @@
            new BlindTrustManagerProvider();
        trustManagers = blindTrustProvider.getTrustManagers();
      } else if (trustStorePath == null) {
            if (isFips()) {
                TrustManager tm = TrustManagers.checkUsingPkcs11TrustStore();
                trustManagers = new TrustManager[] { tm };
            } else {
        trustManagers = PromptTrustManager.getTrustManagers();
            }
      } else
      {
        TrustManager[] tmpTrustManagers =
opendj-server-legacy/src/main/java/org/opends/server/util/CertificateManager.java
@@ -64,6 +64,11 @@
  public static final String KEY_STORE_TYPE_PKCS12 = "PKCS12";
  /**
   * The key store type value that should be used for the "BCFKS" key store.
   */
  public static final String KEY_STORE_TYPE_BCFKS = "BCFKS";
  /**
   * The key store path value that must be used in conjunction with the PKCS11
   * key store type.
   */
@@ -157,7 +162,7 @@
      }
    } else if (keyStoreType.equals(KEY_STORE_TYPE_JKS) ||
        keyStoreType.equals(KEY_STORE_TYPE_JCEKS) ||
        keyStoreType.equals(KEY_STORE_TYPE_PKCS12)) {
        keyStoreType.equals(KEY_STORE_TYPE_PKCS12) || keyStoreType.equals(KEY_STORE_TYPE_BCFKS)) {
      File keyStoreFile = new File(keyStorePath);
      if (keyStoreFile.exists()) {
        if (! keyStoreFile.isFile()) {
@@ -174,7 +179,7 @@
    } else {
      LocalizableMessage msg =  ERR_CERTMGR_INVALID_STORETYPE.get(
          KEY_STORE_TYPE_JKS, KEY_STORE_TYPE_JCEKS,
          KEY_STORE_TYPE_PKCS11, KEY_STORE_TYPE_PKCS12);
          KEY_STORE_TYPE_PKCS11, KEY_STORE_TYPE_PKCS12, KEY_STORE_TYPE_BCFKS);
      throw new IllegalArgumentException(msg.toString());
    }
    this.keyStorePath = keyStorePath;
@@ -377,7 +382,8 @@
      FileInputStream keyStoreInputStream = null;
      if (keyStoreType.equals(KEY_STORE_TYPE_JKS) ||
          keyStoreType.equals(KEY_STORE_TYPE_JCEKS) ||
          keyStoreType.equals(KEY_STORE_TYPE_PKCS12))
          keyStoreType.equals(KEY_STORE_TYPE_PKCS12) ||
          keyStoreType.equals(KEY_STORE_TYPE_BCFKS))
      {
          final File keyStoreFile = new File(keyStorePath);
          if (! keyStoreFile.exists())
opendj-server-legacy/src/messages/org/opends/messages/quickSetup.properties
@@ -506,6 +506,13 @@
INFO_PKCS12_KEYSTORE_DOES_NOT_EXIST=No certificates for the PCKS#12 key store \
 could be found. Check that the provided path and PIN are valid and that \
 the key store contains certificates.
INFO_BCFKS_CERTIFICATE=Use existing BCFKS File
INFO_BCFKS_CERTIFICATE_LABEL=BCFKS File
INFO_BCFKS_CERTIFICATE_TOOLTIP=Select this option if you have a BCFKS \
 certificate.
INFO_BCFKS_KEYSTORE_DOES_NOT_EXIST=No certificates for the BCFKS key store \
 could be found. Check that the provided path and PIN are valid and that \
 the key store contains certificates.
INFO_PREVIOUS_BUTTON_LABEL=< Previous
INFO_PREVIOUS_BUTTON_TOOLTIP=Go to Previous Step
INFO_PROGRESS_CANCELING=Canceling
opendj-server-legacy/src/messages/org/opends/messages/tool.properties
@@ -1785,6 +1785,7 @@
INFO_INSTALLDS_ENABLE_STARTTLS_1382=Do you want to enable Start TLS?
INFO_INSTALLDS_PROMPT_JKS_PATH_1383=Java Key Store (JKS) path:
INFO_INSTALLDS_PROMPT_PKCS12_PATH_1384=PKCS#12 key Store path:
INFO_INSTALLDS_PROMPT_BCFKS_PATH_11002=BCFKS key Store path:
INFO_INSTALLDS_PROMPT_KEYSTORE_PASSWORD_1385=Key store PIN:
INFO_INSTALLDS_PROMPT_CERTNICKNAME_1386=Use nickname %s?
INFO_INSTALLDS_HEADER_CERT_TYPE_1387=Certificate server options:
@@ -1796,6 +1797,8 @@
 a PKCS#12 key store
INFO_INSTALLDS_CERT_OPTION_PKCS11_1391=Use an existing certificate on a \
 PKCS#11 token
INFO_INSTALLDS_CERT_OPTION_BCFKS_11001=Use an existing certificate located on a \
 BCFKS key store
INFO_INSTALLDS_PROMPT_START_SERVER_1393=Do you want to start the server when \
 the configuration is completed?
ERR_INSTALLDS_CERTNICKNAME_NOT_FOUND_1394=The provided certificate \
@@ -1818,6 +1821,9 @@
INFO_INSTALLDS_DESCRIPTION_USE_PKCS11_1400=Use a certificate in a \
 PKCS#11 token that the server should use when accepting SSL-based \
 connections or performing StartTLS negotiation
INFO_INSTALLDS_DESCRIPTION_USE_BCFKS_11000=Path of a BCFKS key \
 store containing the certificate that the server should use when accepting \
 SSL-based connections or performing StartTLS negotiation
INFO_INSTALLDS_DESCRIPTION_USE_JAVAKEYSTORE_1401=Path of a Java \
 Key Store (JKS) containing a certificate to be used as the server certificate. \
 This does not apply to the administration connector, which uses \
opendj-server-legacy/src/messages/org/opends/messages/utility.properties
@@ -321,7 +321,7 @@
ERR_CERTMGR_INVALID_PARENT_274=Parent directory for key store path \
 %s does not exist or is not a directory
ERR_CERTMGR_INVALID_STORETYPE_275=Invalid key store type, it must \
be one of the following: %s, %s, %s or %s
be one of the following: %s, %s, %s, %s or %s
ERR_CERTMGR_KEYSTORE_NONEXISTANT_276=Keystore does not exist, \
it must exist to retrieve an alias, delete an alias or generate a \
certificate request