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

Test 1

The HSM and Security World are usable.

Yes

Test 2

The CA service is running and serving HTTPS.

Yes

Test 3

The CA system keys are stored on the HSM token.

Yes

Test 4

Agent login with the admin certificate.

Yes

Test 5

Issue a certificate signed by the HSM-protected CA key.

Yes

Test 6

OCSP reports the new certificate as good.

Yes

Test 7

Revoke the certificate.

Yes

Test 8

OCSP reports the certificate as revoked.

Yes

Test 9

The certificate record is stored in RHDS.

Yes

Test 10

Generate and verify a new CRL.

Yes

Test 11

Verify the signed audit log.

Only if audit log signing is enabled

Test 12

CA restart and unattended HSM token login.

Optional

Test 13

The CA cannot sign while the HSM is unavailable (expected failure).

Optional

Test 12 and Test 13 restart the CA without user interaction. Do not run them if the CA keys are protected by an OCS with K>1, because the CA can then only start under preload with the cards inserted.

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 Softcard testSC, and the host name pki.domain.com.

  • You can log in to the CA server as a user with sudo privileges.

  • You know the admin PKCS #12 password (pki_client_pkcs12_password in the pkispawn configuration 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.

  1. Create and navigate to a private working folder:

    mkdir -m 700 ~/hsm-test
    cd ~/hsm-test
    export PATH=$PATH:/opt/nfast/bin

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

  2. Set the following shell variables. Replace ca-1 and testSC with 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
  3. 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_cmds reads 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.

  4. Check that the hardserver and the CA are running:

    enquiry | grep -m2 mode
    curl -sk $HTTPS_URL/ca/admin/ca/getStatus

    Both lines from enquiry must show operational, and the CA must report "Status" : "running".

    If enquiry fails, 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
  5. Record the token protection. For a Softcard, the token name is listed by nfkminfo -s. For an OCS, it is listed by nfkminfo -c, together with its K/N quorum:

    nfkminfo -s
    nfkminfo -c

    If the token is an OCS with K>1, check that /opt/nfast/cknfastrc contains NFAST_NFKM_TOKENSFILE, and do not run the following tests:

  6. Check which entries the CA password file contains, without displaying their values:

    sudo ls -l $PW_CONF
    sudo cut -d= -f1 $PW_CONF

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

    • internal is the password of the CA’s NSS database.

    • internaldb is 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:

  1. Check the current audit signing settings:

    sudo grep -E \
      '^log.instance.SignedAudit.(logSigning|signedAuditCertNickname|flushInterval)=' \
      $CS_CFG

    If the output contains log.instance.SignedAudit.logSigning=true, audit log signing is already enabled. Skip the rest of this procedure.

  2. Back up CS.cfg:

    AUDIT_BACKUP=$CS_CFG.bak.$(date +%Y%m%d%H%M%S)
    sudo cp -p $CS_CFG $AUDIT_BACKUP
  3. Stop the CA, so it does not overwrite your changes to CS.cfg:

    sudo systemctl stop pki-tomcatd@$INSTANCE
  4. If signedAuditCertNickname is 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"
  5. Enable audit log signing:

    sudo pki-server ca-config-set -i $INSTANCE \
      log.instance.SignedAudit.logSigning true
  6. 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
  7. Start the CA and wait until it is running:

    sudo systemctl start pki-tomcatd@$INSTANCE
    wait_for_ca
  8. Confirm the new settings:

    sudo grep -E \
      '^log.instance.SignedAudit.(logSigning|signedAuditCertNickname)=' \
      $CS_CFG

    At 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
  1. Check the HSM module mode:

    enquiry

    Example 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
  2. Check the Security World and module state:

    nfkminfo

    Example 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
    ...
  3. 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 enquiry shows mode operational for module #1, and nfkminfo shows Usable in the state of both the World and module #1.

Test 2: The CA service is running and serving HTTPS

What is tested

The pki-tomcatd service 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
Steps
  1. Check that the CA service is running:

    sudo systemctl is-active pki-tomcatd@$INSTANCE

    Expected output:

    active
  2. Record the CA state, ports, and URLs:

    sudo pki-server status $INSTANCE

    Example 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
  3. 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
  4. 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/getStatus

    Example 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 active and getStatus returns "Status" : "running" over a verified TLS connection. If the test fails, check journalctl -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
Steps
  1. Copy the token PINs from password.conf into 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
  2. List the CA system certificates:

    sudo pki-server cert-find -i $INSTANCE

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

  3. List the private keys on the HSM token:

    sudo certutil -K -d $ALIAS_DIR -h $TOKEN -f hsm_token_pin.txt

    Example 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
  4. List the private keys in the internal software token:

    sudo certutil -K -d $ALIAS_DIR -f internal_token_pin.txt

    Expected output:

    certutil: Checking token "NSS Certificate DB" in slot "NSS User Private Key and Certificate Services"
    certutil: no keys found

    certutil exits 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-find is 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
Steps
  1. 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
  2. Create a random password for the client NSS database:

    head -c 24 /dev/urandom | base64 | tr -d '\n' > client_nssdb_password.txt
  3. Copy the admin PKCS #12 file, which only root can read, to the working folder:

    sudo cat /root/.dogtag/$INSTANCE/ca_admin_cert.p12 > admin_cert_and_key.p12
  4. Define the common pki client options (server URL, client NSS database, and its password file):

    PKI="pki -U $HTTPS_URL -d client_nssdb -C client_nssdb_password.txt"
  5. Create the client NSS database, which takes the place of Firefox:

    $PKI client-init --force
  6. Import and trust the CA signing certificate:

    $PKI client-cert-import "CA Certificate" --ca-cert ca_signing_cert.pem

    Expected output:

    Imported certificate "CA Certificate"
  7. Import the admin certificate and key:

    $PKI pkcs12-import --pkcs12 admin_cert_and_key.p12 \
      --password-file admin_p12_password.txt
  8. Find the nickname of the imported admin certificate. It is the certificate with the trust attributes u,u,u:

    certutil -L -d client_nssdb

    Example output:

    Certificate Nickname                                         Trust Attributes
                                                                 SSL,S/MIME,JAR/XPI
    
    CA Certificate                                               CT,C,C
    PKI Administrator for domain.com                             u,u,u
  9. Save the nickname in a variable:

    ADMIN_NICK="PKI Administrator for domain.com"
  10. Call an agent-only function with the admin certificate. Replace caadmin with the value of pki_admin_uid in the pkispawn configuration file if you changed it:

    $PKI -n "$ADMIN_NICK" ca-user-show caadmin

    Example output:

    --------------
    User "caadmin"
    --------------
      User ID: caadmin
      Full name: caadmin
      Email: caadmin@domain.com
      Type: adminType
      State: 1
  11. 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.pem

    admin_private_key.pem contains 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-show returns 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
Steps
  1. 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)
  2. 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.csr

    The 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.conf does not exist, omit the --ext option.

  3. 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
    ...
  4. Approve the request as agent. Replace <request ID> with the Request ID from the previous step:

    $PKI -n "$ADMIN_NICK" ca-cert-request-approve <request ID> --force

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

  5. Record the HSM command counter and save the certificate serial number. Replace <certificate ID> with the Certificate ID from 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)
  6. Download the issued certificate:

    $PKI ca-cert-export $SERIAL --output-file test_user_cert.pem
  7. Display the subject, issuer, serial number, and key usage of the certificate:

    openssl x509 -in test_user_cert.pem -noout \
      -subject -issuer -serial -ext keyUsage

    Example 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
  8. 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
  9. Verify the certificate signature against the CA certificate:

    openssl verify -CAfile ca_signing_cert.pem test_user_cert.pem

    Expected output:

    test_user_cert.pem: OK
Result

The test passes if the request is approved, a certificate is issued, and openssl verify reports OK. 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 openssl verifies that signature.

Prerequisites
Steps
  1. 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 OK and the certificate status is good. 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
  1. Revoke the test certificate as agent:

    $PKI -n "$ADMIN_NICK" ca-cert-revoke $SERIAL \
      --reason Key_Compromise --force

    Example 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
  2. Read the certificate status back from the CA:

    $PKI ca-cert-show $SERIAL

    Example 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-show reports Status: 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
Steps
  1. 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 OK and the certificate status is revoked.

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
Steps
  1. 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_SERIAL

    Example output:

    306375709918902119035888128361431343993
  2. Find the RHDS LDAPI socket:

    ls /run/slapd-*.socket

    Example output:

    /run/slapd-ca-1.socket
  3. 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 certStatus

    Example output:

    dn: cn=306375709918902119035888128361431343993,ou=certificateRepository,ou=ca,
     o=pki-ca-1-CA
    cn: 306375709918902119035888128361431343993
    certStatus: REVOKED
Result

The test passes if ldapsearch finds the entry with certStatus: REVOKED. If ldapsearch fails 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
Steps
  1. 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

    Example output:

    crlNumber=0x0F
  2. 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)
  3. Download the new CRL:

    curl -sS --max-time 60 -o master_crl.der \
      "$HTTP_URL/ca/ee/ca/getCRL?op=getCRL&crlIssuingPoint=MasterCRL"
  4. Verify the CRL signature against the CA certificate:

    openssl crl -inform DER -in master_crl.der -CAfile ca_signing_cert.pem -noout

    Expected output:

    verify OK
  5. Display the CRL number and issue time:

    openssl crl -inform DER -in master_crl.der -noout \
      -crlnumber -lastupdate -nextupdate
    date -u

    Example 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
  6. 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 crl reports verify OK.

  • lastUpdate is 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
Steps
  1. Check that audit log signing is enabled, and display the flush interval:

    sudo grep -E '^log.instance.SignedAudit.(logSigning|flushInterval)=' $CS_CFG

    If logSigning is not true, skip this test.

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

  3. Export the audit signing certificate:

    sudo pki-server cert-export ca_audit_signing -i $INSTANCE \
      --cert-file audit_signing_cert.pem
  4. Add the certificate to the client NSS database with the P trust flag, which AuditVerify requires. 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
  5. Copy the audit log to the working folder, because only root can 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

    AuditVerify reads the list of log files to check, separated by commas, from audit_log_list.txt.

  6. Verify the audit log signatures:

    AuditVerify -d client_nssdb -n "auditSigningCert cert-$INSTANCE CA" \
      -a audit_log_list.txt -P '' -v

    The output reports the number of valid and invalid signatures.

Result

The test passes if AuditVerify reports 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 AuditVerify again.

  • If the signatures are invalid, the log was altered or was not signed by the audit signing key.

  • If AuditVerify reports Unknown signing certificate key type, this version of AuditVerify cannot 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
  • Test 10: Generate and verify a new CRL passed.

  • The token is a Softcard, or an OCS with K=1. Do not run this test for an OCS with K>1 (NFAST_NFKM_TOKENSFILE set in /opt/nfast/cknfastrc).

  • The token PIN is in password.conf (hardware-<token>=).

Steps
  1. 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
  2. Restart the CA and wait until it is running:

    sudo systemctl restart pki-tomcatd@$INSTANCE
    wait_for_ca

    If 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 in password.conf or an unavailable HSM are the usual causes.

  3. 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
  4. 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

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
  1. 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
  2. Stop the hardserver, to cut the CA off from the HSM:

    sudo /opt/nfast/sbin/init.d-ncipher stop
  3. 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
  4. 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

    The CRL number must be the same as before the hardserver was stopped.

  5. Restore the HSM connection:

    sudo /opt/nfast/sbin/init.d-ncipher start
    enquiry | grep -m2 mode

    Both lines from enquiry must show operational.

  6. 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
  7. 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 of enquiry.

Clean up

  1. 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_CFG

    The CA is stopped first, so it does not rewrite CS.cfg while it is restored.

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