Configuring IDM For a Hardware Security Module (HSM) Device

This section demonstrates how to use a PKCS #11 device, such as a hardware security module (HSM), to store the keys used to secure communications. IDM supports retrieval of secrets from HSMs either locally or over the network.

Note

On Windows systems using the 64-bit JDK, the Sun PKCS #11 provider is available only from JDK version 1.8b49 onwards. If you want to use a PKCS #11 device on Windows, either use the 32-bit version of the JDK, or upgrade your 64-bit JDK to version 1.8b49 or higher.

Setting Up the HSM Configuration

This section assumes that you have access to an HSM device (or a software emulation of an HSM device, such as SoftHSM) and that the HSM provider has been configured and initialized.

The command-line examples in this section use SoftHSM for testing purposes. Before you start, set the correct environment variable for the SoftHSM configuration, for example:

export SOFTHSM2_CONF=/usr/local/Cellar/softhsm/2.0.0/etc/softhsm2.conf

Also initialize slot 0 on the provider, with a command similar to the following:

softhsm2-util --init-token --slot 0 --label "My token 1"

This token initialization requests two PINs—an SO PIN and a user PIN. You can use the SO PIN to reinitialize the token. The user PIN is provided to IDM so that it can interact with the token. Remember the values of these PINs because you will use them later in this section.

The PKCS #11 standard uses a configuration file to interact with the HSM device. The following example shows a basic configuration file for SoftHSM:

name = softHSM
library = /usr/local/Cellar/softhsm/2.0.0/lib/softhsm/libsofthsm2.so
slot = 1
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 = true
}

Your HSM configuration file must include at least the following settings:

name

A suffix to identify the HSM provider. This example uses the softHSM provider.

library

The path to the PKCS #11 library.

slot

The slot number to use, specified as a string. Make sure that the slot you specify here has been initialized on the HSM device.

The attributes specify additional PKCS #11 attributes that are set by the HSM. For a complete list of these attributes, see the PKCS #11 Reference.

Important

If you are using the JWT Session Module, you must set CKA_EXTRACTABLE = true for secret keys in your HSM configuration file. For example:

attributes(*, CKO_SECRET_KEY, *) = {
   CKA_PRIVATE = false
   CKA_EXTRACTABLE = true
}

The HSM provider must allow secret keys to be extractable because the authentication service serializes the JWT Session Module key and passes it to the authentication framework as a base 64-encoded string.

Populating the Default Encryption Keys

When IDM first starts up, it generates a number of encryption keys required to encrypt specific data. If you are using an HSM provider, you must generate these keys manually. The secret keys must use an HMAC algorithm. The following steps set up the required encryption keys.

Note

This procedure assumes that your HSM configuration file is located at /path/to/hsm/hsm.conf:

  1. The openidm-sym-default key is the default symmetric key required to encrypt the configuration. The following command generates that key in the HSM provider. The -providerArg must point to the HSM configuration file described in "Setting Up the HSM Configuration".

    keytool \
    -genseckey \
    -alias openidm-sym-default \
    -keyalg AES \
    -keysize 128 \
    -keystore NONE \
    -storetype PKCS11 \
    -providerClass sun.security.pkcs11.SunPKCS11 \
    -providerArg /path/to/hsm/hsm.conf
    Enter keystore password: 

    Enter the password of your HSM device. If you are using SoftHSM, enter your user PIN as the keystore password. The remaining sample steps use user PIN as the password.

  2. The openidm-selfservice-key is used by the Self-Service UI to encrypt managed user passwords and other sensitive data. Generate that key with a command similar to the following:

    keytool \
    -genseckey \
    -alias openidm-selfservice-key \
    -keyalg AES \
    -keysize 128 \
    -keystore NONE \
    -storetype PKCS11 \
    -providerClass sun.security.pkcs11.SunPKCS11 \
    -providerArg /path/to/hsm/hsm.conf
    Enter keystore password: user PIN

    Enter the password of your HSM device. If you are using SoftHSM, enter your user PIN as the keystore password.

  3. The openidm-jwtsessionhmac-key is used by the JWT session module to encrypt JWT session cookies. For more information, see "JWT_SESSION". Generate the JWT session module key with a command similar to the following:

    keytool \
    -genseckey \
    -alias openidm-jwtsessionhmac-key \
    -keyalg HmacSHA256 \
    -keysize 2048 \
    -keystore NONE \
    -storetype PKCS11 \
    -providerClass sun.security.pkcs11.SunPKCS11 \
    -providerArg /path/to/hsm/hsm.conf
    Enter keystore password: user PIN
  4. The openidm-localhost certificate is used to support SSL/TLS. Generate that certificate with a command similar to the following:

    keytool \
    -genkey \
    -alias openidm-localhost \
    -keyalg RSA \
    -keysize 2048 \
    -keystore NONE \
    -storetype PKCS11 \
    -providerClass sun.security.pkcs11.SunPKCS11 \
    -providerArg /path/to/hsm/hsm.conf
    Enter keystore password: user PIN
    What is your first and last name?
      [Unknown]:  localhost
    What is the name of your organizational unit?
      [Unknown]:
    What is the name of your organization?
      [Unknown]:  OpenIDM Self-Signed Certificate
    What is the name of your City or Locality?
      [Unknown]:
    What is the name of your State or Province?
      [Unknown]:
    What is the two-letter country code for this unit?
      [Unknown]:
    Is CN=localhost, OU=Unknown, O=OpenIDM Self-Signed Certificate, L=Unknown, ST=Unknown, C=Unknown correct?
      [no]:  yes
  5. The selfservice certificate secures requests from the End User UI. Generate that certificate with a command similar to the following:

    keytool \
    -genkey \
    -alias selfservice \
    -keyalg RSA \
    -keysize 2048 \
    -keystore NONE \
    -storetype PKCS11 \
    -providerClass sun.security.pkcs11.SunPKCS11 \
    -providerArg /path/to/hsm/hsm.conf
    Enter keystore password: user PIN
    What is your first and last name?
      [Unknown]:  localhost
    What is the name of your organizational unit?
      [Unknown]:
    What is the name of your organization?
      [Unknown]:  OpenIDM Self Service Certificate
    What is the name of your City or Locality?
      [Unknown]:
    What is the name of your State or Province?
      [Unknown]:
    What is the two-letter country code for this unit?
      [Unknown]:
    Is CN=localhost,O=OpenIDM Self Service Certificate,OU=None,L=None,ST=None,C=None?
      [no]:  yes
  6. If you are not using the HSM provider for the truststore, you must add the certificates generated in the previous two steps to the default IDM truststore.

    If you are using the HSM provider for the truststore, you can skip this step.

    To add the openidm-localhost certificate to the IDM truststore, export the certificate from the HSM provider, then import it into the truststore, as follows:

    keytool \
    -export \
    -alias openidm-localhost \
    -file exportedCert \
    -keystore NONE \
    -storetype PKCS11 \
    -providerClass sun.security.pkcs11.SunPKCS11 \
    -providerArg /path/to/hsm/hsm.conf
    Enter keystore password: user PIN
    Certificate stored in file exportedCert
    
    keytool \
    -import \
    -alias openidm-localhost \
    -file exportedCert \
    -keystore /path/to/openidm/security/truststore
    Enter keystore password: changeit
    Owner: CN=localhost, OU=Unknown, O=OpenIDM Self-Signed Certificate, L=...
    Issuer: CN=localhost, OU=Unknown, O=OpenIDM Self-Signed Certificate, L=...
    Serial number: 5d2554bd
    Valid from: Fri Aug 19 13:11:54 SAST 2016 until: Thu Nov 17 13:11:54 SAST 2016
    Certificate fingerprints:
    	 MD5:  F1:9B:72:7F:7B:79:58:29:75:85:82:EC:79:D8:F9:8D
    	 SHA1: F0:E6:51:75:AA:CB:14:3D:C5:E2:EB:E5:7C:87:C9:15:43:19:AF:36
    	 SHA256: 27:A5:B7:0E:94:9A:32:48:0C:22:0F:BB:7E:3C:22:2A:64:B5:45:24:14:70:...
    	 Signature algorithm name: SHA256withRSA
    	 Version: 3
    
    Extensions:
    
    #1: ObjectId: 2.5.29.14 Criticality=false
    SubjectKeyIdentifier [
    KeyIdentifier [
    0000: 7B 5A 26 53 61 44 C2 5A   76 E4 38 A8 52 6F F2 89  .Z&SaD.Zv.8.Ro..
    0010: 20 04 52 EE                                         .R.
    ]
    ]
    Trust this certificate? [no]:  yes
    Certificate was added to keystore
    

    The default truststore password is changeit.

Changing the Default Keystore Password

The default keystore password is changeit. You should change this password in a production environment.

To change the default keystore password, follow these steps:

  1. Shut down the server if it is running:

    /path/to/openidm/shutdown.sh
  2. Use the keytool command to change the keystore password. The following command changes the keystore password to newPassword:

    keytool \
    -storepasswd \
    -keystore /path/to/openidm/security/keystore.jceks \
    -storetype jceks
    Enter keystore password: changeit
    New keystore password: newPassword
    Re-enter new keystore password: newPassword
  3. IDM uses a number of encryption keys by default, listed in "Mapping SecretIDs to Key Aliases". The passwords of each of these keys must match the password of the keystore.

    To obtain a list of the keys in the keystore, run the following command:

    keytool \
    -list \
    -keystore /path/to/openidm/security/keystore.jceks \
    -storetype jceks\
    -storepass newPassword
    Keystore type: JCEKS
    Keystore provider: SunJCE
    
    Your keystore contains 5 entries
    
    openidm-sym-default, Nov 5, 2019, SecretKeyEntry,
    openidm-jwtsessionhmac-key, Nov 5, 2019, SecretKeyEntry,
    selfservice, Nov 5, 2019, PrivateKeyEntry,
    Certificate fingerprint (SHA-256): E9:0B:BA:FB:58:73:...:7B
    openidm-selfservice-key, Nov 5, 2019, SecretKeyEntry,
    openidm-localhost, Nov 5, 2019, PrivateKeyEntry,
    Certificate fingerprint (SHA-256): 21:50:6C:90:C7:A7:...:1B

    Change the passwords of each of the default encryption keys as follows:

    keytool \
    -keypasswd \
    -alias openidm-localhost \
    -keystore /path/to/openidm/security/keystore.jceks \
    -storetype jceks \
    -storepass newPassword
    Enter key password for <openidm-localhost> changeit
    New key password for <openidm-localhost>: newPassword
    Re-enter new key password for <openidm-localhost>: newPassword
    
    keytool \
    -keypasswd \
    -alias openidm-sym-default \
    -keystore /path/to/openidm/security/keystore.jceks \
    -storetype jceks \
    -storepass newPassword
    Enter key password for <openidm-sym-default> changeit
    New key password for <openidm-sym-default>: newPassword
    Re-enter new key password for <openidm-sym-default>: newPassword
    
    keytool \
    -keypasswd \
    -alias openidm-selfservice-key \
    -keystore /path/to/openidm/security/keystore.jceks \
    -storetype jceks \
    -storepass newPassword
    Enter key password for <openidm-selfservice-key> changeit
    New key password for <openidm-selfservice-key>: newPassword
    Re-enter new key password for <openidm-selfservice-key>: newPassword
    
    keytool \
    -keypasswd \
    -alias selfservice \
    -keystore /path/to/openidm/security/keystore.jceks \
    -storetype jceks \
    -storepass newPassword
    Enter key password for <selfservice> changeit
    New key password for <selfservice>: newPassword
    Re-enter new key password for <selfservice>: newPassword
    
    keytool \
    -keypasswd \
    -alias openidm-jwtsessionhmac-key \
    -keystore /path/to/openidm/security/keystore.jceks \
    -storetype jceks \
    -storepass newPassword
    Enter key password for <openidm-jwtsessionhmac-key> changeit
    New key password for <openidm-jwtsessionhmac-key>: newPassword
    Re-enter new key password for <openidm-jwtsessionhmac-key>: newPassword
  4. In your resolver/boot.properties file, change the value of the openidm.keystore.password property to match the new password. The password is encrypted when you start up the server.

  5. If you are using the default embedded DS repository, you must also change the keystore PIN for the IDM Key Manager Provider in the DS configuration.

    Open the /path/to/openidm/db/openidm/opendj/config/config.ldif file and replace the following:

    dn: cn=OpenIDM Key Manager Provider,cn=Key Manager Providers,cn=config
    ...
    ds-cfg-key-store-pin: changeit

    with the new keystore password, for example:

    dn: cn=OpenIDM Key Manager Provider,cn=Key Manager Providers,cn=config
    ...
    ds-cfg-key-store-pin: newPassword

    Note

    This step leaves the keystore password in clear text in the DS configuration file. This should be acceptable for testing purposes. The embedded DS repository is not supported in a production environment.

  6. Restart the server.

    /path/to/openidm/startup.sh

Important

Repeat this procedure on each node if you run multiple nodes in a cluster to ensure that the new password is present on all nodes.

Configuring IDM to Support an HSM Provider

To enable IDM to use an HSM provider, make the following configuration changes:

In your secret store configuration (conf/secrets.json)

Change the mainKeyStore and mainTrustStore to reference the HSM. For example:

{
  "stores": [
    {
      "name": "mainKeyStore",
      "class": "org.forgerock.openidm.secrets.config.HsmBasedStore",
      "config": {
        "storetype": "&{openidm.keystore.type|PKCS11}",
        "providerName": "&{openidm.keystore.provider|SunPKCS11-softHSM}",
        "storePassword": "&{openidm.keystore.password|changeit}",
        "mappings": [
          {
            "secretId" : "idm.default",
            "types": [ "ENCRYPT", "DECRYPT" ],
            "aliases": [ "&{openidm.config.crypto.alias|openidm-sym-default}" ]
          },
          {
            "secretId" : "idm.config.encryption",
            "types": [ "ENCRYPT", "DECRYPT" ],
            "aliases": [ "&{openidm.config.crypto.alias|openidm-sym-default}" ]
          },
          {
            "secretId" : "idm.password.encryption",
            "types": [ "ENCRYPT", "DECRYPT" ],
            "aliases": [ "&{openidm.config.crypto.alias|openidm-sym-default}" ]
          },
          {
            "secretId" : "idm.jwt.session.module.encryption",
            "types": [ "ENCRYPT", "DECRYPT" ],
            "aliases": [ "&{openidm.https.keystore.cert.alias|openidm-localhost}" ]
          },
          {
            "secretId" : "idm.jwt.session.module.signing",
            "types": [ "SIGN", "VERIFY" ],
            "aliases": [ "&{openidm.config.crypto.jwtsession.hmackey.alias|openidm-jwtsessionhmac-key}" ]
          },
          {
            "secretId" : "idm.selfservice.signing",
            "types": [ "SIGN", "VERIFY" ],
            "aliases": [ "selfservice" ]
          },
          {
            "secretId" : "idm.selfservice.encryption",
            "types": [ "ENCRYPT", "DECRYPT" ],
            "aliases": [ "&{openidm.config.crypto.selfservice.sharedkey.alias|openidm-selfservice-key}" ]
          }
        ]
      }
    },
    {
      "name": "mainTrustStore",
      "class": "org.forgerock.openidm.secrets.config.HsmBasedStore",
      "config": {
        "storetype": "&{openidm.keystore.type|PKCS11}",
        "providerName": "&{openidm.keystore.provider|SunPKCS11-softHSM}",
        "storePassword": "&{openidm.keystore.password|changeit}",
        "mappings": [
        ]
      }
    }
  ],
  "populateDefaults": false
}

Note

The "populateDefaults": false turns off the default key generation. This setting is required for an HSM key provider.

In the IDM Java security file (conf/java.security)

Specify the location of your PKCS #11 configuration file. For example:

security.provider.14=SunPKCS11 /path/to/pkc11/config/pkcs11.conf

Templates for the pkcs11.conf file are included in your PKCS package.

You should now be able to start IDM with the keys in the HSM provider.

Read a different version of :