Skip to main content
Skip table of contents

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.

There are multiple interfaces available to communicate with HSMs

  • REST based APIs that are proprietary and specific for each HSM. In EJBCA these are listed as a specific HSM, i.e. AWS KMS, Azure Key Vault, Fortanix DSM, Securosys Primus
  • PKCS#11 is a standard interface standardized by Oasis. This comes with two implementations.
    • Java PKCS#11 (a.k.a SunPKCS11) is the implementation included in standard OpenJDK, and most other JDKs. It provides a Java keystore API to applications, but has many limitations. EJBCA is limited to what Java PKCS#11 supports.
    • PKCS#11 NG is the primary implementation in EJBCA Enterprise, giving more control of the implementation, including early support for quantum-safe algorithms.

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 or PKCS#11 NG options are 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 or PKCS#11 NG as Type. As PKCS#11 Library there is a list of the available known HSMs found in the file system.

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

  • To use Java PKCS#11 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.

PKCS#11 Multiple HSM Support

EJBCA supports using multiple PKCS#11 HSMs at the same time (e.g. multiple HSMs from different HSM vendors). PKCS#11 have some limitations, such as that vendors typically supports only installing one instance of the PKCS#11 library on the host system.

Multiple HSM support is useful where for example different CAs or VAs use different HSMs or different HSM slots, configured as different independent Crypto Tokens in EJBCA. It is not related to HSM High Avilability. For HA features of an HSM consult the HSM vendors documentation.

The following an be done:

  • Using multiple HSMs from different vendors (using different PKCS#11 libraries).
  • Using multiple tokens in the same HSM (in different EJBCA crypto tokens) when exposed as different tokens/slots in PKCS#11.

The following is not supported:

  • Using multiple HSMs from the same vendor (using the same PKCS#11 library), unless the PKCS#11 library allows such configuration presenting the different HSMs as multiple tokens/slots to EJBCA.
  • Using the same token/slot with multiple EJBCA crypto tokens (you can merge crypto tokens if you have created several with the same configuration).
  • Using the same HSM / PKCS#11 library with both SunPKCS11 and P11NG at the same time (e.g. they may conflict).

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.

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

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

Or with P11NG (Thales Luna example):

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

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.

BASH
pin foo123
pin 6bc841b2745e2c95e042a68b4777b34c

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

BASH
$ 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

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

If you use P11NG you can configure logging in JBoss/WildFly to log all PKCS#11 commands being done from the application to the HSM driver. Set debug logging on org.pkcs11.jacknji11.Cryptoki.

CODE
/subsystem=logging/logger=org.pkcs11.jacknji11.Cryptoki:add
/subsystem=logging/logger=org.pkcs11.jacknji11.Cryptoki:write-attribute(name=level, value=DEBUG)

Or when using the P11Ng CLI you can configure a log file for this in log4j.xml with something like this.

CODE
<!-- PKCS11 debug output -->
<appender name="pkcs11" class="org.apache.log4j.FileAppender">
    <param name="file" value="pkcs11.log" />
    <param name="append" value="false" />
    <param name="threshold" value="debug" />
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d{ISO8601} %-5p [%c{1}] - %m%n" />
    </layout>
</appender>
...
<category name="org.pkcs11.jacknji11.Cryptoki" additivity="false">
    <priority value="DEBUG"/>
    <appender-ref ref="pkcs11"/>
</category>


There are also other external tools available to sit as a man-in-the-middle to proxy and log all PKCS#11 calls.

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:

CODE
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.

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

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

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

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

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).

CODE
# 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

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

CODE
# 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"/*

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.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.