Hardware Security Modules (HSM)

EJBCA has support for several Hardware Security Modules (HSMs) and each HSM has its own specific interface for key generation and maintenance, independent of EJBCA. Make sure you are familiar with how your HSM works.

This section provides information on Hardware Security Modules (HSMs) in the following sections:

HSM modules available in the Admin GUI

As of EJBCA 6.0, you can manage crypto tokens fully in the Admin GUI or CLI. The Admin GUI automatically shows you the HSMs available in your system.

When creating a new Crypto Token (Crypto Tokens>Create New) you can select between Soft and PKCS#11 crypto tokens.

  • The PKCS#11 option is only available if EJBCA is able to find any known PKCS#11 modules in the file system.

If EJBCA finds known PKCS#11 modules in the file system, you can select PKCS#11 as Type. As PKCS#11 Library there is a list of the available known HSMs found in the file system.

If the PKCS#11 option is not available or your desired HSM is not in the list of available Libraries, there are a few options to configure:

  • If you are using JBoss 7 you must make the java PKCS#11 classes exportable. For more information, see Application Servers.

  • You can configure PKCS#11 modules that are not already known to EJBCA in conf/web.properties. See conf/web.properties.sample how to add new known modules and override existing (overriding should not be needed since you can add new locations with the same name).

For more information on creating and using Crypto Tokens for HSMs, see Managing Crypto Tokens and Managing CAs.

The following sections describe the underlying operations and technical features of using HSMs and PKCS#11.

Configuring HSMs

The GUI configuration of CAs is backed by a properties field where properties unique to a particular CAs usage of the HSM is specified. All implemented HSM modules are using the same property keywords to define the identity and the purpose of the keys to be used. These keywords are:

  • certSignKey: Key used when signing certificates, can be RSA or ECDSA.

  • crlSignKey: Key used when signing CLSs, can be RSA or ECDSA.

  • keyEncryptKey: Key used for key encryption and decryption, this must be an RSA key.

  • testKey: Key used by HSM status checks, can be RSA or ECDSA.

  • hardTokenEncrypt: Key used for hardtoken encryption and decryption. PUK will be decrypted by this key.

  • defaultKey: Key used when no other key is defined for a purpose. If this is the only definition, then this key will be used for all purposes.

  • pin: Optional pin code used for auto-activation of CA token, see below. Not recommended for high security set-ups, but very useful in some cases.

You may omit defaultKey if you want to be sure that the right key is used, but then all the other keys must be specified. It is recommended that the certificate and CRL signing keys are linked to the same key since different keys are rarely supported by verifying applications.

When implementing support for a new HSM the KeyStrings class could be used to manage the key properties described above. When it is an JCA/JCE API for the HSM it could also be wise to extend the BaseCAToken class.

The same activation code must be used for all keys used by a CA.

There are four additional key properties that can (optionally) be used when renewing CA keys and to produce roll-over certificates. Some of these (in particular the next keys) are only used when using API methods (such as WS).

  • previousCertSignKey : Alias of the previous signature key, as opposed to certSignKey which is the current signature key.

  • previousSequence: Sequence identifying the previous signature key, as opposed to the current sequence that is held in the CA token. This sequence will replace the current sequence in the caRef field when signing a request with the CAs previous key.

  • nextCertSigningKey: Alias of a new generated key on the HSM. When updating a CA signed by an external CA this is used to send a request, but the CA is still active using the old key. When the certificate response is received this key is activate and moved to certSignKey/crlSignKey.

  • nextSequence: Sequence identifying the next signature key.

Supported and tested HSMs are described below, with sample configurations and HSM specific documentation.

As of EJBCA 3.6, the recommended HSM connector to use the PKCS#11 interface. Older JCE implementations are deprecated and removed. Contact PrimeKey if you need to migrate.

Testing PKCS#11 keys for use by EJBCA

To test keys on the HSM for use by EJBCA, you can use the EJBCA Client Toolbox.

ant clientToolBox
cd dist/clientToolBox
./ejbcaClientToolBox.sh PKCS11HSMKeyTool test

The command gives further instructions about the parameters required, PKCS#11 library and slot.

Auto-activation of Crypto Tokens

The pin property is used to be able to automatically activate a CA token. The activation code may be specified in the property field with the keyword pin. If this property is not specified, then the CA has to be manually activated after each restart or re-deployment of EJBCA. Manual activation is done in the Admin GUI under Basic Functions > View Information or using the cli bin/ejbca.sh ca activateca.

The pin property can use a clear text password or an encrypted one.

pin foo123
pin 6bc841b2745e2c95e042a68b4777b34c

These two properties contains the same password. The obfuscated pin value can be obtained with the command bin/ejbca.sh encryptpwd:

$ bin/ejbca.sh encryptpwd foo123
Using JBoss JNDI provider...
Please note that this encryption does not provide absolute security, ....
Enter word to encrypt:
Encrypting pwd...

This encrypted password is not a high security encryption. If the password.encryption.key property has not been customized it will not provide more security than just preventing accidental viewing since an EJBCA built-in encryption key is used. If an attacker gets hold of the encrypted password and the password.encryption.key has not been customized, the password can be decrypted using the source code of EJBCA


Support for DSA or ECDSA in HSMs are dependant on the support for the algorithms in the HSM. You have to check if that support is available.

For more information on HSMs and ECDSA, see ECDSA Keys and Signatures.

Generic PKCS#11 provider

A PKCS#11 wrapper has been used to implement support for tokens with PKCS#11 libraries. The PKCS#11 provider have been tested with Utimaco CryptoServer and nCipher nShield/netHSM and SafeNet ProtectServer and SafeNet Luna and AEP Keyper and ARX CoSign and Bull TrustWay.

Besides the keys previously described the Crypto Token property field (matching with user friendly values of the Crypto Token in the Administration GUI) should contain the following properties:

  • sharedLibrary: Path to the HSM PKCS#11 library (/etc/utimaco/libcs2_pkcs11.so, /usr/safenet/lunaclient/lib/libCryptoki2_64.so etc)

  • slotLabelType: Type of slot reference, see below

  • slotLabelValue: Value of the slot reference (1, myslot etc).

The slot label type can be one of the following

  • SLOT_NUMBER: ny positive integer, can be used to refer to slots in any HSM with consecutive slot numbering.

  • SLOT_INDEX: Any positive integer, prefaced by an 'i'.

  • SLOT_LABEL: The PKCS#11 standard allows for using strings for labeling slots. This label may also be an integer or an 'i' followed by an integer (like a number or an index)

  • SUN_FILE: The slot specified by a SUN config file. The slot label can be left blank.

Optionally a few extra properties fields can be used:

  • attributesFile: A file specifying PKCS#11 attributes (used mainly for key generation).

  • keyspec: Key specification used when generating new HSM keys from within the admin GUI. Keyspec that is used as first choice when generating new keys in the GUI of form "1024" for RSA keys, "DSA1024" for DSA keys and secp256r1 for EC keys. If keyspec is not given EJBCA tries to generate a key with the same specification as the current cert signing key.

An attributes file is in the format specified in the JavaTM PKCS#11 Reference Guide and the examples further down in this file.

Prior to EJBCA 3.11 there were no default attributes used when no attributesFile existed. Now there is a built in default configuration used when no attributesFile is specified. Unless you have some strange HSM not working well with the defaults(see below) you should NOT use an attributesFile. Below is an example of an 'attributesFile' (that should not be used) which will give generated keys same attribute values as the default:

attributes(*, CKO_PUBLIC_KEY, *) = {
CKA_TOKEN = false
CKA_WRAP = true
attributes(*, CKO_PRIVATE_KEY, *) = {
CKA_TOKEN = true
CKA_SIGN = true
CKA_DERIVE = false
disabledMechanisms = {

The only known occasion where the default is not working is when the module protected slot of a Thales/nCipher HSM is used; then the file must exist and have CKA_PRIVATE = false (see below).

The default attributes that are applied to each key generated by EJBCA will assure that:

  • All needed operations could be done.

  • The private part of the key is stored in the HSM but not the public part (which is in a certificate that is stored on the HSM).

  • It will be impossible to read the private part of the key from the HSM.

The default configuration will also disable some signing mechanisms. The disabled mechanisms are for signing when the data to be signed is hashed by PKCS#11 before using the private key in the HSM. When these mechanism are disabled the sun PKCS#11 wrapper provider will do the hashing instead of the of the HSM. This will speed up the signing in most cases, especially when your HSM is on another host. This will not have any security impacts since no secret in the HSM is used for the hashing.

However it will be possible not disable these hash/signing mechanisms, see the PKCS#11 section of '$EJBCA_HOME/conf/cesecore.properties'. You could try not to disable the mechanisms if you get the error CKR_FUNCTION_NOT_SUPPORTED (0x54) from PKCS#11 when signing.

If you are using an attributesFile and have more than one CA using the same slot it is very important that BOTH CA token properties configurations contains the attributesFile. This is because the attributes are applied when the provider is installed during startup. If one configuration does not have the attributesFile it can not be applied later on by the other configuration.

The tool EJBCA_HOME/dist/clientToolBox/ejbcaClientToolBox.sh PKCS11HSMKeyTool is used administrate and generate keys. Use it without parameters to get all valid options. Keys may be generated in two ways. Examples:

dist/clientToolBox/ejbcaClientToolBox.sh PKCS11HSMKeyTool generate hsmp11.so 2048 defaultKey 1
dist/clientToolBox/ejbcaClientToolBox.sh PKCS11HSMKeyTool generate hsmp11.conf 2048 defaultKey

The first example is using built in default and are then using specified slot and PKCS#11 library. The second is using a configuration file. The contents of the file is specified in the PKCS#11 wrapper documentation from Oracle. Often it is enough to use the default but with some HSM it necessary to define some PKCS#11 attributes for the generated key.

All keys to be used has to be generated before the application server is started.

Generated HSM objects

EJBCA needs (via the Java PKCS#11 provider) two object on the HSM, which are all generated by the generate commands above:

  • A private key

  • A certificate - this is simply a holder of the public key used by java, and not the real certificate of a CA

A java keystore entry has no reference to a publickey pkcs#11 object, just a private key object and a certificate object, hence the public key object is not needed after the certificate object has been written to the keystore. By setting the CKA_TOKEN attribute to false for the public key its object will not be stored on the HSM. If CKA_TOKEN is true then all public keys will be on the HSM forever since no public key is deleted when a private key is deleted from the keystore. So in order not to waste memory on the HSM CKA_TOKEN must be false for the public key.

When generating keys with clientToolBox each private key have the CKA_LABEL attribute set to the alias of the key prefixed with priv-. But when generating a key in ejba there will normally not be a CKA_LABEL for the private key. If you want to have a label even when the key is generated by ejbca you got to use an attribute file with a CKA_LABEL definition in your configuration. The value of the attribute is a hexadecimal string starting with "0h". These labels are normally seen only when you use the native HSM tools to list and manipulate objects.

The above example would then include:

attributes(*,CKO_PRIVATE_KEY,*) = {
CKA_LABEL = 0h6b657931

The example above gives the label key1 to the private key. You can give any label by simply looking up the hex codes of characters in the ascii table.

Utimaco CryptoServer

The Utimaco PKCS11 module have a configurable timeout (AppTimeout) that clears all session information if you do not use the keys for some time. The default time-out is 30 minutes, which may be way too short if your CA is not very very active. We recommend that you set this timeout to a longer value, several days. Put a configuration file in /etc/utimaco/cs2_pkcs11.ini:

Timeout = 5000
Logging = 0
Logpath = /tmp
Device = TCP:3001@
Timeout = 600000
AppTimeout = 172800
SlotCount = 100

The timeout in this example of 172800 seconds will allow your CA to idle for a long time.

When using a PKCS#11 token you should first create keys with the command: $EJBCA_HOME/dist/clientToolBox/ejbcaClientToolBox.sh PKCS11HSMKeyTool generate

Each CA should have its own slot.

Each slot must have been initialized before keys could be generated on the them. This includes setting a user PIN for it. The slot must also require login. Tools for doing this is not provided from EJBCA. The HSM vendor should provide this tool.

Here follows an example on how to initialize a slot and generate keys to be used by EJBCA. The password is user1:

./p11tool Slot=1 InitToken=officer1
./p11tool Slot=1 Label=CVCA LoginSO=officer1 InitPin=user1
$EJBCA_HOME/dist/clientToolBox/ejbcaClientToolBox.sh PKCS11HSMKeyTool generate ./libcs2_pkcs11.so 4096 signKey 1
PKCS11 Token [SunPKCS11-libcs2_pkcs11.so-slot1] Password:
Creating certificate with entry signKey.
$EJBCA_HOME/dist/clientToolBox/ejbcaClientToolBox.sh PKCS11HSMKeyTool generate ./libcs2_pkcs11.so 2048 defaultKey 1
PKCS11 Token [SunPKCS11-libcs2_pkcs11.so-slot1] Password:
Creating certificate with entry defaultKey.
$EJBCA_HOME/dist/clientToolBox/ejbcaClientToolBox.sh PKCS11HSMKeyTool generate ./libcs2_pkcs11.so 512 testKey 1
PKCS11 Token [SunPKCS11-libcs2_pkcs11.so-slot1] Password:
Creating certificate with entry testKey. 

You can view the pkcs11 objects created with the command:

./p11tool Slot=1 Login=user1 ListObjects 

This is a example of a property field when creating the CA:

defaultKey defaultKey
certSignKey signKey
crlSignKey signKey
testKey testKey
pin user1
sharedLibrary /opt/utimaco/p11/libcs2_pkcs11.so

Utimaco have an emulator for their CryptoServer LAN HSM that can be used for test and development. If you have the emulation kit there is a howto in doc/howto/cryptoserver-lan-emulator.txt with steps to follow in order to use it with EJBCA.

You can check the status of a CryptoServer LAN device, for example the emulator with:

./csadm Device=TCP:3001@ GetState

Import a PKCS#12 file in Utimaco CryptoServer

Although not recommended it is possible to import keys from a p12 file to CryptoServer. These steps were contributed by Philipp Vogt and Helmut Edlhaimb-Rexeis. The tools used are a combination of p11tool that ships with Utimaco HSMs and ejbcaClientToolBox.sh PKCS11HSMKeyTool.

  • Import the .p12 file with p11Tool from Utimaco (into slot 20 in this example). p11tool Slot=22 AuthRSASign=GenPKIAd,:cs2:cyb:/dev/ttyS0 Login=123456 ID=TestCA2XYID ImportP12=mycert.p12,1234 It is absolutely necessary to set an unique id (ID=...) at import time. The key alias for the imported key is set to X509 Certificate (taken from the imported certificate) and cannot be change at import time.

  • Rename the key alias to an unique key alias with PKCS11HSMKeyTool rename from ejbcaClientToolbox. ejbcaClientToolBox.sh PKCS11HSMKeyTool rename /etc/utimaco/libcs2_pkcs11.so 20 X509 Certificate TestCA2Key The new key alias is set to the label and the id of the CKO_CERTIFICATE and the id of the CKO_PRIVATE_KEY.

  • Optional: Delete the public key with p11Tool using Label="RSA Public Key". p11tool Slot=20 Login=123456 Label="RSA Public Key" DeleteObject

  • Test the keys, to make sure they are usable from EJBCA. ejbcaClientToolBox.sh PKCS11HSMKeyTool test ./libcs2_pkcs11.so 20 1

Make sure no other public keys using this label are present in the HSM. Even if more than one .p12 file needs to be imported only one at a time can be imported and renamed. The import and the rename process are tied together and cannot be separated.

nCipher nShield/netHSM

This subsection describes how the nShield card from nCipher is used.
First the card has to be installed and admin and operator card sets has to be created. This is described in step 1.
Step 2 describes environments variables that must be set before generating keys and installing a new CA.
Step 3-5 describe PKCS#11 keys are generated and how different CAs within an installation is configured to use these keys. In earlier versions of this manual it was also described how the nCipher JCA provider could be used by EJBCA. This has been removed since PKCS#11 keys are better in every respect.

Step 1. Install the nShield card

  1. Make sure you have all necessary software and drivers installed and created the user and group nfast. In Linux should the software be installed to /opt/nfast or the location environment variable NFAST_HOME is pointing to.

  2. Login as the nfast user: sudo su nfast

  3. Set the nCipher box to initialization mode by setting the switch to mode I.

  4. Clear the nCipher box by pressing the reset button on the device.

  5. Check that the mode is in pre-initialization mode and not in operational:

    nfast@donny:/home/lars/work$ /opt/nfast/bin/enquiry
    enquiry reply flags none
    enquiry reply level Six
    serial number 41C5-BA04-6D2C
    mode operational
    version 2.23.6
    speed index 147
    rec. queue 442..642
    level one flags Hardware HasTokens
    version string 2.23.6cam5, 2.22.6cam7 built on Apr 25 2005 18:15:46
    checked in 00000000431dca98 Tue Sep 6 18:58:00 2005
    level two flags none
    max. write size 8192
    level three flags KeyStorage
    level four flags OrderlyClearUnit HasRTC HasNVRAM HasNSOPermsCmd ServerHasPollCmds FastPollSlotList HasSEE HasKLF HasShareACL HasFeatureEnable HasFileOp HasLongJobs ServerHasLongJobs AESModuleKeys NTokenCmds LongJobsPreferred
    module type code 0
    product name nFast server
    device name
    EnquirySix version 4
    impath kx groups
    feature ctrl flags none
    features enabled none
    version serial 0
    remote server port 9004
    Module #1:
    enquiry reply flags none
    enquiry reply level Six
    serial number 41C5-BA04-6D2C
    mode pre-initialisation
    version 2.22.6
    speed index 147
    rec. queue 9..152
    level one flags Hardware HasTokens InitialisationMode PreMaintInitMode
    version string 2.22.6cam7 built on Apr 25 2005 18:15:46
    checked in 00000000426636cd Wed Apr 20 13:02:37 2005
    level two flags none
    max. write size 8192
    level three flags KeyStorage
    level four flags OrderlyClearUnit HasRTC HasNVRAM HasNSOPermsCmd ServerHasPollCmds FastPollSlotList HasSEE HasKLF HasShareACL HasFeatureEnable HasFileOp HasLongJobs ServerHasLongJobs AESModuleKeys NTokenCmds LongJobsPreferred
    module type code 6
    product name nC1002P/nC3022P
    device name #1 nFast PCI device, bus 0, slot 13.
    EnquirySix version 5
    impath kx groups DHPrime1024
    feature ctrl flags LongTerm
    features enabled StandardKM
    version serial 24
    rec. LongJobs queue 8
    SEE machine type gen1AIF 
  6. Create the security world with the command:

    $ /opt/nfast/bin/new-world -i -Q 1/1
    15:04:50 WARNING: Module #1: preemptively erasing module to see its slots!
    Create Security World:
    Module 1: 0 cards of 1 written
    Module 1 slot 0: empty
    Module 1 slot 0: unknown card
    Module 1 slot 0:- passphrase specified - overwriting card
    Card writing complete.
    security world generated on module #0; hknso = 6807e0b031c4f797b739ec33ca7dba05279cf54f

    The -Q K/N option tells how many administration cards that are created N. K of these cards will be needed to restore a module with a backup of the security world. 1/1 is a bad choice in production but will do in this example. Choose K>=3 and N>K in production.

  7. Change mode on the switch on the device to mode O.

  8. Press the Clear button again.

  9. Check with enquiry that the mode have changed to Operational
    Example on creation of operator cards:

    $ /opt/nfast/bin/createocs -m 1 -Q 2/3 -N ejbca -M -p -T 0
    Creating Cardset:
    Module 1: 0 cards of 3 written
    Module 1 slot 0: Admin Card #1
    Module 1 slot 0: empty
    Module 1 slot 0: blank card
    Module 1 slot 0:- passphrase specified - writing card (naming `EJBCA card 1')
    Module 1: 1 card of 3 written
    Module 1 slot 0: remove already-written card #1
    Module 1 slot 0: empty
    Module 1 slot 0: blank card
    Module 1 slot 0:- passphrase specified - writing card (naming `EJBCA card 2')
    Module 1: 2 cards of 3 written
    Module 1 slot 0: remove already-written card #2
    Module 1 slot 0: empty
    Module 1 slot 0: blank card
    New passphrases do not match; please try again.
    Module 1 slot 0:- passphrase specified - writing card (naming `EJBCA card 3')
    Card writing complete.
    cardset created; hkltu = 8d30f2ab5bdccacd8a4333aefed2c0ea1ff0e6db

    This will generate 3 cards of the card set named ejbca. Any 2 of these cards will be needed when generating keys and starting ejbca. Different card sets could be used for different CAs.

    The preload command (see below) must always be called as the same user unless the directory /opt/nfast/kmdata/preload is removed.
    If you get a HostDataAccessDenied error when running preload or starting JBoss, it is because the file permissions on the directory /opt/nfast/kmdata/preload is wrong. It's probably because you (sometime) ran preload as another user, such as root or nfast.

  10. Load the card set so that keys protected by the card set could be generated:

    $ /opt/nfast/bin/preload -c ejbca pause
    Loading cardsets:
    ejbca on modules 1
    Loading `ejbca':
    Module 1 slot 0: `ejbca' #3 (`EJBCA card 3')
    Module 1 slot 0:- passphrase supplied - reading card
    Module 1 slot 0: `ejbca' #3 (`EJBCA card 3'): already read
    Module 1 slot 0: empty
    Module 1 slot 0: `ejbca' #2 (`EJBCA card 2')
    Module 1 slot 0:- passphrase supplied - reading card
    Card reading complete.
    Loading complete; now pausing 

Step 2. Setup the environment
Login as the user that is running the application server. This user must be a member of the nfast group. The following environment variables should be set for this user:

  • JAVA_HOME (/usr/local/jdk1.6.0_16 or similar)

  • APPSRV_HOME (/home/jboss/jboss-5.1.0.GA or similar)

  • EJBCA_HOME (/home/jboss/ejbca or similar)

  • NFAST_HOME (/opt/nfast)

Step 3. Create PKCS#11 keys that should be used on the nShield card

  1. Start a new window and login as the same user (jboss user).

    An ECC key could not be used with preload (at least not the curve secp160r1). Such a key is generated OK and could be used as long as the current preload is running. But if all preload processes are stopped and then if then preload is restarted the key could not be used. This means that ECC could only be used with a 1/n OCS.

  2. Now 3 keys protected by the key set ejbca are created like this:

    $ ~nfast/bin/preload -c ejbca $EJBCA_HOME/dist/clientToolBox/ejbcaClientToolBox.sh PKCS11HSMKeyTool generate /opt/nfast/toolkits/pkcs11/libcknfast.so 4096 defaultRoot i1
    Executing ejbcaClientToolBox.sh PKCS11HSMKeyTool generate /opt/nfast/toolkits/pkcs11/libcknfast.so 4096 defaultRoot i1
    PKCS11 Token [SunPKCS11-NFastJava] Password:
    Creating certificate with entry default.
    $ ~nfast/bin/preload -c ejbca $EJBCA_HOME/dist/clientToolBox/ejbcaClientToolBox.sh PKCS11HSMKeyTool generate /opt/nfast/toolkits/pkcs11/libcknfast.so 2048 cryptRoot i1
    Loaded pkcs11 uc17cfc7c330e613af5709789ff823a476177e233c-d165e440baa8dc9963780c682836ba17513e8cbf key (RSAPrivate) on modules 1
    Executing ejbcaClientToolBox.sh PKCS11HSMKeyTool generate /opt/nfast/toolkits/pkcs11/libcknfast.so 2048 cryptRoot i1
    PKCS11 Token [SunPKCS11-NFastJava] Password:
    Creating certificate with entry crypt.
    $ ~nfast/bin/preload -c ejbca $EJBCA_HOME/dist/clientToolBox/ejbcaClientToolBox.sh PKCS11HSMKeyTool generate /opt/nfast/toolkits/pkcs11/libcknfast.so 1024 test i1
    Loaded pkcs11 uc17cfc7c330e613af5709789ff823a476177e233c-27cfdae84bf4298f2dde83cd00980a81bcf095bf key (RSAPrivate) on modules 1
    Executing ejbcaClientToolBox.sh PKCS11HSMKeyTool generate /opt/nfast/toolkits/pkcs11/libcknfast.so 1024 test i1
    PKCS11 Token [SunPKCS11-NFastJava] Password:
    Creating certificate with entry test

Step 4. Start EJBCA with nShield HSM
To start EJBCA, preload must be running with the required key stores loaded. In this example this was done in step 2. Preload is now used to start jboss:

$ ~nfast/bin/preload -c ejbca $APPSRV_HOME/bin/run.sh 

Step 5. Create a new CA in the web GUI of EJBCA
Choose PKCS#11 as CA Token Type.

Properties are defined according to the Generic PKCS#11 provider section above.

All preloaded operator card sets (OCSs) has it's own slot. It is not possible to predict the slot ID. But the index of the slot in the slot list is predictable. slotListIndex must therefore be used. If only one OCS is preloaded this index is always 1.

If several CAs are sharing the same OCS (and hence slot) each key (identified by a key label) may only be used for one CA but the test key. Same test key could be used for all CAs.

Example with previous generated keys where signRoot is used for CAs signing, and defaultRoot is used for everything else (encryption):

When preload is used no authentication code is needed to activate a CA. You could give any value for the authentication code when activating. The pin property could be used in the configuration to automatically activate a CA. The value of this property could be anything.

defaultKey defaultRoot
testKey test
keyEncryptKey cryptRoot
hardTokenEncrypt cryptRoot
pin dummy
slotLabelType SLOT_INDEX
slotLabelValue 1
sharedLibrary /opt/nfast/toolkits/pkcs11/libcknfast.so 

Using module protected keys

Module protected keys do not need an operator card set. Hence no PIN code is needed to active such a key. A CA could be configured to use a keystore with module protected keys.

When using PKCS#11 slot 0 is used to indicate module protection. The only other thing except using slot 0 you have to do is to use a configuration file when creating the key. The file could look like this:

attributes(*,CKO_PUBLIC_KEY,*) = {
CKA_TOKEN = false
attributes(*,CKO_PRIVATE_KEY,*) = {
CKA_TOKEN = true
CKA_SIGN = true
disabledMechanisms = {

Not using preload

If a 1/N card set is used then preload don't have to be used (but it can be used). If preload is not used then jboss could be made to start automatically at boot time.

For PKCS#11 simple do not use the preload command. The authentication code is now needed when activating the CA.

Using more than one OCS

It is also possible to use more than one OCS. This is needed when you want different CAs protected by different OCSs.

The key to get this working is to set the environment variable CKNFAST_LOADSHARING=1. This environment variable is also implicitly set when running with preload.

To get a list of all available slots do:

$ CKNFAST_LOADSHARING=1 ~nfast/bin/ckinfo
PKCS#11 library CK_INFO
interface version 2.01
flags 0
manufacturerID "nCipher Corp. Ltd "
libraryDescription "nCipher PKCS#11 1.58.48 "
implementation version 1.58
slots[0] CK_SLOT_INFO
slotDescription " "
manufacturerID "nCipher Corp. Ltd "
flags 5
flags & CKF_HW_SLOT
hardware version 0.00
firmware version 0.00
slots[0] CK_TOKEN_INFO
label "loadshared accelerator "
manufacturerID "nCipher Corp. Ltd "
model " "
serialNumber " "
flags 201
flags & CKF_RNG
ulMaxSessionCount 1024
ulMaxRwSessionCount 1024
ulMaxPinLen 18446744073709551615
ulMinPinLen 0
hardware version 0.00
firmware version 0.00
utcTime " "
slots[1] CK_SLOT_INFO
slotDescription "1of2_0 "
manufacturerID "nCipher Corp. Ltd "
flags 6
flags & CKF_HW_SLOT
hardware version 0.00
firmware version 0.00
slots[1] Token not present
slots[2] CK_SLOT_INFO
slotDescription "2of3_0 "
manufacturerID "nCipher Corp. Ltd "
flags 6
flags & CKF_HW_SLOT
hardware version 0.00
firmware version 0.00
slots[2] Token not present
slots[3] CK_SLOT_INFO
slotDescription "ejbca "
manufacturerID "nCipher Corp. Ltd "
flags 6
flags & CKF_HW_SLOT
hardware version 0.00
firmware version 0.00
slots[3] Token not present
slots[4] CK_SLOT_INFO
slotDescription "2of3_1 "
manufacturerID "nCipher Corp. Ltd "
flags 6
flags & CKF_HW_SLOT
hardware version 0.00
firmware version 0.00
slots[4] Token not present
slots[5] CK_SLOT_INFO
slotDescription "1of2_1 "
manufacturerID "nCipher Corp. Ltd "
flags 7
flags & CKF_HW_SLOT
hardware version 0.00
firmware version 0.00
slots[5] CK_TOKEN_INFO
label "1of2_1 "
manufacturerID "nCipher Corp. Ltd "
model " "
serialNumber "ee6071c52a77370c"
flags 20D
flags & CKF_RNG
ulMaxSessionCount 1024
ulMaxRwSessionCount 1024
ulMaxPinLen 18446744073709551615
ulMinPinLen 0
hardware version 0.00
firmware version 0.00
utcTime " " 

You then got to identify your OCSs with the slot index. The label in the list gives the name you gave to your OCS when creating it. Then you get the slot list index from the x in slot[x]. Use this for slotListIndex in the CA properties.

When using a 1/n OCS one card of the OCS must be inserted when activating a CA. If the OCS is persistent then the card could be removed and you could then activate another CA by inserting its OCS.

To make the OCS persistent use the -p argument at createocs time, if this is not the case as soon as the card is removed then the cardset will unload itself.

When using k/n OCS where k>1 you got to load all OCSs to be used with preload and then start the application server also with preload. Example:

$ ~nfast/bin/preload -c 2of3_0 pause
-- follow instruction to insert cards and enter pins. --
-- then press ctr-z --
$ bg
$ ~nfast/bin/preload -c 2of3_1 exit
-- follow instruction to insert cards and enter pins. -- 

When the application server then is started with preload, CAs defined for slot list index 2 and 4 could be activated. When activating a CA when running preload no PIN has to be given. Also when the application server is started with preload then only CAs of preloaded slots could be activated (not preloaded 1/n slots could not be used).

nCipher load balancing

If you want to use the Loadsharing with multiple modules, be it PCI cards of NetHSM's then you must ensure you have a 1/N OCS and the N quorum to be able to have enough cards to be inserted in every HSM you want to load balance the key at server/CA start up when logging in.
Same security world got to be loaded in all modules participating.
After setting up the first netHSM, do the following on the second:

  • Use the panel of the second netHSM to configure the rfs

  • Use the panel of the second netHSM to load the security world

  • Use the panel of the second netHSM to configure clients

  • on each client run: /opt/nfast/bin/nethsmenroll

With load balancing you need to have CKNFAST_LOADSHARING=1. Preload implicitly sets CKNFAST_LOADSHARING.

If preload is used fail-over to the other HSM if one of the HSMs is broken is not working.

Example of starting jboss:

ejbca@host:/usr/local/ejbca> CKNFAST_LOADSHARING=1 ../jboss/bin/run.sh

When activating a CA you need a smart card from the OCS of the corresponding slot inserted in both HSMs. The OCS got to be 1/n since preload can not be used.
Sample catoken.properties for generating the initial ManagementCA on the netHSM.

defaultKey defaultKey
certSignKey defaultSign
crlSignKey defaultSign
testKey testKey
sharedLibrary /opt/nfast/toolkits/pkcs11/libcknfast.so
slotLabelValue 1

AEP Keyper

The document xxxxxxKeyperInstallation.pdf (xxxxxx is six digits) in the KeyPer UserGuides describes how the HSM is installed, the details start in section 3.5 (Configuring the Keyper HSM for the first time). As default there is only one slot - 0. The document xxxxxxKeyperP11.pdf describes the PKCS#11 interface in details.

ARX CoSign

This HSM only works on Windows. The installation is done with an installer and the setup with a GUI.
All generated keys will be on slot 1. The PIN code used when activating the keys could be anything since the authentication is made when login on to the user that runs EJBCA. The shared library is called C:\windows\system32\sadaptor.dll

Bull Trustway Proteccio

The Installation and User's Guide describes how the HSM is installed and how how PKCS#11 tokens are created and how a backup of a token is done. But it might be helpful to mention some additional things:

  1. A virtual HSM correspond to a PKCS#11 token.

  2. The number of the virtual HSM corresponds to the PKCS#11 slot ID of the token.

  3. The PKCS#11 user PIN is the PKCS#11 application authentication in the Personalizing a virtual HSM step.

  4. If CIK startup mode is selected for the virtual HSM personalization you must start the HSM manually before EJBCA can use it.

  5. Make sure that backup-restore work before taken the HSM in production since the first versions did not backup the certificate of a key which is needed by the java wrapper.

Bull Trustway PCI Crypto Card

This is an old HSM. New installations will probably use Proteccio.

Do the installation of the card according to Install_and_Use_cc2000.pdf. When the card is installed it is ready to use with EJBCA. Only one slot (slot index 0) is available. The slot is not protected by any PIN so an undefined pin (empty) property may be used in the configuration.

When using PKCS11HSMKeyTool and starting EJBCA, libcc2000_tok.so and libgpkcs11cc2000.so must be in the library path. Examples:

lars@maud:~/work/test/ca$ ls -al ../../bullInstall/linux
total 412
dr-xr-xr-x 4 lars lars 4096 28 nov 14.28 .
drwxr-xr-x 4 lars lars 4096 20 apr 21.05 ..
dr-xr-xr-x 6 lars lars 4096 20 apr 21.38 CardAdmin_java
-r-xr-xr-x 1 lars lars 35804 28 nov 14.15 cc2000_lx24.tgz
-r-xr-xr-x 1 lars lars 74955 28 nov 14.15 cc2000_src.tgz
-r-xr-xr-x 1 lars lars 14 28 nov 14.15 cc2000S_release
-r-xr-xr-x 1 lars lars 633 28 nov 14.15 desinstall
-r-xr-xr-x 1 lars lars 171 28 nov 14.15 gpkcs11cc2000.rc
dr-xr-xr-x 2 lars lars 4096 28 nov 14.28 include
-r-xr-xr-x 1 lars lars 7209 28 nov 14.15 install
-r-xr-xr-x 1 lars lars 101788 28 nov 14.15 libcc2000_tok.so
-r-xr-xr-x 1 lars lars 146820 28 nov 14.15 libgpkcs11cc2000.so
-r-xr-xr-x 1 lars lars 3843 28 nov 14.15 LisezMoi.txt
-r-xr-xr-x 1 lars lars 3410 28 nov 14.15 ReadMe.txt
lars@maud:~/work/test/ca$ LD_LIBRARY_PATH=../../bullInstall/linux ../../java/jboss/bin/run.sh
$ LD_LIBRARY_PATH=~/work/bullInstall/linux $EJBCA/dist/clientToolBox/ejbcaClientToolBox.sh PKCS11HSMKeyTool generate ../../bullInstall/linux/libgpkcs11cc2000.so 2048 defaultkey i0

SafeNet Luna

Install HW and SW

Consult the SafeNet documentation regarding installation of HW and SW.


Do all steps (1-7 in the section) in "A - Configuration (Setup Appliance after Installing)" of in the html document "Luna SA Online Help – Document # 800274-xxx" that should be found on your installation CD. Some notes about our test setup:

Step 3: You may do nothing here. But note that changing many of the policies will reset the HSM. This means that you can't change any of these policies later on.

Step 4: Note that a new partition could be added at any time. Each partition will be represented as a PKCS#11 slot. Make sure to write the Record Partition Client Password (TP) in a text file. In the example the password is btqx-EFGH-3456-7/K9 for the first created partition (slot 1). The TP will later be used as PIN for the slot.

Step 5: A good idea is to allow partitions (p11 slots) to be "activated". If a partition is not activated you got to insert the black key in the PED and give PIN each time a resource in the HSM is used by the client. So in most cases you want to be able to activate a partition: lunash:>partition changePolicy -partition partition1 -policy 22 -value 1

Step 6: You don't have to be in the '/usr/LunaSA/bin' directory as the documentation says. We think it is preferable to be in a directory owned by yourself so you don't have to use sudo. Example of running in your own directory:

$ /usr/lunasa/bin/ctp admin@lunasa.int.primekey.com:server.pem .

Example of occasions when sudo must be used is registration of server and adding client certificates (root owned files and directories are used and updated):

$ sudo /usr/lunasa/bin/vtl addServer -n lunasa.int.primekey.com -c server.pem
$ sudo /usr/lunasa/bin/vtl createCert -n milton

Step 7: Each partition assigned to a client will be represented by a PKCS#11 slot for this client. It seems that each new added partition will be put last in the slot list and the number of a slot will be slot list index plus 1 (list index starting with 0 and slot number starting with 1). To get the partition slot mapping on the client do:

$ /usr/lunasa/bin/vtl verify
The following Luna SA Slots/Partitions were found:
Slot Serial # Label
==== ======== =====
1 950784001 partition1
2 950784002 partition2

Now the client may use these slot with EJBCA and it's tools

Activating slots

Before a partition (slot) could be used by a client it must be activated. This is described in 'B - Administration & Maintenance > Activating and AutoActivating Partitions'. The partition policy required do the activation must have been set (see step 5 above). Example to activate a partition:

lunash:>hsm login
lunash:>partition activate -partition partition1 -password btqx-EFGH-3456-7/K9

The password is from the configuration step 4. See above.

Generate keys on a slot

$ ./ejbcaClientToolBox.sh PKCS11HSMKeyTool generate /usr/lunasa/lib/libCryptoki2_64.so 2048 rsa2048_1 1
0 [main] INFO org.ejbca.util.keystore.KeyTools - Using SUN PKCS11 provider: sun.security.pkcs11.SunPKCS11
PKCS11 Token [SunPKCS11-Luna] Password:
Created certificate with entry rsa2048_1.
$ ./ejbcaClientToolBox.sh PKCS11HSMKeyTool generate /usr/lunasa/lib/libCryptoki2_64.so secp160r1 secp160r1_1 1
0 [main] INFO org.ejbca.util.keystore.KeyTools - Using SUN PKCS11 provider: sun.security.pkcs11.SunPKCS11
PKCS11 Token [SunPKCS11-Luna] Password:
Created certificate with entry secp160r1_1.

The password btqx-EFGH-3456-7/K9 (see above) is used.

List and test all keys that could be used by EJBCA

$ ./ejbcaClientToolBox.sh PKCS11HSMKeyTool test /usr/lunasa/lib/libCryptoki2_64.so 1
Test of keystore with ID 1.
0 [main] INFO org.ejbca.util.keystore.KeyTools - Using SUN PKCS11 provider: sun.security.pkcs11.SunPKCS11
PKCS11 Token [SunPKCS11-libCryptoki2_64.so-slot2] Password:
Testing of key: rsa2048_1
SunJCE version 1.7SunPKCS11-libCryptoki2_64.so-slot2 version 1.7; modulus length: 2048; byte length 245. The docoded byte string is equal to the original!
Signature test of key rsa2048_1: signature length 256; first byte 28; verifying true
Key statistics.
Signings per second: 369; Decryptions per second: 135
Testing of key: secp160r1_1
Signature test of key secp160r1_1: signature length 48; first byte 30; verifying true
Key statistics.
Signings per second: 68 No crypto available for this key. 

Sample Hard Token Properties

This is a sample configuration of the Hard Token Properties for PKCS#11 token when creating a new CA.


Some useful Luna commands

Here are some useful native Luna cmu commands.

List objects and their handles:

./cmu list -display=index,handle,class,keyType,label

If you have created keys with native commands, or imported keys, there is probably no certificate object as required by Java PKCS#11 provider. Create a self signed certificate referencing the private handle:

./cmu selfSign -privatehandle=87 -CN="caSign00001" -startDate=20020101
-endDate=20451231 -serialNum=0133337f

Notice that they will have to replace 87 with the handle of the private key they found when running the list command.

SafeNet ProtectServer

install SW

Install the software according to the installation instructions for the ProtectServer. Below are sample commands for installing the SDK rpm on an Ubuntu system, wich means first converting it to a deb.
Using the SDK you can use the SDK as a good emulator for testing and development. If you are installing with a real ProtectServer you should install the Runtime instead of the SDK. When using the SDK you may use /opt/ETcpsdk/lib/linux-x86_64 instead of /opt/PTK/lib

fakeroot alien -c $CDROM/Linux64/ptkc_sdk/ETcpsdk-3.32.00-1.x86_64.rpm
sudo dpkg -i ./etcpsdk_3.32.00-2_amd64.deb

et passwords for admin SO och admin user

LD_LIBRARY_PATH=/opt/PTK/lib /opt/PTK/bin/ctconf

create 10 slots

LD_LIBRARY_PATH=/opt/PTK/lib /opt/PTK/bin/ctconf -c10

Set no public crypto

See Programming in FIPS mode in the Protect Toolkit-C Programmers Manual for information about this flag.

LD_LIBRARY_PATH=/opt/PTK/lib /opt/PTK/bin/ctconf -fc

Initialize slot 5. Sets SO and user password

LD_LIBRARY_PATH=/opt/PTK/lib /opt/PTK/bin/ctkmu t -s5 -lroot

Generate keys on slot 5

./ejbcaClientToolBox.sh PKCS11HSMKeyTool generate /opt/PTK/lib/libcryptoki.so 2048 defaultSign 5
./ejbcaClientToolBox.sh PKCS11HSMKeyTool generate /opt/PTK/lib/libcryptoki.so 2048 default 5
./ejbcaClientToolBox.sh PKCS11HSMKeyTool generate /opt/PTK/lib/libcryptoki.so 512 test 5

If JBoss was started you have to restart JBoss before the keys becomes available in EJBCA.

Contents of CA Token Properties

When you create the CA in EJBCA you can now use the simple CA token properties below.

certSignKey defaultSign
crlSignKey defaultSign
defaultKey default
testKey test

Test and list keys on slot 5

./ejbcaClientToolBox.sh PKCS11HSMKeyTool test /opt/PTK/lib/libcryptoki.so 5
Testing of key: test
SunJCE version 1.7SunPKCS11-libcryptoki.so-slot3 version 1.7; modulus length: 2048; byte length 53. The docoded byte string is equal to the original!
SunPKCS11-libcryptoki.so-slot3 RSA private key, 512 bits (id 4, token object, sensitive, extractable)
Signature test of key test1: signature length 64; first byte 3d; verifying true
Signings per second: 257
Decryptions per second: 260

The attributes are listed as token object, sensitive, extractable, and here is important that is says sensitive (extractable only means that the key can be backed up securely using SafeNet tools).

Backup and restore

When you have tested that all keys are working you should back them up. Read about how this is done in the ProtectServer documentation. Then clear the slot that you has just backed up:

ctkmu -s <slot nr> t

Then restore the backup according to the ProtectServer documentation and run the clientToolBox test as above. Now when you now that the keys of the slot could be restored from the backup medium you should set the attributes of them so that they could not be extracted from the HSM by any means. Unfortunate this could not be done with the ctkmu CLI tool since the private key got no label. Use the GUI kmu instead. For each key do:

  1. Select the token and login to it.

  2. Double click on the private key that you want to protect.

  3. Uncheck the Exportable box and press OK

  4. Verify that the Exportable and the Extractable boxes are unchecked and can't be changed

  5. Verify that the Private and the Sensitive boxes are checked and can't be changed

Now it should be impossible to do any backup of the key. If you got a key ceremony protocol it could be a good idea to note that keys was made unexportable. Also note that the Exportable attribute has to be unchecked each time the backup is restored.

The emulator has an annoying feature (only emulator not real HSM). Each key of same length that are generated is the same, because the seed for the random number generator is static. This means that a slot may only have one key. If a second key is generated for a slot the certificate object for the first key is deleted before writing the certificate object for the new key. This is done since the Sun p11 wrapper provider does not allow two keys that are equal to be present in a keystore. To fix this you should set the environment variable ET_PTKC_SW_AUTOSEEDRNG=true.

Generating keys using ProtectServer tools

You can also generate keys, and the needed self signed certificate, using the SafeNet tools delivered with the HSM. This is for example suitable when you want to generate ECC keys with curves not supported by JDK (although you may still have to patch the JDK in order to use them anyhow).

For example, the below commands generates an ECC key with curve P-256 on slot 1, storing it on the HSM with alias foo, assigning a selfsigned certificate to it and finally listing the object of slot 1.

cd /opt/ETCprt/bin/linux-x86-64
./ctkmu c -tec -nfoo -aPSVXxTRD -s1 -CP-256
./ctcert c -s1 -lfoo
./ctkmu l -s1

Or you can wrap it all up in a single command...

./ctcert c -k -lfoo -tec -s1 -CP-256 -d30y

If JBoss was started you have to restart JBoss before the keys becomes available in EJBCA.


SmartCard-HSM is a lightweight hardware security module in a Smart Card, MicroSD or USB form factor providing a remotely manageable secure key store to protect your RSA and ECC keys.


SoftHSM2 works very well with EJBCA, and after initializing a slot you can use it by creating a new Crypto Token in the Admin GUI.

The user PIN is what you will use to activate the token in EJBCA.

sudo apt-get install softhsm2

To use it as a normal user, make /var/lib/softhsm/tokens available to your normal user (for writing in order to create keys), and /etc/softhsm/* readable by the user.

After setting privileges, you can use softhsm as normal user.

softhsm2-util --init-token --free --label myslo

The Ubuntu package for SoftHSM2 is not always initializing properly (depending on the Ubuntu version you are running) so you may have to create missing directories etc. If you get an ERROR: Could not initialize the library when running the above there is a directory missing, and a token not initialized.

sudo mkdir /var/lib/softhsm/tokens
sudo chmod a+rwx /var/lib/softhsm
sudo chmod a+rwx /var/lib/softhsm/tokens
sudo chmod a+rx /etc/softhsm
sudo chmod a+r /etc/softhsm/*
softhsm2-util --init-token --free --label myslot

The above commands give write privileges to all users in the system and you may wish to tune that to your security policy.

Now you can initialize additional slots. Note that if you provide the --slot parameter to SoftHSM2 it will most likely not become the slotnumber you specify.

To list the slots, use the following command:

softhsm2-util --show-slots

PKCS11 Spy

You can debug PKCS11 sessions and all calls made, using OpenSC's P11Spy. As of EJBCA 6.8.0, P11Spy is by default included in the known P11 implementation in con/web.properties.

Stop JBoss, install P11Spy, and set the environment variables used in the JBoss terminal:

apt-get install opensc-pkcs11
export PKCS11SPY=/usr/local/lib/softhsm/libsofthsm2.so
export PKCS11SPY_OUTPUT=logfile.log

Then start JBoss and create a new PKCS11 Crypto Token using the PKCS11Spy PKCS#11 Library.

Support for new HSMs

EJBCA uses PKCS#11 so in theory can support any HSMs that provide a decent PKCS#11 implementation. If the HSM is peculiar you may have to provide specific attribute parameters as descibed for an 'attributesFile' above.


Out of the box in Java PKCS#11 RSASSA-PSS is not supported. The software in EJBCA supports it, but the Java PKCS#11 provider does not.

At the time of writing, Oracle Java does not have support for SHA256WithRSAandMGF1 (also known as RSASSA-PSS) in the PKCS#11 provider. PrimeKey has made a patch which is waiting for approval in the OpenJDK. You can get a compiled patch together with an installation script for Debian-based operating systems from PrimeKey.

This issue is registered in the EJBCA issue tracker as ECA-2014.

The patch should work on all HSMs that have support for SHA256WithRSAandMGF1.

With the patch applied you can create CAs using HSMs with the SHA256WithRSAandMGF1 (and SHA384 and SHA512) algorithm.

Extending Sun PKCS#11 to set CKA_MODIFIABLE=false

In order to change the CKA_MODIFIABLE attribute of a private key to FALSE directly after it has been generated the Sun PKCS#11 implementation must be extended. This extension must be done by adding classes to Installed Extensions classpath. See https://docs.oracle.com/javase/tutorial/ext/basics/install.html

This is achieved by putting the '$EJBCA_HOME/dist/ext/cesecore-p11.jar' in one of the directories that is defined by the 'java.ext.dirs' system property. You can put the jar in '$JAVA_HOME/jre/lib/ext'. You may also change the property to include the directory of the jar. Here is an example:

JAVA_OPTS="-Djava.ext.dirs=/usr/lib/jvm/java-7-openjdk-amd64/jre/lib/ext:$EJBCA_HOME/dist/ext" $JBOSS_HOME/bin/standalone.sh

Ensure to keep '$JAVA_HOME/jre/lib/ext' in the classpath.

To enable the feature in EJBCA, set 'pkcs11.makeKeyUnmodifiableAfterGeneration=true' in $EJBCA_HOME/conf/cesecore.properties.

If you use '$EJBCA_HOME/dist/ejbcaClientToolBox.sh' you do not have to set the java.ext.dirs setting as the configuration is performed by the script.

Everything will work without this jar in the classpath, but if it is not in classpath, the CKA_MODIFIABLE will be TRUE for every key that is generated and a warning written to the log.

The reason to set CKA_MODIFIABLE to FALSE is that it should not be possible to set CKA_DERIVE to TRUE. If CKA_DERIVE is true it might be possible to extract the private key from some HSMs (CVE-2015-5464), although most vendors have now patched this by not allowing weak key derivation schemes.

The ability to set CKA_MODIFIABLE=true is HSM vendor dependent and using the above method to change CKA_MODIFIABLE to false may not give the desired bahavior and thorough testing is advised.

Certain HSMs (for example SoftHSM2) refuses to set CKA_MODIFIABLE to FALSE (the PKCS#11 standard says that this behavior is OK).

In summary, the configuration requires careful testing. Tests can be performed using the clientToolBox tool with a generate-test cycle:

$EJBCA_HOME/dist/ejbcaClientToolBox.sh PKCS11HSMKeyTool generate (to generate a new key)
$EJBCA_HOME/dist/ejbcaClientToolBox.sh PKCS11HSMKeyTool test (to test, in a new PKCS#11 session if it is usable)

If you also generate keys using the Admin GUI, this should also be tested, together with restarting JBoss between generation and usage.