Additional Testing
The tests in this section verify that the RHCS CA uses the nShield HSM for all of its private-key operations. They use command-line tools instead of Firefox.
Each test describes what is tested, how it relates to the HSM, the commands to run, an example of the expected output, and the criteria for the test to pass. Run the tests in order, because later tests use the files and values created by earlier tests.
| Test | Description | Required |
|---|---|---|
The HSM and Security World are usable. |
Yes |
|
The CA service is running and serving HTTPS. |
Yes |
|
The CA system keys are stored on the HSM token. |
Yes |
|
Agent login with the admin certificate. |
Yes |
|
Issue a certificate signed by the HSM-protected CA key. |
Yes |
|
OCSP reports the new certificate as good. |
Yes |
|
Revoke the certificate. |
Yes |
|
OCSP reports the certificate as revoked. |
Yes |
|
The certificate record is stored in RHDS. |
Yes |
|
Generate and verify a new CRL. |
Yes |
|
Verify the signed audit log. |
Only if audit log signing is enabled |
|
CA restart and unattended HSM token login. |
Optional |
|
The CA cannot sign while the HSM is unavailable (expected failure). |
Optional |
Before you begin
Make sure that:
-
The CA instance was deployed as described in Procedures. The examples in this section use the instance name
ca-1, the SoftcardtestSC, and the host namepki.domain.com. -
You can log in to the CA server as a user with
sudoprivileges. -
You know the admin PKCS #12 password (
pki_client_pkcs12_passwordin thepkispawnconfiguration file). -
If the CA keys are protected by an OCS, the OCS is inserted in the HSM.
Prepare the test environment
Run all the commands, in this section and in the tests, in the same shell session on the CA server.
-
Create and navigate to a private working folder:
mkdir -m 700 ~/hsm-test cd ~/hsm-test export PATH=$PATH:/opt/nfast/binAll the files created during the tests are saved in this folder. Some of them contain secrets. Delete the folder at the end of the tests, as described in Clean up.
-
Set the following shell variables. Replace
ca-1andtestSCwith your CA instance name and HSM token name:INSTANCE=ca-1 TOKEN=testSC CS_CFG=/var/lib/pki/$INSTANCE/ca/conf/CS.cfg PW_CONF=/var/lib/pki/$INSTANCE/conf/password.conf ALIAS_DIR=/var/lib/pki/$INSTANCE/conf/alias HOST=$(sudo grep -m1 '^machineName=' $CS_CFG | cut -d= -f2-) BASEDN=$(sudo grep -m1 '^internaldb.basedn=' $CS_CFG | cut -d= -f2-) HTTPS_URL=https://$HOST:8443 HTTP_URL=http://$HOST:8080 echo "$HOST $BASEDN"Example output:
pki.domain.com o=pki-ca-1-CA
-
Define the following shell functions:
# Total number of commands processed by the hardserver. hsm_cmds() { stattree | awk '/CmdCount/ && $NF ~ /^[0-9]+$/ {s += $NF} END {print s}'; } # Waits until the CA reports that it is running. wait_for_ca() { until curl -sk --max-time 10 $HTTPS_URL/ca/admin/ca/getStatus \ | grep -q '"Status" *: *"running"'; do sleep 5 done echo "CA is running" }hsm_cmdsreads the hardserver command counters. Tests 5, 6, 8, and 10 compare the counter before and after each signing operation, as evidence that the operation was carried out by the HSM. The counter is evidence only, not a pass or fail criterion. -
Check that the hardserver and the CA are running:
enquiry | grep -m2 mode curl -sk $HTTPS_URL/ca/admin/ca/getStatusBoth lines from
enquirymust showoperational, and the CA must report"Status" : "running".If
enquiryfails, start the hardserver, then restart the CA so it opens new sessions with the HSM:sudo /opt/nfast/sbin/init.d-ncipher start sudo systemctl restart pki-tomcatd@$INSTANCE wait_for_ca -
Record the token protection. For a Softcard, the token name is listed by
nfkminfo -s. For an OCS, it is listed bynfkminfo -c, together with its K/N quorum:nfkminfo -s nfkminfo -cIf the token is an OCS with K>1, check that
/opt/nfast/cknfastrccontainsNFAST_NFKM_TOKENSFILE, and do not run the following tests: -
Check which entries the CA password file contains, without displaying their values:
sudo ls -l $PW_CONF sudo cut -d= -f1 $PW_CONFExample output:
-rw-rw----. 1 pkiuser pkiuser 96 Oct 23 18:40 /var/lib/pki/ca-1/conf/password.conf hardware-testSC internal internaldb replicationdb
The CA reads this file at every start-up to log in to its tokens:
-
hardware-<token>is the PIN of the HSM token. -
internalis the password of the CA’s NSS database. -
internaldbis the password the CA uses to bind to RHDS.
-
(Optional) Enable signed audit logging
Test 11: Verify the signed audit log verifies the CA audit log, which is signed with the audit signing key on the HSM. It can only run if audit log signing is enabled.
To ensure that audit log signing is enabled before you start the tests:
-
Check the current audit signing settings:
sudo grep -E \ '^log.instance.SignedAudit.(logSigning|signedAuditCertNickname|flushInterval)=' \ $CS_CFGIf the output contains
log.instance.SignedAudit.logSigning=true, audit log signing is already enabled. Skip the rest of this procedure. -
Back up
CS.cfg:AUDIT_BACKUP=$CS_CFG.bak.$(date +%Y%m%d%H%M%S) sudo cp -p $CS_CFG $AUDIT_BACKUP -
Stop the CA, so it does not overwrite your changes to
CS.cfg:sudo systemctl stop pki-tomcatd@$INSTANCE -
If
signedAuditCertNicknameis not set, set it to the audit signing certificate on the HSM token:sudo pki-server ca-config-set -i $INSTANCE \ log.instance.SignedAudit.signedAuditCertNickname \ "$TOKEN:auditSigningCert cert-$INSTANCE CA" -
Enable audit log signing:
sudo pki-server ca-config-set -i $INSTANCE \ log.instance.SignedAudit.logSigning true -
Record the current length of the audit log. The existing entries were written unsigned, so Test 11: Verify the signed audit log only verifies the entries written after this point:
AUDIT_START=$(sudo wc -l /var/log/pki/$INSTANCE/ca/signedAudit/ca_audit \ | awk '{print $1}') echo $AUDIT_START -
Start the CA and wait until it is running:
sudo systemctl start pki-tomcatd@$INSTANCE wait_for_ca -
Confirm the new settings:
sudo grep -E \ '^log.instance.SignedAudit.(logSigning|signedAuditCertNickname)=' \ $CS_CFGAt the end of the tests, restore the original configuration as described in Clean up.
Test 1: The HSM and Security World are usable
- What is tested
-
The HSM module is operational, and the Security World and module #1 are in a usable state.
- HSM relevance
-
The CA can only use its keys if the hardserver can reach module #1 and the Security World is loaded.
- Prerequisites
-
-
The nShield software is installed and the hardserver is running.
-
The HSM is enrolled with this server.
-
The Security World is loaded on the HSM.
-
- Steps
-
-
Check the HSM module mode:
enquiryExample output (excerpt):
... Module #1: enquiry reply flags none enquiry reply level Six serial number 1234-5678-9ABC mode operational version 13.8.5 ... module type nShield Connect XC ... connection status OK ... hardware status OK
-
Check the Security World and module state:
nfkminfoExample output (excerpt):
World generation 2 state 0x37270009 Initialised Usable Recovery !PINRecovery !ExistingClient RTC NVRAM FTO AlwaysUseStrongPrimes !DisablePKCS1Padding !PpStrengthCheck AuditLogging !StrictKeyAgreement SEEDebug ... Module #1 generation 2 state 0x2 Usable ...
-
Measure the idle HSM command rate. This is the baseline for the HSM command counters in later tests:
C1=$(hsm_cmds) sleep 5 C2=$(hsm_cmds) IDLE=$((C2 - C1)) echo "Idle baseline: $IDLE commands in 5 seconds"Example output:
Idle baseline: 1258 commands in 5 seconds
-
- Result
-
The test passes if
enquiryshowsmode operationalfor module #1, andnfkminfoshowsUsablein the state of both the World and module #1.
Test 2: The CA service is running and serving HTTPS
- What is tested
-
The
pki-tomcatdservice is active, and the CA answers its status request over HTTPS. - HSM relevance
-
At start-up, the CA logs in to the HSM token with the PIN in
password.conf. The HTTPS handshake is signed with the SSL server key, which is stored on the HSM, so a successful TLS connection shows that the HSM key is in use. - Prerequisites
-
-
The CA instance was installed with
pkispawnon the HSM token. -
The token PIN is stored in
password.conf(hardware-<token>=).
- Steps
-
-
Check that the CA service is running:
sudo systemctl is-active pki-tomcatd@$INSTANCEExpected output:
active
-
Record the CA state, ports, and URLs:
sudo pki-server status $INSTANCEExample output (excerpt):
Instance ID: ca-1 Active: True Unsecure Port: 8080 Secure Port: 8443 ... CA Subsystem: ... Unsecure URL: http://pki.domain.com:8080/ca/ee/ca Secure Agent URL: https://pki.domain.com:8443/ca/agent/ca Secure EE URL: https://pki.domain.com:8443/ca/ee/ca Secure Admin URL: https://pki.domain.com:8443/ca/services -
Export the CA signing certificate. Later tests use it to verify everything that the CA signs:
sudo pki-server cert-export ca_signing -i $INSTANCE \ --cert-file ca_signing_cert.pem -
Connect to the CA over TLS, verifying the server certificate against the CA certificate:
curl -sS --max-time 30 --cacert ca_signing_cert.pem \ $HTTPS_URL/ca/admin/ca/getStatusExample output:
{ "Response" : { "State" : "1", "Type" : "CA", "Status" : "running", "Version" : "11.10.1", "ProductVersion" : "Red Hat Certificate System 11.0.0" } }
-
- Result
-
The test passes if the service is
activeandgetStatusreturns"Status" : "running"over a verified TLS connection. If the test fails, checkjournalctl -u pki-tomcatd@<instance>for token login errors.
Test 3: The CA system keys are stored on the HSM token
- What is tested
-
All CA system certificates have their private keys on the HSM token, not in the internal (software) NSS token.
- HSM relevance
-
This shows that the keys were generated in, and are protected by, the HSM rather than stored in software.
- Prerequisites
-
-
The HSM token PIN (
hardware-<token>=) and the internal token password (internal=) are inpassword.conf.
- Steps
-
-
Copy the token PINs from
password.confinto files in the working folder, without displaying them:sudo grep -m1 "^hardware-$TOKEN=" $PW_CONF \ | cut -d= -f2- | tr -d '\n' > hsm_token_pin.txt sudo grep -m1 '^internal=' $PW_CONF \ | cut -d= -f2- | tr -d '\n' > internal_token_pin.txt -
List the CA system certificates:
sudo pki-server cert-find -i $INSTANCEExample output (excerpt):
Cert ID: ca_signing Nickname: caSigningCert cert-ca-1 CA Token: testSC ... Cert ID: ca_ocsp_signing Nickname: ocspSigningCert cert-ca-1 CA Token: testSC ... Cert ID: sslserver Nickname: Server-Cert cert-ca-1 Token: testSC ... Cert ID: subsystem Nickname: subsystemCert cert-ca-1 Token: testSC ... Cert ID: ca_audit_signing Nickname: auditSigningCert cert-ca-1 CA Token: testSC ...
Note the nickname of each certificate.
-
List the private keys on the HSM token:
sudo certutil -K -d $ALIAS_DIR -h $TOKEN -f hsm_token_pin.txtExample output:
certutil: Checking token "testSC" in slot "testSC" < 0> mldsa 64b9452a89acf1fe5be2c6ce8d4f3ebe087dad42 testSC:caSigningCert cert-ca-1 CA < 1> mldsa ae1b3594762344bd41a3471b64a370a391beb3ad testSC:ocspSigningCert cert-ca-1 CA < 2> rsa 959d612696c69b633d159aea8b147435a5b31d1e testSC:Server-Cert cert-ca-1 < 3> mldsa 091c91c5a34160a6580f48753846e3bcef074e19 testSC:subsystemCert cert-ca-1 < 4> mldsa 3b78e5e2b3d285563b5b5ac3b9f2a45bd5400d30 testSC:auditSigningCert cert-ca-1 CA
-
List the private keys in the internal software token:
sudo certutil -K -d $ALIAS_DIR -f internal_token_pin.txtExpected output:
certutil: Checking token "NSS Certificate DB" in slot "NSS User Private Key and Certificate Services" certutil: no keys found
certutilexits with code 255 when a token holds no private keys. This is the expected result for the internal token.
-
- Result
-
The test passes if every system certificate nickname from
pki-server cert-findis listed on the HSM token, and none are listed in the internal software token.
Test 4: Agent login with the admin certificate
- What is tested
-
A client NSS database is created, the CA certificate is trusted, the admin PKCS #12 is imported, and the agent interface is accessed with the admin certificate. This replaces importing the CA chain and the agent credential into Firefox.
- HSM relevance
-
The CA certificate trusted here is signed by the CA signing key on the HSM, and the TLS session uses the SSL server key on the HSM.
- Prerequisites
-
-
Test 2: The CA service is running and serving HTTPS passed, and
ca_signing_cert.pemis in the working folder. -
The admin PKCS #12 file created by
pkispawnis at/root/.dogtag/<instance>/ca_admin_cert.p12.
-
- Steps
-
-
Save the admin PKCS #12 password in a file. Enter the password when prompted:
read -rs -p "Admin PKCS #12 password: " P12PW; echo printf '%s' "$P12PW" > admin_p12_password.txt unset P12PW -
Create a random password for the client NSS database:
head -c 24 /dev/urandom | base64 | tr -d '\n' > client_nssdb_password.txt -
Copy the admin PKCS #12 file, which only
rootcan read, to the working folder:sudo cat /root/.dogtag/$INSTANCE/ca_admin_cert.p12 > admin_cert_and_key.p12 -
Define the common
pkiclient options (server URL, client NSS database, and its password file):PKI="pki -U $HTTPS_URL -d client_nssdb -C client_nssdb_password.txt" -
Create the client NSS database, which takes the place of Firefox:
$PKI client-init --force -
Import and trust the CA signing certificate:
$PKI client-cert-import "CA Certificate" --ca-cert ca_signing_cert.pemExpected output:
Imported certificate "CA Certificate"
-
Import the admin certificate and key:
$PKI pkcs12-import --pkcs12 admin_cert_and_key.p12 \ --password-file admin_p12_password.txt -
Find the nickname of the imported admin certificate. It is the certificate with the trust attributes
u,u,u:certutil -L -d client_nssdbExample output:
Certificate Nickname Trust Attributes SSL,S/MIME,JAR/XPI CA Certificate CT,C,C PKI Administrator for domain.com u,u,u -
Save the nickname in a variable:
ADMIN_NICK="PKI Administrator for domain.com" -
Call an agent-only function with the admin certificate. Replace
caadminwith the value ofpki_admin_uidin thepkispawnconfiguration file if you changed it:$PKI -n "$ADMIN_NICK" ca-user-show caadminExample output:
-------------- User "caadmin" -------------- User ID: caadmin Full name: caadmin Email: caadmin@domain.com Type: adminType State: 1
-
Save the admin certificate and private key as PEM files. Test 10: Generate and verify a new CRL uses them with
curl, which cannot read the client NSS database:openssl pkcs12 -in admin_cert_and_key.p12 \ -passin file:admin_p12_password.txt \ -clcerts -nokeys -out admin_cert.pem openssl pkcs12 -in admin_cert_and_key.p12 \ -passin file:admin_p12_password.txt \ -nocerts -nodes -out admin_private_key.pem chmod 600 admin_private_key.pemadmin_private_key.pemcontains the admin private key unencrypted. Delete it at the end of the tests, as described in Clean up.
-
- Result
-
The test passes if
ca-user-showreturns the admin user over the client-authenticated HTTPS connection. If it fails, check the PKCS #12 password and that the PKCS #12 file exists.
Test 5: Issue a certificate signed by the HSM-protected CA key
- What is tested
-
A new certificate request is submitted, approved by the agent, and issued. The issued certificate is verified against the CA certificate.
- HSM relevance
-
Issuing a certificate requires a signature with the CA signing key, which only exists on the HSM.
- Prerequisites
-
-
The
caUserCertenrollment profile is enabled on the CA.
- Steps
-
-
Choose a unique name for the test user and record the HSM command counter:
TEST_UID=hsmtest-$(date +%Y%m%d%H%M%S) BEFORE=$(hsm_cmds) -
Create a key pair and a certificate request for the test user:
$PKI nss-cert-request --subject "UID=$TEST_UID" \ --ext /usr/share/pki/tools/examples/certs/testuser.conf \ --csr test_user_request.csrThe test user’s key pair is generated in the client NSS database, in software. Only the CA’s signature on the certificate uses the HSM. If
/usr/share/pki/tools/examples/certs/testuser.confdoes not exist, omit the--extoption. -
Submit the request to the CA:
$PKI ca-cert-request-submit --profile caUserCert \ --csr-file test_user_request.csr \ --subject "UID=$TEST_UID"Example output:
----------------------------- Submitted certificate request ----------------------------- Request ID: 0xe1828106f8d1ff5e765153d9669b74c0 Type: enrollment Request Status: pending Operation Result: success ...
-
Approve the request as agent. Replace
<request ID>with theRequest IDfrom the previous step:$PKI -n "$ADMIN_NICK" ca-cert-request-approve <request ID> --forceExample output:
--------------------------------------------------------------- Approved certificate request 0xe1828106f8d1ff5e765153d9669b74c0 --------------------------------------------------------------- Request ID: 0xe1828106f8d1ff5e765153d9669b74c0 Type: enrollment Request Status: complete Operation Result: success Certificate ID: 0xe67dd0bdd4662bf3989553cadf1ca379 ...
The CA signs the certificate with its HSM key when the request is approved.
-
Record the HSM command counter and save the certificate serial number. Replace
<certificate ID>with theCertificate IDfrom the previous step:AFTER=$(hsm_cmds); echo "HSM commands: $((AFTER - BEFORE)) (idle baseline: $IDLE in 5 seconds)" SERIAL=<certificate ID>Example output:
HSM commands: 2077 (idle baseline: 1258 in 5 seconds)
-
Download the issued certificate:
$PKI ca-cert-export $SERIAL --output-file test_user_cert.pem -
Display the subject, issuer, serial number, and key usage of the certificate:
openssl x509 -in test_user_cert.pem -noout \ -subject -issuer -serial -ext keyUsageExample output:
subject=UID=hsmtest-20261023202949 issuer=O=domain.com Security Domain, OU=ca-1, CN=CA Signing Certificate serial=E67DD0BDD4662BF3989553CADF1CA379 X509v3 Key Usage: critical Digital Signature, Non Repudiation, Key Encipherment -
Display the algorithm that the CA’s HSM key signed with:
openssl x509 -in test_user_cert.pem -noout -text | grep -m1 'Signature Algorithm'Example output:
Signature Algorithm: ML-DSA-44
-
Verify the certificate signature against the CA certificate:
openssl verify -CAfile ca_signing_cert.pem test_user_cert.pemExpected output:
test_user_cert.pem: OK
-
- Result
-
The test passes if the request is approved, a certificate is issued, and
openssl verifyreportsOK. An increase in the HSM command counter well above the idle baseline is further evidence that the HSM signed the certificate.
Test 6: OCSP reports the new certificate as good
- What is tested
-
The CA’s OCSP responder is queried for the new certificate before it is revoked.
- HSM relevance
-
The OCSP response is signed with the OCSP signing key on the HSM, and
opensslverifies that signature. - Prerequisites
-
-
Test 5: Issue a certificate signed by the HSM-protected CA key passed.
-
The OCSP responder is reachable on port 8080.
-
- Steps
-
-
Query the OCSP responder, and record the HSM command counter before and after:
BEFORE=$(hsm_cmds) openssl ocsp -issuer ca_signing_cert.pem -cert test_user_cert.pem \ -CAfile ca_signing_cert.pem -url $HTTP_URL/ca/ocsp AFTER=$(hsm_cmds); echo "HSM commands: $((AFTER - BEFORE)) (idle baseline: $IDLE in 5 seconds)"Example output:
Response verify OK test_user_cert.pem: good This Update: Oct 23 20:29:59 2026 GMT HSM commands: 1267 (idle baseline: 1258 in 5 seconds)
-
- Result
-
The test passes if the output contains
Response verify OKand the certificate status isgood. A verification failure points to the OCSP signing key or its certificate.
Test 7: Revoke the certificate
- What is tested
-
The agent revokes the test certificate with the reason
Key_Compromise. - HSM relevance
-
The agent request uses a client-authenticated TLS session with the SSL server key on the HSM. The revocation is recorded in the CA database.
- Prerequisites
- Steps
-
-
Revoke the test certificate as agent:
$PKI -n "$ADMIN_NICK" ca-cert-revoke $SERIAL \ --reason Key_Compromise --forceExample output:
-------------------------------------------------------- Revoked certificate "0xe67dd0bdd4662bf3989553cadf1ca379" -------------------------------------------------------- Serial Number: 0xe67dd0bdd4662bf3989553cadf1ca379 Subject DN: UID=hsmtest-20261023202949 Issuer DN: CN=CA Signing Certificate,OU=ca-1,O=domain.com Security Domain Status: REVOKED ... Revoked On: Fri Oct 23 20:30:02 UTC 2026 Revoked By: caadmin
-
Read the certificate status back from the CA:
$PKI ca-cert-show $SERIALExample output:
Serial Number: 0xe67dd0bdd4662bf3989553cadf1ca379 Subject DN: UID=hsmtest-20261023202949 Issuer DN: CN=CA Signing Certificate,OU=ca-1,O=domain.com Security Domain Status: REVOKED ...
-
- Result
-
The test passes if
ca-cert-showreportsStatus: REVOKED.
Test 8: OCSP reports the certificate as revoked
- What is tested
-
The OCSP responder is queried again after the revocation.
- HSM relevance
-
A new OCSP response is signed with the OCSP signing key on the HSM.
- Prerequisites
-
-
Test 7: Revoke the certificate passed.
-
The OCSP responder is reachable on port 8080.
-
- Steps
-
-
Query the OCSP responder, and record the HSM command counter before and after:
BEFORE=$(hsm_cmds) openssl ocsp -issuer ca_signing_cert.pem -cert test_user_cert.pem \ -CAfile ca_signing_cert.pem -url $HTTP_URL/ca/ocsp AFTER=$(hsm_cmds); echo "HSM commands: $((AFTER - BEFORE)) (idle baseline: $IDLE in 5 seconds)"Example output:
Response verify OK test_user_cert.pem: revoked This Update: Oct 23 20:30:05 2026 GMT Revocation Time: Oct 23 20:30:02 2026 GMT HSM commands: 1268 (idle baseline: 1258 in 5 seconds)
-
- Result
-
The test passes if the output contains
Response verify OKand the certificate status isrevoked.
Test 9: The certificate record is stored in RHDS
- What is tested
-
The test certificate’s entry exists in the CA’s certificate repository in RHDS and shows the revoked status.
- HSM relevance
-
RHDS stores the CA data, not keys. This test confirms that the HSM-signed certificate was persisted.
- Prerequisites
-
-
Test 7: Revoke the certificate passed.
-
RHDS runs on the CA server, with its LDAPI socket in
/run. -
Root autobind is enabled in RHDS.
-
- Steps
-
-
Convert the certificate serial number to decimal. RHDS stores certificates under their decimal serial number:
DEC_SERIAL=$(python3 -c "import sys; print(int(sys.argv[1], 16))" $SERIAL) echo $DEC_SERIALExample output:
306375709918902119035888128361431343993
-
Find the RHDS LDAPI socket:
ls /run/slapd-*.socketExample output:
/run/slapd-ca-1.socket
-
Look up the certificate record in RHDS. In the
ldapi://URL, each/of the socket path is written as%2F:sudo ldapsearch -Y EXTERNAL -Q -LLL \ -H 'ldapi://%2Frun%2Fslapd-ca-1.socket' \ -b "ou=certificateRepository,ou=ca,$BASEDN" \ "(cn=$DEC_SERIAL)" cn certStatusExample output:
dn: cn=306375709918902119035888128361431343993,ou=certificateRepository,ou=ca, o=pki-ca-1-CA cn: 306375709918902119035888128361431343993 certStatus: REVOKED
-
- Result
-
The test passes if
ldapsearchfinds the entry withcertStatus: REVOKED. Ifldapsearchfails to authenticate, root autobind might be disabled in RHDS. In that case, the CA side of the revocation was already verified in Test 7: Revoke the certificate.
Test 10: Generate and verify a new CRL
- What is tested
-
The agent asks the CA to regenerate the MasterCRL. The CRL is downloaded, its signature is verified, its date is checked, and the revoked serial number is looked up. This replaces the Update Revocation List and Display Revocation List steps in the agent web interface.
- HSM relevance
-
The CRL is signed with the CA signing key on the HSM.
- Prerequisites
-
-
Test 4: Agent login with the admin certificate passed, and
admin_cert.pemandadmin_private_key.pemare in the working folder. -
Test 7: Revoke the certificate passed.
-
- Steps
-
-
Download the current CRL and note its number:
curl -sS --max-time 60 -o master_crl.der \ "$HTTP_URL/ca/ee/ca/getCRL?op=getCRL&crlIssuingPoint=MasterCRL" openssl crl -inform DER -in master_crl.der -noout -crlnumberExample output:
crlNumber=0x0F
-
Ask the CA to sign a new CRL now, and record the HSM command counter before and after:
BEFORE=$(hsm_cmds) curl -sS --max-time 120 --cacert ca_signing_cert.pem \ --cert admin_cert.pem --key admin_private_key.pem \ -d 'crlIssuingPoint=MasterCRL&waitForUpdate=true&xml=true' \ $HTTPS_URL/ca/agent/ca/updateCRL AFTER=$(hsm_cmds); echo; echo "HSM commands: $((AFTER - BEFORE)) (idle baseline: $IDLE in 5 seconds)"Example output:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><xml><header><crlIssuingPoint>MasterCRL</crlIssuingPoint><time>16</time></header><fixed/><records/></xml> HSM commands: 1280 (idle baseline: 1258 in 5 seconds)
-
Download the new CRL:
curl -sS --max-time 60 -o master_crl.der \ "$HTTP_URL/ca/ee/ca/getCRL?op=getCRL&crlIssuingPoint=MasterCRL" -
Verify the CRL signature against the CA certificate:
openssl crl -inform DER -in master_crl.der -CAfile ca_signing_cert.pem -nooutExpected output:
verify OK
-
Display the CRL number and issue time:
openssl crl -inform DER -in master_crl.der -noout \ -crlnumber -lastupdate -nextupdate date -uExample output:
crlNumber=0x10 lastUpdate=Oct 23 20:30:07 2026 GMT nextUpdate=Oct 23 21:00:00 2026 GMT Fri Oct 23 20:30:09 UTC 2026
-
Display the signature algorithm and check that the revoked serial number is listed in the CRL:
openssl crl -inform DER -in master_crl.der -noout -text \ | grep -m1 'Signature Algorithm' openssl crl -inform DER -in master_crl.der -noout -text \ | grep -i "Serial Number: ${SERIAL#0x}"Example output:
Signature Algorithm: ML-DSA-44 Serial Number: E67DD0BDD4662BF3989553CADF1CA379
-
- Result
-
The test passes if all of the following are true:
-
The CRL number is higher than before the update, so a new CRL was signed.
-
openssl crlreportsverify OK. -
lastUpdateis within the last 5 minutes. -
The serial number of the certificate revoked in Test 7: Revoke the certificate is listed in the CRL.
-
Test 11: Verify the signed audit log
- What is tested
-
The CA’s signed audit log is verified with
AuditVerify, using the audit signing certificate. - HSM relevance
-
Audit log signatures are made with the audit signing key on the HSM. Valid signatures prove that this key is in use.
- Prerequisites
-
-
Audit log signing is enabled. See (Optional) Enable signed audit logging.
-
The audit signing key is on the HSM token.
- Steps
-
-
Check that audit log signing is enabled, and display the flush interval:
sudo grep -E '^log.instance.SignedAudit.(logSigning|flushInterval)=' $CS_CFGIf
logSigningis nottrue, skip this test. -
Wait for the flush interval (in seconds) plus 5 seconds. The CA signs the audit log each time it flushes its buffer, so this ensures that the entries from the previous tests are signed.
-
Export the audit signing certificate:
sudo pki-server cert-export ca_audit_signing -i $INSTANCE \ --cert-file audit_signing_cert.pem -
Add the certificate to the client NSS database with the
Ptrust flag, whichAuditVerifyrequires. Use the audit signing certificate nickname from Test 3: The CA system keys are stored on the HSM token:certutil -A -d client_nssdb -n "auditSigningCert cert-$INSTANCE CA" \ -t ',,P' -i audit_signing_cert.pem \ -f client_nssdb_password.txt -
Copy the audit log to the working folder, because only
rootcan read it:-
If you enabled audit log signing in (Optional) Enable signed audit logging, copy only the entries written after signing was enabled:
mkdir -p audit_logs sudo tail -n +$((AUDIT_START + 1)) \ /var/log/pki/$INSTANCE/ca/signedAudit/ca_audit > audit_logs/ca_audit printf '%s' audit_logs/ca_audit > audit_log_list.txt -
If audit log signing was already enabled, copy all the audit log files:
mkdir -p audit_logs for f in $(sudo ls -1tr /var/log/pki/$INSTANCE/ca/signedAudit | grep '^ca_audit'); do sudo cat /var/log/pki/$INSTANCE/ca/signedAudit/$f > audit_logs/$f done ls -1tr audit_logs/* | paste -sd, - | tr -d '\n' > audit_log_list.txt
AuditVerifyreads the list of log files to check, separated by commas, fromaudit_log_list.txt. -
-
Verify the audit log signatures:
AuditVerify -d client_nssdb -n "auditSigningCert cert-$INSTANCE CA" \ -a audit_log_list.txt -P '' -vThe output reports the number of valid and invalid signatures.
-
- Result
-
The test passes if
AuditVerifyreports at least one valid signature and no invalid signatures.-
If no signatures are found, the CA has not yet flushed the audit buffer. Wait a few minutes and run
AuditVerifyagain. -
If the signatures are invalid, the log was altered or was not signed by the audit signing key.
-
If
AuditVerifyreportsUnknown signing certificate key type, this version ofAuditVerifycannot verify signatures made with the key type of the audit signing key, for example ML-DSA. This is a limitation of the verification tool, not of the HSM. To confirm that the CA wrote signed entries, count them:grep -c AUDIT_LOG_SIGNING audit_logs/*
-
Test 12: CA restart and unattended HSM token login
- What is tested
-
The CA service is restarted, and it must come back up and sign a new CRL.
- HSM relevance
-
On start-up, the CA must open a session with the HSM and log in to the HSM token using the PIN in
password.conf, without user interaction. - Prerequisites
-
-
The token is a Softcard, or an OCS with K=1. Do not run this test for an OCS with K>1 (
NFAST_NFKM_TOKENSFILEset in/opt/nfast/cknfastrc). -
The token PIN is in
password.conf(hardware-<token>=).
- Steps
-
-
Download the current CRL and note its number:
curl -sS --max-time 60 -o master_crl.der \ "$HTTP_URL/ca/ee/ca/getCRL?op=getCRL&crlIssuingPoint=MasterCRL" openssl crl -inform DER -in master_crl.der -noout -crlnumber -
Restart the CA and wait until it is running:
sudo systemctl restart pki-tomcatd@$INSTANCE wait_for_caIf the CA does not report that it is running within 5 minutes, press Ctrl+C and check
journalctl -u pki-tomcatd@<instance>. A wrong token PIN inpassword.confor an unavailable HSM are the usual causes. -
Ask the CA to sign a new CRL:
curl -sS --max-time 120 --cacert ca_signing_cert.pem \ --cert admin_cert.pem --key admin_private_key.pem \ -d 'crlIssuingPoint=MasterCRL&waitForUpdate=true&xml=true' \ $HTTPS_URL/ca/agent/ca/updateCRL -
Download the CRL and note its number:
curl -sS --max-time 60 -o master_crl.der \ "$HTTP_URL/ca/ee/ca/getCRL?op=getCRL&crlIssuingPoint=MasterCRL" openssl crl -inform DER -in master_crl.der -noout -crlnumber
-
- Result
-
The test passes if the CA restarts, and the CRL number after the restart is higher than before it. If the CA restarted but no new CRL was signed, check the CA debug log for token errors.
Test 13: The CA cannot sign while the HSM is unavailable (expected failure)
- What is tested
-
The nShield hardserver is stopped, and the CA is asked to sign a new CRL. The hardserver is then started, and the CA restarted.
- HSM relevance
-
With the hardserver stopped, the CA has no access to the HSM, so every private-key operation (CRL signing and the TLS handshake) must fail. This proves that the CA keys exist only in the HSM.
- Prerequisites
-
-
The token is a Softcard, or an OCS with K=1.
-
No other application on this server needs the HSM during the test.
|
This test briefly stops the hardserver, which disconnects every application on this server from the HSM. Make sure that you complete the restore steps, even if the test is interrupted. |
- Steps
-
-
Download the current CRL and note its number:
curl -sS --max-time 60 -o master_crl.der \ "$HTTP_URL/ca/ee/ca/getCRL?op=getCRL&crlIssuingPoint=MasterCRL" openssl crl -inform DER -in master_crl.der -noout -crlnumber -
Stop the hardserver, to cut the CA off from the HSM:
sudo /opt/nfast/sbin/init.d-ncipher stop -
Ask the CA to sign a new CRL. This is expected to fail:
curl -sS --max-time 120 --cacert ca_signing_cert.pem \ --cert admin_cert.pem --key admin_private_key.pem \ -d 'crlIssuingPoint=MasterCRL&waitForUpdate=true&xml=true' \ $HTTPS_URL/ca/agent/ca/updateCRL -
Download the CRL and note its number:
curl -sS --max-time 60 -o master_crl.der \ "$HTTP_URL/ca/ee/ca/getCRL?op=getCRL&crlIssuingPoint=MasterCRL" openssl crl -inform DER -in master_crl.der -noout -crlnumberThe CRL number must be the same as before the hardserver was stopped.
-
Restore the HSM connection:
sudo /opt/nfast/sbin/init.d-ncipher start enquiry | grep -m2 modeBoth lines from
enquirymust showoperational. -
Restart the CA so it opens new sessions with the HSM, and wait until it is running:
sudo systemctl restart pki-tomcatd@$INSTANCE wait_for_ca -
Ask the CA to sign a new CRL, and check that the CRL number increases:
curl -sS --max-time 120 --cacert ca_signing_cert.pem \ --cert admin_cert.pem --key admin_private_key.pem \ -d 'crlIssuingPoint=MasterCRL&waitForUpdate=true&xml=true' \ $HTTPS_URL/ca/agent/ca/updateCRL curl -sS --max-time 60 -o master_crl.der \ "$HTTP_URL/ca/ee/ca/getCRL?op=getCRL&crlIssuingPoint=MasterCRL" openssl crl -inform DER -in master_crl.der -noout -crlnumber
-
- Result
-
The test passes if both of the following are true:
-
No new CRL was signed while the hardserver was stopped.
-
After the hardserver was started and the CA restarted, the CA signed a new CRL.
If a CRL was signed while the hardserver was stopped, not all CA keys are on the HSM. Check Test 3: The CA system keys are stored on the HSM token. If the CA did not recover after the hardserver was started, check
journalctl -u pki-tomcatd@<instance>and the output ofenquiry.
-
Clean up
-
If you enabled audit log signing in (Optional) Enable signed audit logging, restore the original
CS.cfg:sudo systemctl stop pki-tomcatd@$INSTANCE sudo cp -p $AUDIT_BACKUP $CS_CFG sudo systemctl start pki-tomcatd@$INSTANCE wait_for_ca sudo grep -E '^log.instance.SignedAudit.logSigning=' $CS_CFGThe CA is stopped first, so it does not rewrite
CS.cfgwhile it is restored. -
Delete the working folder. It contains the token PINs, the admin PKCS #12 password, and the unencrypted admin private key:
cd ~ rm -rf ~/hsm-test