---
title: PKCS#11 hardware security module
description: DS servers support key management using a PKCS#11 token store. The PKCS#11 standard defines a cryptographic token interface, a platform-independent API for storing keys in an HSM, for example.
component: pingds
version: 7.3
page_id: pingds:security-guide:pki-hsm
canonical_url: https://docs.pingidentity.com/pingds/8.1/security-guide/pki-hsm.html
llms_txt: https://docs.pingidentity.com/pingds/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
revdate: 2025-07-07T12:28:05Z
keywords: ["Features", "LDAP", "Security", "Setup &amp; Configuration", "Standards"]
superseded_by: https://docs.pingidentity.com/pingds/8.1/security-guide/pki-hsm.html
section_ids:
  pki-hsm-prepare: Prepare the HSM
  store_keys_for_securing_connections: Store keys for securing connections
  generate_a_tls_key_pair_for_securing_connections: Generate a TLS key pair for securing connections
  pki-hsm-create-provider: Create a PKCS#11 key manager provider
  pki-hsm-use-provider: Use the PKCS#11 key manager provider
  hsm-shared-master-key: Store the shared master key
---

# PKCS#11 hardware security module

DS servers support key management using a PKCS#11 token store. The PKCS#11 standard defines a cryptographic token interface, a platform-independent API for storing keys in an HSM, for example.

DS servers rely on the PKCS#11 interface and Java APIs to use it. DS servers do not support vendor-specific interfaces.

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | DS servers use an HSM only to hold asymmetric key pairs and, optionally, CA certificates. (Since the CA certificate holds the CA's *public* key, which is not secret, ForgeRock recommends storing it in a separate, file-based keystore or PEM file, not in the HSM.)The asymmetric key pairs you can store in the HSM are the server's TLS keys, and the shared master key for the deployment.DS servers use the shared master key to wrap symmetric (secret) keys. DS servers store secret keys in the data they encrypt. Therefore, DS servers do not use the HSM for secret keys. |

Using a PKCS#11 device for storing DS keys involves:

* Storing the keys on the PKCS#11 device.

  How you generate and store keys in your HSM depends on the device. For details, refer to the documentation for your device.

* Creating the DS PKCS11 key manager provider to access the device.

  The DS server accesses a PKCS#11 device using a PIN. The PIN can be provided in the server configuration, in a separate file, or as the value of an environment variable or Java system property. The PIN must be stored as a cleartext value, so take care to protect it in production environments.

* Configuring DS components to use the key manager provider.

  For example, DS connection handlers and OAuth 2.0 authorization mechanisms requiring mutual TLS can reference the key manager provider in their configurations.

## Prepare the HSM

The examples on this page use a [SoftHSM](https://opendnssec.readthedocs.io/en/latest/softhsm/) PKCS#11 software device for evaluation, development, and testing. (Specifically, these examples depend on SoftHSM 2.4.0. The build was prepared with `./configure --with-openssl=/usr/local/opt/openssl --disable-gost --disable-p11-kit`. Your OpenSSL installation location might be different.)

Adapt the examples for use with your HSM.

The examples also use the `sun.security.pkcs11.SunPKCS11` provider implementation with SoftHSM. If you use a different Java implementation, refer to the documentation for details on how to use PKCS#11 devices with your JVM:

1. Install SoftHSM, including the configuration and the `SOFTHSM2_CONF` environment variable.

   For details, refer to the SoftHSM documentation, using the following hints:

   * Make sure you can write tokens to SoftHSM:

     ```bash
     $ cat $SOFTHSM2_CONF
     # SoftHSM v2 configuration file

     directories.tokendir = /path/to/softhsm/tokens/
     objectstore.backend = file

     # ERROR, WARNING, INFO, DEBUG
     log.level = INFO

     # If CKF_REMOVABLE_DEVICE flag should be set
     slots.removable = false

     # Enable and disable PKCS#11 mechanisms using slots.mechanisms.
     slots.mechanisms = ALL

     # If the library should reset the state on fork
     library.reset_on_fork = false
     ```

   * Keep track of the PINs that you enter when initializing the device:

     ```bash
     $ softhsm2-util --init-token --slot 0 --label "My token 1" --pin password --so-pin password
     The token has been initialized and is reassigned to slot <number>
     ```

     The user PIN is the one the DS server needs to access the device.

     The SO PIN is to reinitialize the token.

     The *\<number>* is the slot number to use in the PKCS#11 configuration.

2. Prepare the PKCS#11 configuration to generate key pairs.

   For example, to use the Java `keytool` command with the device, create a PKCS#11 configuration file that is used by the security provider implementation.

   Replace *\<number>* in with the slot number from the previous step. If you lost track of the slot number, run `softhsm2-util --show-slots` to view it again:

   ```ini
   $ cat /path/to/hsm.conf
   name = SoftHSM
   library = /usr/local/lib/softhsm/libsofthsm2.so
   slot = <number>
   attributes(generate, *, *) = {
      CKA_TOKEN = true
   }
   attributes(generate, CKO_CERTIFICATE, *) = {
      CKA_PRIVATE = false
   }
   attributes(generate, CKO_PUBLIC_KEY, *) = {
      CKA_PRIVATE = false
   }
   attributes(*, CKO_SECRET_KEY, *) = {
      CKA_PRIVATE = false
      CKA_EXTRACTABLE = false
   }
   ```

   Notes regarding the configuration file:

   * The format is described in the [Java PKCS#11 Reference Guide](https://docs.oracle.com/en/java/javase/17/security/pkcs11-reference-guide.html).

   * The `library` must point to the SoftHSM `libsofthsm2.so` library.

   * The `slot` must be one obtained when initializing the device.

   * You can find configuration recommendations for production deployments in the platform documentation page, [HSM support](https://docs.pingidentity.com/platform/8/platform-guide/hsm-support.html).

3. Verify that Java can access the device using your configuration.

   The following example shows that you can use the Java `keytool` command to list the SoftHSM keys:

   ```bash
   $ keytool \
    -list \
    -keystore NONE \
    -storetype PKCS11 \
    -storepass password \
    -providerClass sun.security.pkcs11.SunPKCS11 \
    -providerArg /path/to/hsm.conf
   Keystore type: PKCS11
   Keystore provider: SunPKCS11-SoftHSM

   Your keystore contains 0 entries
   ```

## Store keys for securing connections

The examples that follow use SoftHSM to store the TLS keys for securing network connections (LDAPS, HTTPS, and so on). Adapt them to your HSM.

### Generate a TLS key pair for securing connections

This is the server key pair for securing TLS connections. It can be specific to one DS server, and does not need to be shared.

DS presents the certificate to client applications, so get it signed by a CA they trust. *This example is for evaluation only*, and uses `localhost` as the hostname and a self-signed certificate:

1. Generate a TLS key pair.

   The following example generates a key pair with the alias `ssl-key-pair`:

   ```bash
   $ keytool \
    -genkeypair \
    -alias ssl-key-pair \
    -keyalg EC \
    -groupname secp521r1 \
    -ext "san=dns:localhost" \
    -dname "CN=localhost,O=Example Corp,C=FR" \
    -keystore NONE \
    -storetype PKCS11 \
    -storepass password \
    -providerClass sun.security.pkcs11.SunPKCS11 \
    -providerArg /path/to/hsm.conf
   ```

   The keystore password is the user PIN.

2. Get the public key certificate signed.

   The following example self-signs the certificate:

   ```bash
   $ keytool \
    -selfcert \
    -alias ssl-key-pair \
    -keystore NONE \
    -storetype PKCS11 \
    -storepass password \
    -providerClass sun.security.pkcs11.SunPKCS11 \
    -providerArg /path/to/hsm.conf
   ```

   Refer to your HSM documentation for details on getting the certificate signed by a CA.

### Create a PKCS#11 key manager provider

Repeat these steps for each DS server:

1. Make the plaintext PIN available to the DS server.

   With SoftHSM, this is the user PIN set when initializing the slot where you stored the keys, `softhsm2-util --pin password`.

   The following example sets the PIN in an environment variable:

   ```bash
   $ export SOFTHSM_USER_PIN=password
   ```

   The value must be accessible every time the DS server starts.

2. Prepare the Java environment for the DS server to use the HSM configuration for PKCS#11.

   1. Add the HSM configuration for the security provider in the Java security configuration to use for DS.

      In this example, the `$JAVA_HOME/conf/security/java.security` file for the JVM defines a security provider for PKCS#11, `security.provider.13=SunPKCS11`. You must update or override that value for `security.provider.13` to add the HSM configuration file as a parameter.

      Create a one-line, local `java.security` file the overrides the value:

      ```bash
      $ cat /path/to/java.security
      security.provider.13=SunPKCS11 /path/to/hsm.conf
      ```

   2. Use the Java security configuration when starting DS.

      For example, add the configuration to the `start-ds.java-args` for the server:

      ```bash
      # Edit config/java.properties to set java.security.properties on startup:
      $ grep java.security /path/to/opendj/config/java.properties
      start-ds.java-args=-server -Djava.security.properties=/path/to/java.security

      # Restart the server so the changes take effect:
      $ stop-ds --restart
      ```

3. Create the PKCS#11 key manager provider configuration.

   The following example creates a provider for SoftHSM with the PIN from the user environment:

   ```bash
   $ dsconfig \
    create-key-manager-provider \
    --provider-name SoftHSM \
    --type pkcs11 \
    --set enabled:true \
    --set key-store-pin:"&{softhsm.user.pin}" \
    --hostname localhost \
    --port 4444 \
    --bindDN uid=admin \
    --bindPassword password \
    --usePkcs12TrustStore /path/to/opendj/config/keystore \
    --trustStorePassword:file /path/to/opendj/config/keystore.pin \
    --no-prompt
   ```

   DS key manager providers also support storing the PIN in the configuration, in a file, or in a Java property.

### Use the PKCS#11 key manager provider

1. Set a connection handler or authorization mechanism to use the PKCS#11 key manager provider.

   The following example configures the LDAPS connection handler to use the SoftHSM provider:

   ```bash
   $ dsconfig \
    set-connection-handler-prop \
    --handler-name LDAPS \
    --set listen-port:1636 \
    --set enabled:true \
    --set use-ssl:true \
    --set key-manager-provider:SoftHSM \
    --hostname localhost \
    --port 4444 \
    --bindDN uid=admin \
    --bindPassword password \
    --usePkcs12TrustStore /path/to/opendj/config/keystore \
    --trustStorePassword:file /path/to/opendj/config/keystore.pin \
    --no-prompt
   ```

2. Verify that the secure connection negotiation works with the HSM configured:

   ```bash
   $ ldapsearch \
    --hostname localhost \
    --port 1636 \
    --useSSL \
    --baseDN dc=example,dc=com \
    "(uid=bjensen)" \
    cn

   User DN  : CN=localhost, O=Example Corp, C=FR
   Issuer   : CN=localhost, O=Example Corp, C=FR
   Validity : <validity-period>

   Do you trust this server certificate?

     1) No
     2) Yes, for this session only
     3) Yes, also add it to a truststore
     4) View certificate details

   Enter choice: [1]: 2

   dn: uid=bjensen,ou=People,dc=example,dc=com
   cn: Barbara Jensen
   cn: Babs Jensen
   ```

## Store the shared master key

* Before you start

  Set up DS servers *without the `--start` option*, and *without any data or setup profiles that create base entries or generate data*, as if you were following the instructions in [Install DS for custom cases](../install-guide/custom-replica.html).

  Do not start the DS server until you have configured it to use the shared master key in your HSM, as described below.

  The `setup` command requires a deployment ID and password. It generates a shared master key that you will discard.

  However, if you start DS with any data at all, it protects secret keys for encryption with that shared master key, and you will need to continue to use that shared master key.

  This procedure is therefore not intended for deployments where you are upgrading servers with encrypted data.

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | The shared master key is an asymmetric key pair with a self-signed certificate. Only DS uses the shared master key, and only for encrypting and decrypting secret keys. DS does not check the hostname or the validity period of the shared master key, so neither matters.When you store the shared master key in an HSM:* *The HSM must share the identical master key with all DS servers in the deployment*.

  Each server encrypts and decrypts shared secret keys with the shared master key. Without access to the same shared master key, DS servers cannot read each others' encrypted data.

  The (networked) HSM must replicate the same shared master key pair everywhere for each HSM instance that DS servers access.

* *DS servers must not rely on `cn=admin data`.*

  All the secret keys must use the DS and later security model exclusively. The procedures describing how to use an HSM for the shared master key do not apply if you have upgraded from DS 6.5 or earlier, and used encrypted data. |

1. Generate a shared master key pair in the HSM, using `RSA` as the key algorithm.

   The following example generates a key pair with the alias `master-key`:

   ```bash
   $ keytool \
    -genkeypair \
    -alias master-key \
    -keyalg RSA \
    -keysize 3072 \
    -dname "CN=Master key, O=Example.com" \
    -keystore NONE \
    -storetype PKCS11 \
    -storepass password \
    -providerClass sun.security.pkcs11.SunPKCS11 \
    -providerArg /path/to/hsm.conf
   ```

   The keystore password is the user PIN.

2. For each DS server, create the PKCS#11 key manager provider to access the HSM, as described in [Create a PKCS#11 key manager provider](#pki-hsm-create-provider), but *without starting the server*.

   For the `dsconfig create-key-manager-provider` command, replace the connection parameters with `--offline`.

3. For each DS server, update the Crypto Manager to reference the PKCS#11 key manager provider.

   For example, set the key manager provider to `SoftHSM` using the default alias for the key pair, `master-key`:

   ```bash
   $ dsconfig \
    set-crypto-manager-prop \
    --set key-manager-provider:SoftHSM \
    --offline \
    --no-prompt
   ```

4. For each DS server, apply [Setup profiles](../install-guide/setup-profiles.html) with the `setup-profile` command, and complete any necessary preliminary configuration.

   When you run DS commands, such as `setup-profile` and many others, that involve encrypting or decrypting data, make sure the Crypto Manager can access the configuration for the HSM. For example, add the Java argument `-Djava.security.properties=/path/to/java.security`, as you did for `start-ds`.

5. Start each DS server.
