Fortanix DSM for LUKS2 Volume Encryption and Decryption

Prev Next

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.

A screenshot of a login screen  AI-generated content may be incorrect., Picture

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:

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

  2. On the Adding new group page, do the following:

    1. Title: Enter a name for your group.

    2. Description (optional): Enter a short description of the group.

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

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

  2. On the Adding new app page, do the following:

    1. App name: Enter the name for your application.

    2. ADD DESCRIPTION (optional): Enter a short description of the application.

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

    4. Assigning the new app to groups: Select the group created in Section 6.3: Creating a Groupfrom the list.

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

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

  2. On the INFO tab, click VIEW API KEY DETAILS.

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

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

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

  1. Run the following command to verify the Ubuntu OS version:

    cat /etc/os-release
  2. Run the following command to verify the installed systemd-cryptenroll version:

    systemd-cryptenroll --version
  3. Run the following command to verify if OpenSC and OpenSSL PKCS#11 engine are installed:

    apt list opensc
    openssl engine pkcs11

    If not installed, run the following command to install OpenSC and OpenSSL PKCS#11 engine:

    apt install opensc
    apt install libengine-pkcs11-openssl 
  4. Run the following command to create the openssl.cnf file 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 = 1

    Where,

    • dynamic_path: Specifies the OpenSSL PKCS#11 engine library path.

    • MODULE_PATH: Specifies the Fortanix PKCS#11 library path.

  5. 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/fortanix
  6. Run the following command to create the /etc/pkcs11/modules directory:

    mkdir -p /etc/pkcs11/modules
  7. Run the following command to navigate to the directory:

    cd /etc/pkcs11/modules
  8. Run the following command to create the fortanix.module file 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.so is the location of the Fortanix PKCS#11 library.

  9. You can create the pkcs11.conf file in the /etc/fortanix directory using one of the following authentication methods:

    1. Using API key:

      1. Run the following command to create the pkcs11.conf file 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.

      2. Using certificate:

        1. Run the following command to set the OpenSSL configuration environment variable:

          export OPENSSL_CONF=/root/openssl.cnf
        2. Run 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.

      3. Run the following command to convert the private key file to PKCS#8 PEM format:

        openssl pkcs8 -topk8 -in private.key -out private.pem -nocrypt
      4. Run the following command to create the pkcs#11.conf file 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 that

9.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:

  1. 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:
  2. Run the following command to retrieve the LUKS UUID:

    cryptsetup luksUUID <device name> 

    For example,

    cryptsetup luksUUID /dev/sda1
    eae667fa-78c0-462d-bc55-1761fc82f556

    Use the UUID as the LUKS partition instead of /dev/sdX.

    For example, /dev/disk/by-uuid/eae667fa-78c0-462d-bc55-1761fc82f556.

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

  4. 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 3b
  5. Run the following command to verify that the LUKS partition type is crypto_LUKS:

    blkid

    For 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:

  1. 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:2048

    Ensure 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:     local
  2. Run 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/null

    Ensure that the OpenSSL PKCS#11 engine is installed and configured in the openssl.conf file.

  3. 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:         44c45d8e302d4b56b3c0a8cf177d98d4
  4. Run 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%d4

    Sample URI:

    pkcs11:token=Fortanix%20Token;id=%44%c4%5d%8e%30%2d%4b%56%b3%c0%a8%cf%17%7d%98%d4
  5. Run 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-1761fc82f556

    Ensure 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.
  6. 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-1761fc82f556

    Ensure 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 3b

    NOTE

    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.

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

    Sample output:

    Successfully logged into security token 'Fortanix Token'.
    Successfully decrypted key with security token.
  8. Run the following command to verify that the mapped device is enrolled:

    /dev/mapper# ls -ltr

    Sample 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####
  9. 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:

  1. 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-1761fc82f556 with your LUKS partition UUID.

  2. Run the following command to create the /usr/local/bin/unlock-and-mount-fortanix.sh script 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/fstab for 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.

  3. Run the following command to create a systemd service file as /etc/systemd/system/unlock-myvolume.service 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.target
  4. Run the following command to reload the systemd daemon:

    sudo systemctl daemon-reload
  5. Run the following command to enable the service:

    sudo systemctl enable unlock-myvolume.service
  6. Run the following command to start the service:

    sudo systemctl start unlock-myvolume.service
  7. Run the following command to verify the status of the service:

    sudo systemctl status unlock-myvolume.service
  8. Run the following command to verify that the volume is mounted:

    df -h | grep luks_vol_unlocked
  9. Run the following command to stop the service:

    sudo systemctl stop unlock-myvolume.service
  10. Reboot 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:

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

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

  3. 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:2048

    Sample 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:     local
  4. Run 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/null
  5. Run 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:         f796359bfbd34a62b7179e3efdb34b08
  6. Run 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%08

    Sample 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.
  7. 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-1761fc82f556

    Sample 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 3b

    Verify that the new token is mapped to Keyslot: 2.

  8. 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 --debug
  9. Run 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.sh script:

    #!/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"
  10. 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.

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

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

    Verify that the PKCS#11 token information is retained in the LUKS header.

  3. Run the following command to verify the Ubuntu OS and systemd-cryptenroll version:

    cat /etc/os-release
    systemd-cryptenroll --version

    Ensure that systemd-cryptenroll version 255 is installed.

  4. Run the following command to verify if OpenSC is installed:

    apt list opensc

    If not installed, run the following command to install OpenSC:

    apt install opensc
  5. Run the following command to install OpenSSL PKCS#11 library engine:

    apt install libengine-pkcs11-openssl
  6. Run the following command to create openssl.conf file 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 = 1
  7. 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/fortanix
  8. Run the following command to create the /etc/pkcs11/modules directory:

    mkdir -p /etc/pkcs11/modules
  9. Run the following command to navigate to the /etc/pkcs11/modules directory:

    cd /etc/pkcs11/modules
  10. Run the following command to create the fortanix.module file and add the associated configuration:

    vi fortanix.module
    module: /etc/fortanix/libpkcs11_fortanix.so #(This is the location of fortanix pkcs11 lib)
  11. Run the following command to create the pkcs11.conf file containing Fortanix DSM credentials in /etc/fortanix directory 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"
  12. 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-objects

    Sample 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:     local	

    If the objects are listed properly, then it indicates that the connectivity with Fortanix DSM is working correctly.

  13. 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 myvol

    Sample output:

    Successfully logged into security token 'Fortanix Token'.
    Successfully decrypted key with security token.
  14. 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-0
  15. Run the following command to close the volume:

    ###Close the volume ####
     cryptsetup luksClose myvol
  16. Run the following command to create the unlock -/usr/local/bin/unlock-and-mount-fortanix.sh script for automatic decryption during the boot:

    vi /usr/local/bin/unlock-and-mount-fortanix.sh 

    Sample 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"
  17. 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 /datadrive
  18. Run the following command to create the systemd service 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.target
  19. Reboot the VM and verify that the encrypted volume is automatically unlocked and mounted during boot.

Fortanix-logo

4.6

star-ratings

As of August 2025