Integrating with a SmartCard-HSM

Note

The instructions on this page are for an Debian 12 host and assume that Cascade has already been installed using our DEB package.

Note

The instructions on this page assume you will be using the Smart Card exclusively for the task at hand and might wipe the content of the SC.

SmartCard-HSM is a lightweight Hardware Security Module in a Smart Card, MicroSD or USB form factors and protect your RSA and ECC keys in hardware. They are accessible through a PKCS #11 interface. You can use them to experiment with PKCS #11 without having to purchase an expensive HSM. (Hint: do not expect wonders in terms of performance.)

https://www.smartcard-hsm.com

_images/smartcard-and-reader.jpg

Install the Prerequisites

# apt install -y opensc opensc-pkcs11

Identify the Card Reader

Your card reader may well be of a different vendor and type.

# opensc-tool -l
# Detected readers (pcsc)
Nr.  Card  Features  Name
0    Yes             Identive CLOUD 2700 R Smart Card Reader [CCID Interface]

Initialize the Smartcard

The card is configured with the SO PIN and user PIN as per the vendor. You can initialize (i.e. fully reset) the card and change these using sc-hsm-tool which is provided in the opensc package:

# sc-hsm-tool --initialize --so-pin 0123012301230123 --pin 123456 --label NL-smartcard
Using reader with a card: Identive CLOUD 2700 R Smart Card Reader [CCID Interface]

Show the card’s slot information

We display a list of available slots and take note of our slot ID (0) to which our card label (NL-smartcard) is associated:

# pkcs11-tool --list-slots
Available slots:
Slot 0 (0x0): Identive CLOUD 2700 R Smart Card Reader [CCID Interface] (536...
  token label        : NL-smartcard (UserPIN)
  token manufacturer : www.CardContact.de
  token model        : PKCS#15 emulated
  token flags        : login required, rng, token initialized, PIN initialized
  hardware version   : 24.13
  firmware version   : 4.1
  serial num         : DECC1206715
  pin min/max        : 6/15

List the Smart Card’s mechanisms

# pkcs11-tool --module opensc-pkcs11.so --list-mechanisms
Using slot 0 with a present token (0x0)
Supported mechanisms:
  SHA-1, digest
  SHA224, digest
  SHA256, digest
  SHA384, digest
  SHA512, digest
  MD5, digest
  RIPEMD160, digest
  GOSTR3411, digest
  ECDSA, keySize={192,521}, hw, sign, verify, EC F_P, EC parameters, EC OID, EC uncompressed
  ECDSA-SHA384, keySize={192,521}, sign, verify
 ...

Configure cascade-hsm-bridge

cascade-hsm-bridge needs to know where to find the OpenSC PKCS#11 module. As PKCS#11 modules are loaded into a host application, any access to resources needed by the PKCS#11 module must be granted to the host application.

# sed -i -e 's|^lib_path = .\+|lib_path = "/usr/lib/x86_64-linux-gnu/opensc-pkcs11.so"|' /etc/cascade-hsm-bridge/config.toml
# systemctl start cascade-hsm-bridge

Create a Cascade Policy that uses your HSM

Create a Cascade policy called smartcard and set it to use the HSM called cascade-hsm-bridge we configured earlier.

# cascade template policy | tee /etc/cascade/policies/smartcard.toml
# sed -i -e 's|^#hsm-server-id = .\+|hsm-server-id = "cascade-hsm-bridge"|' /etc/cascade/policies/smartcard.toml

Start the Cascade daemon:

# systemctl start cascaded
# cascade policy reload
Policies reloaded:
- smartcard added

Configure a HSM in Cascade called cascade-hsm-bridge that will connect to the locally running cascade-hsm-bridge daemon. The username is the slot identifier we found our card in earlier, and the password is the user PIN configured for the card. (username can also be the full token label which in our above example is the complete string NL-smartcard (UserPIN).)

# cascade hsm add --insecure --username 0 --password "123456" cascade-hsm-bridge 127.0.0.1
Added KMIP server 'cascade-hsm-bridge 0.1.0-alpha using PKCS#11 token with label NL-smartcard (UserPIN) in slot Identive CLOUD 2700 R Smart Card Reader [CCID Interface] (536... via library opensc-pkcs11.so'.

Sign a Test Zone with SmartCard-HSM

Create a test zone to load and sign and ensure the Cascade daemon has access to it:

# mkdir /etc/cascade/zones
# cat > /etc/cascade/zones/example.net << EOF
example.net.    3600    IN      SOA     ns.example.net. username.example.net. 1 86400 7200 2419200 300
example.net.            IN      NS      ns
ns                      IN      A       192.0.2.1
EOF
# chown -R cascade: /etc/cascade/zones

Add our test zone to Cascade and associate the policy that we created with the zone:

# cascade zone add --source /etc/cascade/zones/example.net --policy smartcard example.net
Added zone example.net

Check that the zone has been signed, and print out additional information which includes the identifiers of the signing keys that were used:

# cascade zone status example.net --detailed
Status report for zone 'example.net' using policy 'smartcard' Waited for a new version of the example.net zone
✔ Loaded version 1
  Loaded at 2025-10-09T14:58:11+00:00 (26s ago)
  Loaded 196 B and 3 records from the filesystem in 0 seconds
✔ Auto approving signing of version 1, no checks enabled in policy.
✔ Approval received to sign version 1, signing requested
✔ Signed version 1 as version 2025100901
  Signing requested at 2025-10-09T14:58:11+00:00 (26s ago)
  Signing started at 2025-10-09T14:58:11+00:00 (25s ago)
  Signing finished at 2025-10-09T14:58:11+00:00 (25s ago)
  Collected 3 records in 0s, sorted in 0s
  Generated 5 NSEC(3) records in 0s
  Generated 5 signatures in 0s (5 sig/s)
  Inserted signatures in 0s (5 sig/s)
  Took 0s in total, using 2 threads
  Current action: Finished
✔ Auto approving publication of version 2025100901, no checks enabled in policy.
✔ Published version 2025100901
  Published zone available on 127.0.0.1:4543
DNSSEC keys:
  KSK tagged 15202:
    Reference: kmip://cascade-hsm-bridge/keys/CE8E308B232C890B54066E6D3CF85802FB6B27F8_pub?algorithm=13&flags=257
    Actively used for signing
  ZSK tagged 43092:
    Reference: kmip://cascade-hsm-bridge/keys/870D4E7E7A1C89A14D3A8FD14BDC953D249093D9_pub?algorithm=13&flags=256
    Actively used for signing
   ...

Inspect the SmartCard HSM

Use the pkcs11-tool program from the opensc package installed earlier to list objects on the SmartCard-HSM. Initially the card will likely be empty, but after Cascade has created some keys you should see the objects on the card.

# pkcs11-tool --module opensc-pkcs11.so --list-objects
Public Key Object; EC  EC_POINT 256 bits
  EC_POINT:   044104084d2c0a3b1645ef07e898526d2cac0a44d127703209dcd98d484c14dafb7cfa035d7bc903a6b695ecfd830c610be390ba2fc9580aa700d23d606a370da1e9ca
  EC_PARAMS:  06082a8648ce3d030107
  label:      example.net-15202-ksk-pri
  ID:         ce8e308b232c890b54066e6d3cf85802fb6b27f8
  Usage:      verify
  Access:     none

Note how the key tag or key IDs created by Cascade match the labels on the Smart Card: <zone name>-<key tag>-<key type>-pri.

End.

— Contributed by Jan-Piet Mens