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.

The following provides information on Hardware Security Modules (HSMs) in the following sections.

HSM Modules Available in the CA UI

You can manage crypto tokens fully in the EJBCA CA UI or CLI. and the CA UI automatically displays 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

Please note that FIPS mode does not allow the same key to be used for signing and encryption.

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 CRLs, 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 a 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, using the Java PKCS#11 provider, you can use the EJBCA Client Toolbox.

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

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

Or with P11NG (Thales Luna example):

./p11ng-cli.sh listslots --lib-file /usr/safenet/lunaclient/lib/libCryptoki2_64.so
./p11ng-cli.sh showtokeninfo --lib-file /usr/safenet/lunaclient/lib/libCryptoki2_64.so --slot 0
./p11ng-cli.sh listobjects --lib-file /usr/safenet/lunaclient/lib/libCryptoki2_64.so --slot-ref SLOT_NUMBER --slot 0
./p11ng-cli.sh signperformancetest --lib-file /usr/safenet/lunaclient/lib/libCryptoki2_64.so --slot 0 --alias p256 --time-limit 5000 --signature-algorithm SHA256WithECDSA
CODE

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
BASH

These two properties contain 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:
hidden
Encrypting pwd...
6bc841b2745e2c95e042a68b4777b34c
BASH

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.

HSMs and Post-Quantum Cryptographic Algorithms

Support for Post-Quantum cryptographic algorithms in HSMs is dependent on the support for the algorithms in the HSM and you need to confirm whether support is available. For more information on HSMs and Quantum Readiness, see Post-Quantum Cryptography Keys and Signatures.

HSMs and DSA or ECDSA

Support for DSA or ECDSA in HSMs are dependent on the support for the algorithms in the HSM and you need to confirm whether support is available.

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

Vendor Specific Information

For HSM Vendor specific installation and configuration information, see the following sections.

Support for New HSMs

EJBCA uses PKCS#11 and can, in theory, support any HSMs that provide a decent PKCS#11 implementation. If the HSM has very different PKCS#11 attribute requirements than the 10+ HSMs already supported by EJBCA, additional work may be needed.

PKCS11 Call Logging

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 conf/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
CODE

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

Another option for PKCS#11 call logging is PKCS11-Logger. Using something like this example:

PKCS11_LOGGER_LIBRARY_PATH=/opt/utimaco/libcs_pkcs11_R2.so
PKCS11_LOGGER_LOG_FILE_PATH=/tmp/pkcs11_logger.log
PKCS11_LOGGER_FLAGS=64
CODE

And pointing EJBCA to use the PKCS11-Logger library pkcs-11-logger-x64_V2.2.0.so, don't forget to add it as a known P11 implementation in conf/web.properties (unless it's there already.

Remote Forwarding PKCS#11 using P11-Kit

P11-kit can be used to forward for example a USB Token HSM connected to your local laptop to a server running EJBCA. This allows you to have your HSM in your control, while running the server somewhere else, for example in the cloud. It requires some setup and some work when you disconnect/connect your token, but can work for low-scale deployments.

The following is an outline of commands to get a NitroKey HSM (connected to Local) available to a remote server (Remote) over P11-kit. EJBCA runs on the remote server. This is based on information by Maxence Mohr on PKI and HSM in a SME and remote-hsm, and tested on Ubuntu 16.04 and 18.04.

Install p11-kit on both Remote and Local

sudo apt install gcc make gtk-doc-tools help2man texinfo texlive-base libffi-dev libtasn1-dev gnutls-bin
wget https://github.com/p11-glue/p11-kit/releases/download/0.23.15/p11-kit-0.23.15.tar.gz
tar zxvf p11-kit-0.23.15.tar.gz
cd p11-kit-0.23.15/
./configure
make
make check
sudo make install
ls -al /usr/local/bin/p11-kit
ls -al /usr/local/lib/pkcs11/p11-kit-client.so

mkdir -p ~/.config/systemd/user
vi ~/.config/systemd/user/p11-kit-client.service
-----
[Unit]
Description=p11-kit client

[Service]
Type=oneshot
RemainAfterExit=true
RuntimeDirectory=p11-kit
ExecStart=/bin/true

[Install]
WantedBy=default.target
-----

systemctl --user daemon-reload
systemctl --user enable p11-kit-client.service
systemctl --user start p11-kit-client.service
ls /run/user/`id -u`/
CODE

Use SSH to forward P11 from Local to Remote

Run SSH from the machine where you plug your USB device (local) towards the server where you run EJBCA (remote).

# see https://github.com/fladna9/remote-hsm/blob/master/remote-hsm.sh

# Verifying if systemd user service is enabled (local).
systemctl --user status p11-kit-client.service | grep "Active: active"
# If _not_ running, start it
systemctl --user enable p11-kit-client.service
systemctl --user start p11-kit-client.service

# Verifying if systemd user service is enabled (remote). On Local:
ssh user@192.168.122.1 systemctl --user status p11-kit-client.service | grep "Active: active"
# If _not_ running, start it
ssh user@192.168.122.1 systemctl --user enable p11-kit-client.service
ssh user@192.168.122.1 systemctl --user start p11-kit-client.service

# On Local (with the USB Token), get tokenURL and start p11-kit server
p11tool --provider /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so --list-token-urls
(pkcs11:model=PKCS%2315%20emulated;manufacturer=www.CardContact.de;serial=DENK0101866;token=UserPIN%20%28SmartCard-HSM%29)
p11-kit server --provider /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so pkcs11:model=PKCS%2315%20emulated;manufacturer=www.CardContact.de;serial=DENK0101866;token=UserPIN%20%28SmartCard-HSM%29
(P11_KIT_SERVER_ADDRESS=unix:path=/run/user/1000/p11-kit/pkcs11-389; export P11_KIT_SERVER_ADDRESS;P11_KIT_SERVER_PID=390; export P11_KIT_SERVER_PID;)

eval P11_KIT_SERVER_ADDRESS=unix:path=/run/user/1000/p11-kit/pkcs11-389; export P11_KIT_SERVER_ADDRESS;P11_KIT_SERVER_PID=390; export P11_KIT_SERVER_PID;

# Done, local socket is at ${P11_KIT_SERVER_ADDRESS}

# SSH tunneling the socket to remote EJBCA instance. On Local:
ssh user@192.168.122.1 systemd-path user-runtime
(/run/user/1000)
ssh -N -f -R /run/user/1000/p11-kit/pkcs11:${P11_KIT_SERVER_ADDRESS#*=} user@192.168.122.1
# SSH tunneling done, remote socket is at 192.168.122.1:/run/user/1000/p11-kit/pkcs11

# Test remote access to token, from Local
ssh user@192.168.122.1 pkcs11-tool --module /usr/local/lib/pkcs11/p11-kit-client.so -L
CODE

If things fail and you have to start over, you need to clean sockets:

# On Local:
rm /run/user/1000/p11-kit/*
pkill -f p11-kit-server
pkill -f p11-kit-remote
pkill -f "ssh -N -f -R /run/user/"
# On Local (to Remote)
DISTANTRUN=$(ssh user@192.168.122.1 systemd-path user-runtime)
ssh user@192.168.122.1 rm "$DISTANTRUN/p11-kit"/*
CODE

Using SHA256WithRSAandMGF1 (RSASSA-PSS)

You can create CAs using HSMs that support it, with the SHA256WithRSAandMGF1 a.k.a SHA256WithRSASSA-PSS algorithm (and SHA384 and SHA512). The software in EJBCA supports it.

When using HSMs, P11NG (the PKCS#11 NG Crypto Token in EJBCA) supports RSASSA-PSS.

When using the Java PKCS#11 Provider (PKCS#11 Crypto Token in EJBCA), support for RSASSA-PSS was implemented in OracleJDK 8u241, OpenJDK 8u272, and 11.0.6. In the Java PKCS#11 provider, things have been seen to break in different versions though, for example RSASSA-PSS working only with RSA keys 4096 bit or larger in some versions of the JDK. This is outside the control of the EJBCA team.