1.0 Introduction
This document describes the steps to configure Fortanix Data Security Manager (DSM) PKCS#11 for Linux Unified Key Setup (LUKS) volume encryption and decryption using the systemd-cryptenroll tool.
Fortanix DSM PKCS#11 can be enrolled into a LUKS2-encrypted volume and used to unlock the volume during boot or manual decryption operations.
The token enrollment process requires a PKCS#11 URI associated with an RSA key pair and X.509 certificate generated in Fortanix DSM using the same key pair. The RSA public certificate encrypts the randomly generated Volume Master Key (VMK), which is then stored into the LUKS2 JSON token header. During volume decryption, the corresponding private key decrypts the VMK.
2.0 Definition
Linux Unified Key Setup (LUKS) - Linux Unified Key Setup (LUKS) provides tools that simplify managing encrypted devices. With LUKS, you can encrypt block devices and enable multiple user keys to decrypt a master key. For bulk encryption of the partition, use this master key. Fortanix provides connectors for the user to integrate LUKS with the Fortanix DSM.
3.0 Product Versions Tested
The following product versions were tested:
Fortanix DSM version 5.6
Fortanix DSM PKCS#11 5.6.2919
4.0 Prerequisites
Ensure the following:
Ubuntu 24.04 Virtual Machine (VM) with systemd version 255
OpenSC is installed
Fortanix DSM version 5.6 or later
Fortanix DSM PKCS#11 5.6.2919 or later
5.0 Architecture Workflow
This section provides an overview of the LUKS encryption and decryption workflow using Fortanix DSM PKCS#11 integration.
When a disk is encrypted using LUKS, a random Volume Master Key (VMK) is generated to encrypt the data on the disk. Initially, this VMK is protected using a user-defined passphrase.
Fortanix DSM is then used to generate an RSA key pair and X.509 certificate through the PKCS#11 interface.
During the PKCS#11 enrollment process, the public key from the certificate is used to encrypt the VMK, and the encrypted VMK is stored in the LUKS2 header.
During decryption, the Fortanix PKCS#11 token uses the corresponding private key to decrypt the VMK, allowing the encrypted volume to be unlocked and mounted. The decryption process requires the Fortanix token PIN for authentication.

Figure 1: Encryption workflow

Figure 2: Decryption workflow
6.0 Configure Fortanix DSM
A Fortanix DSM service must be configured, and the URL must be accessible. To create a Fortanix DSM account and group, refer to the following sections:
6.1 Signing Up
To get started with the Fortanix DSM cloud service, you must register an account at <Your_DSM_Service_URL>. For example, https://amer.smartkey.io. On-premises customers use the KMS URL, and the SaaS customers can use the URLs as listed here based on the application region.
For more information on how to set up the Fortanix DSM, refer to the User's Guide: Sign Up for Fortanix Data Security Manager SaaS.
6.2 Creating an Account
Access <Your_DSM_Service_URL> in a web browser and enter your credentials to log in to Fortanix DSM.

Figure 3: Logging in
For more information on how to set up an account in Fortanix DSM, refer to the User's Guide: Getting Started with Fortanix Data Security Manager - UI.
6.3 Creating a Group
Perform the following steps to create a group in the Fortanix DSM:
In the DSM left navigation panel, click the Groups menu item, and then click ADD GROUP to create a new group.

Figure 4: Add groups
On the Adding new group page, do the following:
Title: Enter a name for your group.
Description (optional): Enter a short description of the group.
Click SAVE to create the new group.
The new group is added to the Fortanix DSM successfully.
6.4 Creating an Application
Perform the following steps to create an app in the Fortanix DSM:
In the DSM left navigation panel, click the Apps menu item, and then click ADD APP to create a new app.

Figure 5: Add application
On the Adding new app page, do the following:
App name: Enter the name for your application.
ADD DESCRIPTION (optional): Enter a short description of the application.
Authentication method: Select the default API Key as the authentication method from the drop-down menu. For more information on this authentication method, refer to the User's Guide: Authentication.
Assigning the new app to groups: Select the group created in Section 6.3: Creating a Groupfrom the list.
Click SAVE to add the new application.
The new application is added to the Fortanix DSM successfully.
6.5 Copying the API Key
Perform the following steps to copy the API key from the Fortanix DSM:
In the DSM left navigation panel, click the Apps menu item, and then click the app created in Section 6.4: Creating an Application to go to the detailed view of the app.
On the INFO tab, click VIEW API KEY DETAILS.
From the API Key Details dialog box, copy the API Key of the app to use in Section 7.0: Configure PKCS#11 on the VM.
6.6 Copying the App UUID
Perform the following steps to copy the app UUID from the Fortanix DSM:
In the DSM left navigation panel, click the Apps menu item, and then click the app created in Section 6.4: Creating an Application to go to the detailed view of the app.
From the top of the app’s page, click the copy icon next to the app UUID to copy it to use it later.
7.0 Configure PKCS#11 on the VM
This section describes the steps to configure PKCS#11 in the VM.
Ensure that the Ubuntu VM has systemd-cryptenroll version 255 installed.
Perform the following steps to configure PKCS#11 in VM:
Run the following command to verify the Ubuntu OS version:
cat /etc/os-releaseRun the following command to verify the installed systemd-cryptenroll version:
systemd-cryptenroll --versionRun the following command to verify if OpenSC and OpenSSL PKCS#11 engine are installed:
apt list opensc openssl engine pkcs11If not installed, run the following command to install OpenSC and OpenSSL PKCS#11 engine:
apt install opensc apt install libengine-pkcs11-opensslRun the following command to create the
openssl.cnffile and add the associated configuration. This configuration is used later for certificate generation.vi /root/openssl.cnf # PKCS11 engine config openssl_conf = openssl_def [openssl_def] engines = engine_section [req] distinguished_name = req_distinguished_name [req_distinguished_name] # empty [engine_section] pkcs11 = pkcs11_section [pkcs11_section] engine_id = pkcs11 #openssl pkcs11 engine library path dynamic_path = /usr/lib/x86_64-linux-gnu/engines-3/libpkcs11.so MODULE_PATH = /etc/fortanix/libpkcs11_fortanix.so #Fortanix pkcs11 path init = 1Where,
dynamic_path: Specifies the OpenSSL PKCS#11 engine library path.MODULE_PATH: Specifies the Fortanix PKCS#11 library path.
Run the following command to create the /etc/fortanix directory and copy the Fortanix PKCS#11 library. You can download the latest Fortanix PKCS#11 library from the PKCS#11.
mkdir –p /etc/fortanixRun the following command to create the /etc/pkcs11/modules directory:
mkdir -p /etc/pkcs11/modulesRun the following command to navigate to the directory:
cd /etc/pkcs11/modulesRun the following command to create the
fortanix.modulefile and add the associated configuration:vi fortanix.module module: /etc/fortanix/libpkcs11_fortanix.so #(This is the location of fortanix pkcs11 lib)Where,
/etc/fortanix/libpkcs11_fortanix.sois the location of the Fortanix PKCS#11 library.You can create the
pkcs11.conffile in the /etc/fortanix directory using one of the following authentication methods:Using API key:
Run the following command to create the
pkcs11.conffile and add the associated configuration:vi /etc/fortanix/pkcs11.conf api_key = "<api key>" api_endpoint = "<fortanix dsm url" [log] file = "/etc/fortanix/pkcs11.log" level = "info"Where,
<api key>: Specifies the Fortanix DSM app API key.<fortanix dsm url>: Specifies the Fortanix DSM URL.
Using certificate:
Run the following command to set the OpenSSL configuration environment variable:
export OPENSSL_CONF=/root/openssl.cnfRun the following command to generate the client certificate:
openssl req -newkey rsa:2048 -nodes -keyout private.key -x509 -days 365 -out certificate.crt -subj "/C=US/ST=California/L=Mountain View/O=Fortanix, Inc./OU=SE/CN=<Fortanix APP UUID>"Where,
<Fortanix APP UUID>refers to the Fortanix DSM app UUID copied in Section 6.6: Copying the App UUID.
Run the following command to convert the private key file to PKCS#8 PEM format:
openssl pkcs8 -topk8 -in private.key -out private.pem -nocryptRun the following command to create the
pkcs#11.conffile and add the associated configuration:vi /etc/fortanix/pkcs11.conf api_endpoint = "<fortanix dsm url>" #use the certificate fortanix endpoint cert_file = "/root/certificate.crt" # X.509 PEM client certificate key_file = "/root/private.pem" # PKCS#8 PEM client private key app_id = "<app uuid>" [log] file = "/etc/fortanix/pkcs11.log"Where,
api_endpoint: Specifies the Fortanix DSM URL used for certificate authentication.cert_file: Specifies the X.509 PEM client certificate.key_file: Specifies the PKCS#8 PEM private key.app_id: Specifies the Fortanix DSM app UUID as copied in Section 6.6: Copying the App UUID.
8.0 Select a Partition for LUKS Encryption
Run the following command to identify the partition to use for LUKS encryption:
lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 4G 0 disk
└─sda1 8:1 0 4G 0 part
sdb 8:16 0 30G 0 disk
├─sdb1 8:17 0 29G 0 part /
├─sdb14 8:30 0 4M 0 part
├─sdb15 8:31 0 106M 0 part /boot/efi
└─sdb16 259:0 0 913M 0 part /boot
sr0 11:0 1 1024M 0 rom
#sdb is boot disk, hence never choose that9.0 Configure LUKS Encryption on the Partition
This section describes the steps to initialize the selected partition as a LUKS2-encrypted volume.
Perform the following steps to execute LUKS encryption on the disk:
Run the following command to perform LUKS encryption on the partition:
cryptsetup luksFormat --type luks2 <device name>This command prompts for a passphrase. However, this is a temporary passphrase until the Fortanix DSM is enrolled.
For example,
cryptsetup luksFormat --type luks2 /dev/sda1 WARNING: Device /dev/sda1 already contains a 'ext4' superblock signature. WARNING! ======== This will overwrite data on /dev/sda1 irrevocably. Are you sure? (Type 'yes' in capital letters): YES Enter passphrase for /dev/sda1: Verify passphrase:Run the following command to retrieve the LUKS UUID:
cryptsetup luksUUID <device name>For example,
cryptsetup luksUUID /dev/sda1 eae667fa-78c0-462d-bc55-1761fc82f556Use the UUID as the LUKS partition instead of
/dev/sdX.For example,
/dev/disk/by-uuid/eae667fa-78c0-462d-bc55-1761fc82f556.Once the luksFormat command is successfully executed, a random VMK is generated for disk encryption. The VMK is encrypted using the passphrase provided in Step 1.
Run the following command to view the encrypted VMK stored in the LUKS header:
cryptsetup luksDump /dev/disk/by-uuid/<luks_uuid>For example,
cryptsetup luksDump /dev/disk/by-uuid/eae667fa-78c0-462d-bc55-1761fc82f556 LUKS header information Version: 2 Epoch: 3 Metadata area: 16384 [bytes] Keyslots area: 16744448 [bytes] UUID: eae667fa-78c0-462d-bc55-1761fc82f556 Label: (no label) Subsystem: (no subsystem) Flags: (no flags) Data segments: 0: crypt offset: 16777216 [bytes] length: (whole device) cipher: aes-xts-plain64 sector: 4096 [bytes] Keyslots: 0: luks2 Key: 512 bits Priority: normal Cipher: aes-xts-plain64 Cipher key: 512 bits PBKDF: argon2id Time cost: 4 Memory: 596768 Threads: 1 Salt: 9d 20 9c 8d 22 bc 3e 66 3b 84 bd 88 4a b2 b2 2f 24 14 23 58 49 7b 1c 20 6b ea df 73 46 da ed fb AF stripes: 400 AF hash: sha256 Area offset:32768 [bytes] Area length:258048 [bytes] Digest ID: 0 Tokens: Digests: 0: pbkdf2 Hash: sha256 Iterations: 86459 Salt: bc 53 cc ec 87 69 c9 4c 42 28 0c 43 86 d2 ee ac a3 11 b5 d5 a5 a3 eb 52 1e e8 7f ec 39 7f 97 44 Digest: 9f 01 38 1e 20 eb 25 d1 22 13 e6 f8 cf 00 03 3a 1a ae fd 83 60 c6 06 7a 0c 34 39 b0 be 96 00 3bRun the following command to verify that the LUKS partition type is
crypto_LUKS:blkidFor example,
/dev/sdb15: LABEL_FATBOOT="UEFI" LABEL="UEFI" UUID="5573-EA9A" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="3ade8d06-ab2f-4d2e-885d-28e719535161" /dev/sdb1: LABEL="cloudimg-rootfs" UUID="a0dd6a92-c277-479a-ab27-5aa833b1fc8a" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="dfaea228-caf1-4987-8b16-70e9f1db2ac4" /dev/sdb16: LABEL="BOOT" UUID="00766405-b790-42b9-8c51-a6276ed8ac7a" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="58c3a1fa-0333-4ba9-bc35-7c14a31e18f3" /dev/sda1: UUID="eae667fa-78c0-462d-bc55-1761fc82f556" TYPE="crypto_LUKS" PARTUUID="f4a8f1f8-01" /dev/sdb14: PARTUUID="06746839-ae2a-4e30-95ce-6b5bec88bdfb"
10.0 Enroll the Fortanix PKCS#11 Token into LUKS Volume
This section describes the steps to generate an RSA key pair in Fortanix DSM using pkcs11-tool and create an X.509 certificate using the generated key.
Perform the following steps to enroll Fortanix PKCS#11 into LUKS volume:
Run the following command to generate an RSA key pair in Fortanix DSM:
pkcs11-tool --module /etc/fortanix/libpkcs11_fortanix.so --login --pin file:///etc/fortanix/pkcs11.conf -k --id `uuidgen | tr -d -` --label "LuksKey" --key-type rsa:2048Ensure to copy the generated key ID. The same key ID is used later while uploading the X.509 certificate.
For example,
Using slot 0 with a present token (0x0) Key pair generated: Private Key Object; RSA label: LuksKey ID: 44c45d8e302d4b56b3c0a8cf177d98d4 warning: PKCS11 function C_GetAttributeValue(SIGN_RECOVER) failed: rv = CKR_ATTRIBUTE_TYPE_INVALID (0x12) Usage: decrypt, sign, unwrap Access: sensitive, always sensitive, never extractable, local Public Key Object; RSA 2048 bits label: LuksKey ID: 44c45d8e302d4b56b3c0a8cf177d98d4 warning: PKCS11 function C_GetAttributeValue(VERIFY_RECOVER) failed: rv = CKR_ATTRIBUTE_TYPE_INVALID (0x12) Usage: encrypt, verify, wrap Access: localRun the following commands to create an X.509 certificate using the OpenSSL PKCS#11 engine:
export OPENSSL_CONF=/root/openssl.cnf export FORTANIX_PKCS11_NUM_SLOTS=1 openssl req -new -x509 -days 365 -sha256 -engine pkcs11 -keyform engine -key pkcs11:object=LuksKey -out lukscert.crt -subj "/CN=test.example.com" 2>/dev/nullEnsure that the OpenSSL PKCS#11 engine is installed and configured in the
openssl.conffile.Run the following command to upload the certificate generated above to Fortanix DSM using
pkcs11-tool, using the same key ID generated in Step 1.pkcs11-tool --module /etc/fortanix/libpkcs11_fortanix.so --login --pin file:///etc/fortanix/pkcs11.conf --write-object lukscert.crt --type cert --label "lukscert" --id 44c45d8e302d4b56b3c0a8cf177d98d4 Using slot 0 with a present token (0x0)For example,
Created certificate: Certificate Object; type = X.509 cert label: lukscert subject: DN: CN=test.example.com serial: 44717214617E8481FD5B24A065E831EEAAFBCCC0 ID: 44c45d8e302d4b56b3c0a8cf177d98d4Run the following command to encode the key ID to use in the PKCS#11 URI:
echo "44c45d8e302d4b56b3c0a8cf177d98d4"| perl -pe 's/(..)/pack("H2",$1)/ge' | perl -pe 's/(.)/sprintf("%%%02x",ord($1))/ge'Sample output:
%44%c4%5d%8e%30%2d%4b%56%b3%c0%a8%cf%17%7d%98%d4Sample URI:
pkcs11:token=Fortanix%20Token;id=%44%c4%5d%8e%30%2d%4b%56%b3%c0%a8%cf%17%7d%98%d4Run the following command to enroll the Fortanix PKCS#11 token into the LUKS volume:
systemd-cryptenroll --pkcs11-token-uri "pkcs11:token=Fortanix%20Token;id=%44%c4%5d%8e%30%2d%4b%56%b3%c0%a8%cf%17%7d%98%d4" /dev/disk/by-uuid/eae667fa-78c0-462d-bc55-1761fc82f556Ensure to enter the existing LUKS passphrase and press Enter for the Fortanix Token PIN when prompted.
Sample output:
🔐 Please enter current passphrase for disk /dev/disk/by-uuid/eae667fa-78c0-462d-bc55-1761fc82f556: •••• 🔐 Please enter PIN for security token 'Fortanix Token' in order to unlock volume enrollment operation: •••••••••••••••••••••••••••••••• Successfully logged into security token 'Fortanix Token'. New PKCS#11 token enrolled as key slot 1.Once the token is enrolled, a new key slot is created in the LUKS header. The VMK is encrypted using the public certificate associated with the enrolled PKCS#11 token and stored under the new key slot in the LUKS header.
cryptsetup luksDump /dev/disk/by-uuid/eae667fa-78c0-462d-bc55-1761fc82f556Ensure to verify the systemd-pkcs11 token entry and associated key slot in the output.
Sample output:
LUKS header information Version: 2 Epoch: 5 Metadata area: 16384 [bytes] Keyslots area: 16744448 [bytes] UUID: eae667fa-78c0-462d-bc55-1761fc82f556 Label: (no label) Subsystem: (no subsystem) Flags: (no flags) Data segments: 0: crypt offset: 16777216 [bytes] length: (whole device) cipher: aes-xts-plain64 sector: 4096 [bytes] Keyslots: 0: luks Key: 512 bits Priority: normal Cipher: aes-xts-plain64 Cipher key: 512 bits PBKDF: argon2id Time cost: 4 Memory: 596768 Threads: 1 Salt: 9d 20 9c 8d 22 bc 3e 66 3b 84 bd 88 4a b2 b2 2f 24 14 23 58 49 7b 1c 20 6b ea df 73 46 da ed fb AF stripes: 4000 AF hash: sha256 Area offset:32768 [bytes] Area length:258048 [bytes] Digest ID: 0 1: luks2 Key: 512 bits Priority: normal Cipher: aes-xts-plain64 Cipher key: 512 bits PBKDF: pbkdf2 Hash: sha512 Iterations: 1000 Salt: 5d 85 d3 71 bb 50 a6 b4 3d 76 12 dd 57 a6 95 9b 93 e8 6c 2e 37 7c 19 44 cc b3 b4 41 71 03 2d 4e AF stripes: 4000 AF hash: sha512 Area offset:290816 [bytes] Area length:258048 [bytes] Digest ID: 0 Tokens: 0: systemd-pkcs11 pkcs11-uri: pkcs11:token=Fortanix%20Token;id=%44%c4%5d%8e%30%2d%4b%56%b3%c0%a8%cf%17%7d%98%d4 pkcs11-key: 44 1f b9 67 79 f3 11 88 23 60 41 6b 99 44 49 af 3c 97 8f 80 d5 c1 c7 c3 f5 0b 94 6d af 02 51 da 17 b0 e5 6e 98 3c 0d 7b 40 dd d5 c3 06 68 b6 be 8e f5 47 bb c0 f4 cd 75 3d bf 97 4e 57 f9 85 d4 50 23 20 46 c3 13 52 66 50 6c 1d ba 9d 93 c2 0f 8d 31 dd d4 40 75 97 fe 89 0e 0a be 18 10 60 86 24 76 3a f1 eb 56 d6 e3 18 f4 21 a0 17 c4 9d b4 3b e0 6d 3f 78 12 ab a0 19 c4 46 52 df 23 75 e8 28 e9 65 bc ac 41 91 9b db 61 1d b9 a6 76 6f 0d c0 26 b0 5a 15 4b ed 2e 42 9a 74 9e a3 5b a8 cc f7 61 55 03 8b 1d 63 af b6 dd 11 5e 5c a0 eb d9 2a c6 5d 86 92 27 da e8 20 98 3d a6 2f 31 70 09 cb 78 9f 17 96 b5 31 4b f5 ec ae 1b 90 02 9d 71 38 c9 0a 49 a5 18 e8 6e 02 c7 bc 4f 2a a4 36 42 21 5f 95 d3 6f b3 e3 cd 00 d4 a6 7b 34 eb 00 41 d1 71 3b 14 dd 5e c9 b0 82 8f 28 c3 ab a2 9d 0b Keyslot: 1 Digests: 0: pbkdf2 Hash: sha256 Iterations: 86459 Salt: bc 53 cc ec 87 69 c9 4c 42 28 0c 43 86 d2 ee ac a3 11 b5 d5 a5 a3 eb 52 1e e8 7f ec 39 7f 97 44 Digest: 9f 01 38 1e 20 eb 25 d1 22 13 e6 f8 cf 00 03 3a 1a ae fd 83 60 c6 06 7a 0c 34 39 b0 be 96 00 3bNOTE
LUKS allows the creation of recovery keys that can be used to unlock the LUKS volume if the PKCS#11 token is lost. These are similar to regular passphrases; however, they are randomly generated on the computer and thus generally have higher entropy than user-chosen passphrases. Their character set is designed to ensure they are easy to type while maintaining high entropy. They may also be scanned off-screen using QR codes. Recovery keys may be used for unlocking LUKS2 volumes wherever passphrases are accepted. They are intended to be used in combination with an enrolled hardware security token as a recovery option when the token is lost. For more information, refer to the systemd-cryptenroll documentation.
Run the following command to test decryption using the enrolled PKCS#11 token:
echo "file:///etc/fortanix/pkcs11.conf" | cryptsetup open --key-slot 1 --token-only /dev/disk/by-uuid/eae667fa-78c0-462d-bc55-1761fc82f556 myvolSample output:
Successfully logged into security token 'Fortanix Token'. Successfully decrypted key with security token.Run the following command to verify that the mapped device is enrolled:
/dev/mapper# ls -ltrSample output:
total 0 crw------- 1 root root 10, 236 Sep 4 11:50 control lrwxrwxrwx 1 root root 7 Sep 4 12:36 myvol -> ../dm-0 ###Close it####Run the following command to close the mapped LUKS volume:
cryptsetup luksClose myvol
11.0 Configure Automatic LUKS Volume Decryption During Boot
This section describes the steps to configure automatic unlocking and mounting of the LUKS volume during system boot using systemd services.
Perform the following steps to configure decryption of volume during boot:
Create a script to unlock and mount the LUKS volume. You can customize the script as required. Ensure to replace /dev/disk/by-
uuid/eae667fa-78c0-462d-bc55-1761fc82f556with your LUKS partition UUID.Run the following command to create the
/usr/local/bin/unlock-and-mount-fortanix.shscript and add the associated configuration:vi /usr/local/bin/unlock-and-mount-fortanix.sh #!/bin/bash set -e # Unlock the volume echo "file:///etc/fortanix/pkcs11.conf" | cryptsetup luksOpen /dev/disk/by-uuid/eae667fa-78c0-462d-bc55-1761fc82f556 myvolume --token-only --key-slot=1 # Try to mount first, create filesystem if mount fails if ! mount /dev/mapper/myvolume /mnt 2>/dev/null; then echo "Mount failed, likely no filesystem. Creating ext4..." mkfs.ext4 -F /dev/mapper/myvolume mount /dev/mapper/myvolume /mnt fi echo "Volume unlocked and mounted at /mnt"If there are entries in
/etc/fstabfor the block device, then comment them out as systemd uses it to unlock and mount it. In the example, /mnt is used as mount, modify according to your preference.Run the following command to create a
systemdservice file as/etc/systemd/system/unlock-myvolume.serviceand add the associated configuration:vi /etc/systemd/system/unlock-myvolume.service [Unit] Description=Unlock and Mount LUKS volume with Fortanix After=network-online.target Wants=network-online.target [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/local/bin/unlock-and-mount-fortanix.sh TimeoutStartSec=0 [Install] WantedBy=multi-user.targetRun the following command to reload the
systemddaemon:sudo systemctl daemon-reloadRun the following command to enable the service:
sudo systemctl enable unlock-myvolume.serviceRun the following command to start the service:
sudo systemctl start unlock-myvolume.serviceRun the following command to verify the status of the service:
sudo systemctl status unlock-myvolume.serviceRun the following command to verify that the volume is mounted:
df -h | grep luks_vol_unlockedRun the following command to stop the service:
sudo systemctl stop unlock-myvolume.serviceReboot the system to verify that the volume is unlocked and mounted during boot.
In case of issues, run the following command to check the service logs:
journalctl -u unlock-myvolume.service
12.0 Rotate the PKCS#11 Key for the LUKS Volume
This section describes the steps to rotate the PKCS#11 key used for LUKS volume decryption.
Perform the following steps to rotate the key:
Ensure that the PKCS#11 URI always locates a single private key and certificate. Enrollment or decryption of the LUKS volume fails if multiple keys or certificate match the same URI.
It is not recommended to use the Rotate Key option in Fortanix DSM for LUKS key rotation. Instead, generate a new key pair, enroll the Fortanix PKCS#11 token again using the new key, and remove the old key slot after verifying successful decryption.
Run the following command to generate new key using
pkcs11-tool:pkcs11-tool --module /etc/fortanix/libpkcs11_fortanix.so --login --pin file:///etc/fortanix/pkcs11.conf -k --id `uuidgen | tr -d -` --label "LuksKeyv2" --key-type rsa:2048Sample output:
Using slot 0 with a present token (0x0) Key pair generated: Private Key Object; RSA label: LuksKeyv2 ID: f796359bfbd34a62b7179e3efdb34b08 warning: PKCS11 function C_GetAttributeValue(SIGN_RECOVER) failed: rv = CKR_ATTRIBUTE_TYPE_INVALID (0x12) Usage: decrypt, sign, unwrap Access: sensitive, always sensitive, never extractable, local Public Key Object; RSA 2048 bits label: LuksKeyv2 ID: f796359bfbd34a62b7179e3efdb34b08 warning: PKCS11 function C_GetAttributeValue(VERIFY_RECOVER) failed: rv = CKR_ATTRIBUTE_TYPE_INVALID (0x12) Usage: encrypt, verify, wrap Access: localRun the following commands to generate an X.509 certificate using the new key:
export OPENSSL_CONF=/root/openssl.cnf export FORTANIX_PKCS11_NUM_SLOTS=1 openssl req -new -x509 -days 365 -sha256 -engine pkcs11 -keyform engine -key pkcs11:object=LuksKeyv2 -out lukscert.crt -subj "/CN=test.example.com" 2>/dev/nullRun the following command to upload the certificate in Step 4 using the same ID:
pkcs11-tool --module /etc/fortanix/libpkcs11_fortanix.so --login --pin file:///etc/fortanix/pkcs11.conf --write-object lukscert.crt --type cert --label "lukscertv2" --id f796359bfbd34a62b7179e3efdb34b08 Using slot 0 with a present token (0x0) Created certificate: Certificate Object; type = X.509 cert label: lukscertv2 subject: DN: CN=test.example.com serial: 523378D8AE418892015F62BE4FD2181ACDAEAF87 ID: f796359bfbd34a62b7179e3efdb34b08Run the following command to convert the key ID into percent-encoded format for the PKCS#11 URI:
echo "f796359bfbd34a62b7179e3efdb34b08"| perl -pe 's/(..)/pack("H2",$1)/ge' | perl -pe 's/(.)/sprintf("%%%02x",ord($1))/ge' %f7%96%35%9b%fb%d3%4a%62%b7%17%9e%3e%fd%b3%4b%08Sample output:
systemd-cryptenroll --pkcs11-token-uri "pkcs11:token=Fortanix%20Token;id=%f7%96%35%9b%fb%d3%4a%62%b7%17%9e%3e%fd%b3%4b%08" /dev/disk/by-uuid/eae667fa-78c0-462d-bc55-1761fc82f556 🔐 Please enter current passphrase for disk /dev/disk/by-uuid/eae667fa-78c0-462d-bc55-1761fc82f556: •••• 🔐 Please enter PIN for security token 'Fortanix Token' in order to unlock volume enrollment operation: •••••••••••••••••••••••••••••••• Successfully logged into security token 'Fortanix Token'. New PKCS#11 token enrolled as key slot 2.Run the following command to verify that both keys are present in the LUKS header:
cryptsetup luksDump /dev/disk/by-uuid/eae667fa-78c0-462d-bc55-1761fc82f556Sample output:
LUKS header information Version: 2 Epoch: 7 Metadata area: 16384 [bytes] Keyslots area: 16744448 [bytes] UUID: eae667fa-78c0-462d-bc55-1761fc82f556 Label: (no label) Subsystem: (no subsystem) Flags: (no flags) Data segments: 0: crypt offset: 16777216 [bytes] length: (whole device) cipher: aes-xts-plain64 sector: 4096 [bytes] Keyslots: 0: luks2 Key: 512 bits Priority: normal Cipher: aes-xts-plain64 Cipher key: 512 bits PBKDF: argon2id Time cost: 4 Memory: 596768 Threads: 1 Salt: 9d 20 9c 8d 22 bc 3e 66 3b 84 bd 88 4a b2 b2 2f 24 14 23 58 49 7b 1c 20 6b ea df 73 46 da ed fb AF stripes: 4000 AF hash: sha256 Area offset:32768 [bytes] Area length:258048 [bytes] Digest ID: 0 1: luks2 Key: 512 bits Priority: normal Cipher: aes-xts-plain64 Cipher key: 512 bits PBKDF: pbkdf Hash: sha512 Iterations: 1000 Salt: 5d 85 d3 71 bb 50 a6 b4 3d 76 12 dd 57 a6 95 9b 93 e8 6c 2e 37 7c 19 44 cc b3 b4 41 71 03 2d 4e AF stripes: 4000 AF hash: sha512 Area offset:290816 [bytes Area length:258048 [bytes] Digest ID: 0 2: luks2 Key: 512 bits Priority: normal Cipher: aes-xts-plain64 Cipher key: 512 bits PBKDF: pbkdf2 Hash: sha512 Iterations: 1000 Salt: 3d da e4 3d 5b a3 fb 00 e3 7a 24 6c 01 38 dc 60 6b de d5 01 29 6f ea 04 aa 8c fd 26 0a 71 70 97 AF stripes: 4000 AF hash: sha512 Area offset:548864 [bytes] Area length:258048 [bytes] Digest ID: 0 Tokens: 0: systemd-pkcs11 pkcs11-uri: pkcs11:token=Fortanix%20Token;id=%44%c4%5d%8e%30%2d%4b%56%b3%c0%a8%cf%17%7d%98%d4 pkcs11-key: 44 1f b9 67 79 f3 11 88 23 60 41 6b 99 44 49 af 3c 97 8f 80 d5 c1 c7 c3 f5 0b 94 6d af 02 51 da 17 b0 e5 6e 98 3c 0d 7b 40 dd d5 c3 06 68 b6 be 8e f5 47 bb c0 f4 cd 75 3d bf 97 4e 57 f9 85 d4 50 23 20 46 c3 13 52 66 50 6c 1d ba 9d 93 c2 0f 8d 31 dd d4 40 75 97 fe 89 0e 0a be 18 10 60 86 24 76 3a f1 eb 56 d6 e3 18 f4 21 a0 17 c4 9d b4 3b e0 6d 3f 78 12 ab a0 19 c4 46 52 df 23 75 e8 28 e9 65 bc ac 41 91 9b db 61 1d b9 a6 76 6f 0d c0 26 b0 5a 15 4b ed 2e 42 9a 74 9e a3 5b a8 cc f7 61 55 03 8b 1d 63 af b6 dd 11 5e 5c a0 eb d9 2a c6 5d 86 92 27 da e8 20 98 3d a6 2f 31 70 09 cb 78 9f 17 96 b5 31 4b f5 ec ae 1b 90 02 9d 71 38 c9 0a 49 a5 18 e8 6e 02 c7 bc 4f 2a a4 36 42 21 5f 95 d3 6f b3 e3 cd 00 d4 a6 7b 34 eb 00 41 d1 71 3b 14 dd 5e c9 b0 82 8f 28 c3 ab a2 9d 0b Keyslot: 1 1: systemd-pkcs11 pkcs11-uri: pkcs11:token=Fortanix%20Token;id=%f7%96%35%9b%fb%d3%4a%62%b7%17%9e%3e%fd%b3%4b%08 pkcs11-key: 99 a2 be 41 1e 90 ef ec 43 34 6b 2e bb 5e 25 81 82 67 56 75 7f 50 1e eb ca a8 81 08 66 02 3d 71 5a 06 59 fb 11 6d 57 b3 63 65 88 dc 8d 8b dd ab 7d be 7c 9e f5 a2 72 ac 7f c2 23 82 90 0c b0 d8 22 98 2a 19 68 2d 35 5b 9d 5f 15 f1 d3 66 89 31 29 b5 f8 1c a3 f5 6c 36 4f cb 64 88 2c cf 96 02 4f 5b f0 6b 84 e7 36 5c 04 58 e1 d1 09 25 af 3f b9 2f 60 67 3d eb fb 8b 71 20 b2 1e e4 19 61 29 30 a8 7c d3 ba 2e 76 f3 8c d9 5b e7 48 71 b2 ce 97 27 f8 19 1c 8d c9 7d 4c 24 d3 b4 a6 80 2a 8d 5e 3c 67 93 6d 62 dd 61 76 5f 06 24 dd e8 77 45 30 cf cc 1c 1f 05 b7 0f 10 ea 2a d6 2f 0d c1 23 93 a6 86 05 20 af 0c 42 cc 24 5e 7c 9f 73 8e d3 f6 4e 2c c1 70 f3 91 51 23 c5 0f 26 6e f5 f2 87 cd eb 16 27 d2 3a 50 c0 9b 8a f9 ee 04 36 cc cb ae 26 76 ec 09 49 b5 22 f5 e2 cd 36 2d 80 ad 32 Keyslot: 2 Digests: 0: pbkdf2 Hash: sha256 Iterations: 86459 Salt: bc 53 cc ec 87 69 c9 4c 42 28 0c 43 86 d2 ee ac a3 11 b5 d5 a5 a3 eb 52 1e e8 7f ec 39 7f 97 44 Digest: 9f 01 38 1e 20 eb 25 d1 22 13 e6 f8 cf 00 03 3a 1a ae fd 83 60 c6 06 7a 0c 34 39 b0 be 96 00 3bVerify that the new token is mapped to
Keyslot: 2.Run the following command to close the volume and test decryption using the old key slot:
cryptsetup luksClose myvolume echo "file:///etc/fortanix/pkcs11.conf" | cryptsetup open --key-slot=2 --token-only /dev/sdc1 myvol1 --debugRun the following command to use the new key for boot-time decryption, update the key slot in the
/usr/local/bin/unlock-and-mount-fortanix.shscript:#!/bin/bash set -e # Unlock the volume , keyslot=2 echo "file:///etc/fortanix/pkcs11.conf" | cryptsetup luksOpen /dev/disk/by-uuid/eae667fa-78c0-462d-bc55-1761fc82f556 myvolume --token-only --key-slot=2 # Ensure mount point exists #mkdir -p /mnt/luks_vol_unlocked # Try to mount first, create filesystem if mount fails if ! mount /dev/mapper/myvolume /mnt 2>/dev/null; then echo "Mount failed, likely no filesystem. Creating ext4..." mkfs.ext4 -F /dev/mapper/myvolume mount /dev/mapper/myvolume /mnt fi echo "Volume unlocked and mounted at /mnt"After verifying that decryption works correctly with the new key, you can disable the old key from the Fortanix DSM UI.

Figure 6: Security object disabled
13.0 Unlock the LUKS Volume on Another Machine
This section describes the steps to unlock a LUKS-encrypted volume from another machine using the enrolled Fortanix DSM PKCS#11 token.
There could be scenarios such as VM corruption, hardware issue, so on where the LUKS volume must be attached and unlocked from another machine.
Perform the following steps to unlock the encrypted volume in another VM using Fortanix DSM.
Detach the encrypted disk from the existing VM and attach it to target VM.
In this example, an Azure VM is used, and the disk is attached through Azure Portal UI. Based on your environment, follow the appropriate steps to attach the disk.

Figure 7: Edit the data disk details

Figure 8: Data disks
Start the VM and run the following command to verify if the disk is attached correctly:
blkid cryptsetup luksDump /dev/disk/by-uuid/1967a99b-4799-4bc7-afd9-9f2f1634adf2Verify that the PKCS#11 token information is retained in the LUKS header.


Run the following command to verify the Ubuntu OS and
systemd-cryptenrollversion:cat /etc/os-release systemd-cryptenroll --versionEnsure that
systemd-cryptenrollversion 255 is installed.Run the following command to verify if OpenSC is installed:
apt list openscIf not installed, run the following command to install OpenSC:
apt install openscRun the following command to install OpenSSL PKCS#11 library engine:
apt install libengine-pkcs11-opensslRun the following command to create
openssl.conffile and add the associated configuration:vi /root/openssl.cnf # PKCS11 engine config openssl_conf = openssl_def [openssl_def] engines = engine_section [req] distinguished_name = req_distinguished_name [req_distinguished_name] # empty [engine_section] pkcs11 = pkcs11_section [pkcs11_section] engine_id = pkcs11 dynamic_path = /usr/lib/x86_64-linux-gnu/engines-3/libpkcs11.so #openssl pkcs11 engine library path MODULE_PATH = /etc/fortanix/libpkcs11_fortanix.so #Fortanix pkcs11 path init = 1Run the following command to create the
/etc/fortanixdirectory and copy the Fortanix PKCS#11 library. You can download the latest Fortanix PKCS#11 library from the PKCS#11.mkdir –p /etc/fortanixRun the following command to create the
/etc/pkcs11/modulesdirectory:mkdir -p /etc/pkcs11/modulesRun the following command to navigate to the
/etc/pkcs11/modulesdirectory:cd /etc/pkcs11/modulesRun the following command to create the
fortanix.modulefile and add the associated configuration:vi fortanix.module module: /etc/fortanix/libpkcs11_fortanix.so #(This is the location of fortanix pkcs11 lib)Run the following command to create the
pkcs11.conffile containing Fortanix DSM credentials in/etc/fortanixdirectory and add the associated configuration:vi /etc/fortanix/pkcs11.conf api_key = "YjY5NzNlZjgtNmZiZS00MTRhLTk2YjgtMzRlYzZjMmNmZGJjOnZtWHJMSjZZQTJ6dEdGWm41cTdac29LelI1QzJNZGNuQW9RbGNGVXZxdWJtNWh3Z29vNTN6ZF9ndkxRdUQ0SDN3NWFrajItbDNYTTVJaUgySlFad0Zn" api_endpoint = "https://sit.smartkey.io" [log] file = "/etc/fortanix/pkcs11.log" level = "info"Run the following command to verify if the connectivity with Fortanix is working properly using the
pkcs-tool:/etc/pkcs11/modules# pkcs11-tool --module /etc/fortanix/libpkcs11_fortanix.so --login --list-objectsSample output:
Using slot 0 with a present token (0x0) Logging in to "Fortanix Token". Please enter User PIN: Certificate Object; type = X.509 cert label: lukscert subject: DN: CN=test.example.com serial: 2C5E2999AB829825F12862A91F729C79842E571D ID: bb7ff93def9f4146bff2faab26889cab Private Key Object; RSA label: LuksKey ID: bb7ff93def9f4146bff2faab26889cab warning: PKCS11 function C_GetAttributeValue(SIGN_RECOVER) failed: rv = CKR_ATTRIBUTE_TYPE_INVALID (0x12) Usage: decrypt, sign, unwrap Access: sensitive, always sensitive, never extractable, local Public Key Object; RSA 2048 bits label: LuksKey ID: bb7ff93def9f4146bff2faab26889cab warning: PKCS11 function C_GetAttributeValue(VERIFY_RECOVER) failed: rv = CKR_ATTRIBUTE_TYPE_INVALID (0x12) Usage: encrypt, verify, wrap Access: localIf the objects are listed properly, then it indicates that the connectivity with Fortanix DSM is working correctly.
Run the following command to unlock the encrypted volume using enrolled PKCS#11 token:
echo "file:///etc/fortanix/pkcs11.conf" | cryptsetup open --key-slot 1 --token-only /dev/disk/by-uuid/1967a99b-4799-4bc7-afd9-9f2f1634adf2 myvolSample output:
Successfully logged into security token 'Fortanix Token'. Successfully decrypted key with security token.Run the following command to verify that the mapped device is created:
ls -ltr /dev/mapper/Sample output:
total 0 crw------- 1 root root 10, 236 Mar 6 12:02 control lrwxrwxrwx 1 root root 7 Mar 6 12:17 myvol -> ../dm-0Run the following command to close the volume:
###Close the volume #### cryptsetup luksClose myvolRun the following command to create the
unlock -/usr/local/bin/unlock-and-mount-fortanix.shscript for automatic decryption during the boot:vi /usr/local/bin/unlock-and-mount-fortanix.shSample output:
#!/bin/bash set -e # Unlock the volume , keytslot=2 echo "file:///etc/fortanix/pkcs11.conf" | cryptsetup luksOpen /dev/disk/by-uuid/1967a99b-4799-4bc7-afd9-9f2f1634adf2 myvolume --token-only --key-slot=1 # Ensure mount point exists #mkdir -p /mnt/luks_vol_unlocked # Try to mount first, create filesystem if mount fails if ! mount /dev/mapper/myvolume /datadrive 2>/dev/null; then echo "Mount failed, likely no filesystem. Creating ext4..." mkfs.ext4 -F /dev/mapper/myvolume mount /dev/mapper/myvolume /datadrive fi echo "Volume unlocked and mounted at /datadrive"Run the following commands to update the permissions to execute the script and existence of the mount:
chmod +x /usr/local/bin/unlock-and-mount-fortanix.sh mkdir -p /datadriveRun the following command to create the
systemdservice file and add the associated configuration:vi /etc/systemd/system/unlock-myvolume.service [Unit] Description=Unlock and Mount LUKS volume with Fortanix After=network-online.target Wants=network-online.target [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/local/bin/unlock-and-mount-fortanix.sh TimeoutStartSec=0 [Install] WantedBy=multi-user.targetReboot the VM and verify that the encrypted volume is automatically unlocked and mounted during boot.