Creating a volume for pervasive encryption

With cryptsetup, you can conveniently set up volume encryption. It formats the volume and performs the necessary device mapper setup tasks.

Before you begin

As a prerequisite, you require free disk devices or partitions on disk devices that are configured to be persistently available to your Linux® instance.

About this task

To create a volume that will receive encrypted content, you need to know the encryption method for this volume, the wanted key size, and the name and location of the volume. This information is passed to cryptsetup as input parameters.

Also, you must define a passphrase for each volume that you want to encrypt. This passphrase encrypts the LUKS volume encryption key (LVEK) and you can use it for all interactive setup actions on the encrypted volume. In the infrastructure for protected volume encryption, the LVEK is a secure key. Because secure keys are already encrypted by a master key, these passphrases are of limited relevance to security.

For automated opening of the encrypted volume during system startup, you can use a key file containing some random data that fulfills the same purpose as a passphrase.

Procedure

  1. Generate a secure key in the secure key repository using the zkey utility.
    You can generate secure keys (AES DATA keys, AES CIPHER keys as shown in the example, or EP11 AES secure keys) with a length of 128, 192, or 256 bits. When generating secure keys for the XTS cipher mode, only 128 or 256 bit keys are supported. For XTS cipher mode keys, two secure key parts are generated and concatenated to each other.

    For the scenario, issue the following command for the XTS cipher mode with a key name of secure_xtskey1 and a key length of 256 bits. Create four different keys with names secure_xtskey1 up to secure_xtskey4.

    
    # zkey generate --name secure_xtskey1 --key-type CCA-AESCIPHER --keybits 256  --xts \
    --volumes /dev/mapper/disk1:enc-disk1 --volume-type LUKS2 \
    --apqns 03.0039,04.0039  --sector-size 4096
    ...
    # zkey generate --name secure_xtskey4 --key-type CCA-AESCIPHER  --keybits 256 --xts \
    --volumes /dev/mapper/disk4:enc-disk4 --volume-type LUKS2 \
    --apqns 03.0039,04.0039  --sector-size 4096
    

    The keys to be encrypted by the AES master key are generated by random inside a domain of the cryptographic coprocessor and are thus never exposed in clear outside the coprocessor. After the successful generation of the secure key, the randomly generated key is destroyed by the coprocessor. This is possible because during cryptographic operations within the coprocessor, effective keys are always reconstructed by decrypting the secure key with the master key.

    In the shown example, you specify the volumes that are to be encrypted with the new secure key, and you also associate the APQNs where the related master key is located.

    Use a different key for each encrypted volume. Only for certain reasons, if you want to use a particular secure key for selected volumes, generate only one key and associate it to all these selected volumes.

    Note: With the optional parameter --sector-size, you can set the size of the blocks to be encrypted or decrypted. It must be a power of two and in the range 512 - 4096 bytes. cryptsetup chooses a default sector size of 512 bytes. Using 4096-byte sectors provides the best performance on Linux on Z and LinuxONE.
    You can list information about the generated secure keys:
    
    # zkey list
    Key                          : secure_xtskey1                                   
    ---------------------------------------------------------------------
            Description          :
            Secure key size      : 272 bytes
            Clear key size       : 512 bits
            XTS type key         : Yes
            Key type             : CCA-AESCIPHER
            Volumes              : /dev/mapper/disk1:enc-disk1
            APQNs                : 03.0039
                                   04.0039
            Key file name        : /etc/zkey/repository/secure_xtskey1.skey
            Sector size          : 4096 bytes
            Volume type          : LUKS2
            Verification pattern : 303344b12b8258840fa11852a4ecc6d5
                                   84c7a867f893a5dcc0d499557c45bee6
            Created              : 2020-08-20 15:27:20
            Changed              : (never)
            Re-enciphered        : (never)
    ...
    
  2. Generate the commands to format the volume to be encrypted using cryptsetup. The formatting process writes the LUKS2 header onto the volume. During formatting, the LUKS2 volume encryption key, which is the previously generated secure key, is encrypted with a KEK that is derived from the passphrase or from a provided key file.

    When you format a volume, you need to specify values for the following parameters, which are retrieved or calculated during command generation:

    type
    The LUKS2 type of formatting.
    cipher
    The PAES cipher, its operation mode (XTS), and the algorithm to generate the initialization vector (plain64).
    master-key-file
    The location and name of the secure key file generated in step 1.
    key-size
    The size of the secure key file in bits. In our example, an AES CIPHER key used with the XTS cipher mode is generated with a size of 272 bytes = 2176 bits. (An AES DATA key has 64 bytes = 512 bits. An EP11 AES key used with XTS of size 640 bytes has a file size of 5120 bits).

    In addition, you specify the name of the volume. In our case, this is /dev/mapper/disk1 through /dev/mapper/disk4.

    For the sample system, invoke the zkey cryptsetup command for the first volume as follows:

    
    # zkey cryptsetup --volumes /dev/mapper/disk1
    
    cryptsetup luksFormat --type luks2 --pbkdf pbkdf2 
    --master-key-file '/etc/zkey/repository/secure_xtskey1.skey'
    --key-size 2176 --cipher paes-xts-plain64 --sector-size 4096 /dev/mapper/disk1
    
    zkey-cryptsetup setvp /dev/mapper/disk1
    
    Two commands are generated and displayed as shown:
    • the cryptsetup luksFormat command to format the volume
    • the zkey-cryptsetup setvp command to set the verification pattern into the LUKS2 header. The verification pattern is used to identify the valid effective key during recovery actions.
  3. Run the generated commands.
    Copy and paste the generated commands into the command line.
    Note: If the you use an older distribution, the --pbkdf pbkdf2 option may be missing in the generated command. In such a case, edit the command by adding option --pbkdf pbkdf2. This is to avoid an out-of-memory error for a LUKS2 volume during automated opening via /etc/crypttab at system startup. For more information, see Out-of-memory errors when opening a LUKS2 volume.

    For each volume, define a passphrase like disk1pw up to disk4pw.

    # cryptsetup luksFormat --type luks2 --pbkdf pbkdf2 \
    --master-key-file '/etc/zkey/repository/secure_xtskey1.skey' \
    --key-size 2176 --cipher paes-xts-plain64 --sector-size 4096 /dev/mapper/disk1
    
    WARNING!
    ========
    This will overwrite data on /dev/mapper/disk1 irrevocably.
    
    Are you sure? (Type uppercase yes): YES
    Enter passphrase for /dev/mapper/disk1: disk1pw 
    Verify passphrase: disk1pw
    
    # zkey-cryptsetup setvp /dev/mapper/disk1
    Enter passphrase for '/dev/mapper/disk1': disk1pw
    
    When you type the passphrase, it is not displayed.
    Tip: In newer distributions where the --pbkdf pbkdf2 option is automatically generated, you can use the --run option to let the generated commands run directly after creation, without the need to copy and paste:
    
    # zkey cryptsetup --volumes /dev/mapper/disk1 --run
  4. Open the volume using a generated command:
    
    # zkey cryptsetup --volumes /dev/mapper/disk1 --open --run
    

    The following command is generated and immediately run:

    
    # cryptsetup luksOpen /dev/mapper/disk1 enc-disk1

    When prompted, enter the passphrase from step 3.

    This creates a device-mapper device named /dev/mapper/enc-disk1 (see step 5).

    Note: Repeat steps 1 through 4 with the appropriate file names and volume names for each volume that you want to encrypt.
  5. Optional: Check the result of step 4 with the command ls /dev/mapper/:
    # ls /dev/mapper
    control  disk2  disk4  disk6  disk8      enc-disk2  enc-disk4
    disk1    disk3  disk5  disk7  enc-disk1  enc-disk3
    

    As of now, any I/O operation to or from /dev/mapper/enc-disk1 is transparently encrypted or decrypted onto the /dev/mapper/disk1 device. Do not write to this device directly. The same is valid for disks disk2 through disk4.

  6. Create a key file and specify it in an entry in /etc/crypttab to persistently configure the opening at system startup.
    1. Create the key file named disk1.key in directory /etc/luks_keys/ with random content with a size of 4096 bytes (specified by bs=1024 count=4). If the directory does not yet exist, you must create it first.
      # dd if=/dev/urandom of=/etc/luks_keys/disk1.key bs=1024 count=4
      # chmod 0400 /etc/luks_keys/disk1.key

      The second command makes the key file readable by the root user only. Repeat these commands for each volume adequately.

    2. Add a key slot with the previously generated key file:
      # cryptsetup luksAddKey --pbkdf pbkdf2 /dev/mapper/disk1 /etc/luks_keys/disk1.key
      You must also specify option --pbkdf pbkdf2 with the luksAddKey command to avoid an out-of-memory error for a LUKS2 volume during automated opening via /etc/crypttab at system startup. For more information, see Out-of-memory errors when opening a LUKS2 volume.

      Repeat this for each disk. When prompted, enter the passphrase from step 3.

    3. Edit /etc/crypttab and add one entry for each encrypted volume:
      
      # /etc/crypttab
      #
      # See crypttab(5) for more information.
      #
      # <target name> <source device>         <key file>                  <options>
        enc-disk1     /dev/mapper/disk1       /etc/luks_keys/disk1.key    luks       
        enc-disk2     /dev/mapper/disk2       /etc/luks_keys/disk2.key    luks
        enc-disk3     /dev/mapper/disk3       /etc/luks_keys/disk3.key    luks
        enc-disk4     /dev/mapper/disk4       /etc/luks_keys/disk4.key    luks
      The format of the /etc/crypttab file depends on your Linux distribution. See the crypttab man page for more details.

      Alternatively you can have a skeleton for a crypttab entry automatically generated by the zkey crypttab command:

      # zkey crypttab --volumes /dev/mapper/disk<n>

      You only need to add the <key file> column manually.

      You can, however, specify the key file with the command, then you do not need to add the<key file> column manually:

      # zkey crypttab --volumes /dev/mapper/disk<n> --key-file /etc/luks_keys/disk<n>.key
  7. Prepare your volumes for being managed by LVM. For this purpose, you need to perform the following sub-steps:
    1. Define and initialize the physical volumes that you plan to use in order to make them available to LVM. Use the pvcreate command. Each such command creates what is called an LVM physical volume.
    2. Define an LVM volume group where you combine the LVM physical volumes that you want to manage within such a group. Use the vgcreate command.
    3. Add logical volumes to the volume group using the lvcreate command. With the -n option, you specify a meaningful name for the logical volume. With the -L option, you specify a size, which can be independent from the sizes of any existing hardware disks, except for the overall capacity.
    Example:
    
    # pvcreate /dev/mapper/enc-disk1
    # pvcreate /dev/mapper/enc-disk2
    # pvcreate /dev/mapper/enc-disk3
    # pvcreate /dev/mapper/enc-disk4
    
    # vgcreate MY_VOLGROUP /dev/mapper/enc-disk*
    
    # lvcreate -L 10GB MY_VOLGROUP -n LV1
    # lvcreate -L 30GB MY_VOLGROUP -n LV2
    # lvcreate -L 35GB MY_VOLGROUP -n LV3
    
    # ls /dev/mapper 
    control  disk3  disk6  enc-disk1  enc-disk4         MY_VOLGROUP-LV3
    disk1    disk4  disk7  enc-disk2  MY_VOLGROUP-LV1
    disk2    disk5  disk8  enc-disk3  MY_VOLGROUP-LV2
    
    
    Note: For logical volume LV3, only 35 GB are defined, though 40 GB physical space are available. Thus you can enlarge the volume for further purposes.
  8. Create a file system - in the example, an ext4 file system - on the encrypted LVM logical volume created in step 7 or the encrypted volume created in step 4 (if you did not use LVM).
    
    # mkfs.ext4 /dev/mapper/MY_VOLGROUP-LV1
    # mkfs.ext4 /dev/mapper/MY_VOLGROUP-LV2
    # mkfs.ext4 /dev/mapper/MY_VOLGROUP-LV3
    The kernel transparently encrypts or decrypts I/O requests to or from the encrypted volume. Thus, the end-to-end encryption for the data at-rest is implemented.
  9. Create mount points and update /etc/fstab to later mount the file systems on the encrypted volumes.
    1. Create the mount points:
      # mkdir /crypted_lv1
      # mkdir /crypted_lv2
      # mkdir /crypted_lv3
    2. Edit file /etc/fstab and add similar entries like follows:
      
      /dev/mapper/MY_VOLGROUP-LV1 /crypted_lv1 ext4 defaults 0 0
      /dev/mapper/MY_VOLGROUP-LV2 /crypted_lv2 ext4 defaults 0 0
      /dev/mapper/MY_VOLGROUP-LV3 /crypted_lv3 ext4 defaults 0 0
      
  10. Mount the file system through /etc/fstab.
    # mount /crypted_lv1
    # mount /crypted_lv2
    # mount /crypted_lv3
    Note: To let users issue the mount command for a particular mount point, add the user option to the entry for this mount point in /etc/fstab.

Results

You created four encrypted volumes as LVM physical volumes grouped into three LVM logical volumes. Each of these LVM logical volumes contains an empty file system ready to accept files. All content you save onto these LVM logical volumes is automatically encrypted.

The result of this task is illustrated in Figure 1.

What to do next

  • Create permissions for users to access data on the mounted file system.
  • Now a user can start to read and write data on the mounted file system, which is transparently encrypted or decrypted.

    For example, issue:

    
    $ echo ’what is secret’ > /crypted_lv1/mysecret 
    $ ls /crypted_lv1
    $ cat /crypted_lv1/mysecret
    
Note: You might encounter an out-of-memory error when opening a LUKS2 volume either during manual opening or during automated opening via /etc/crypttab at system startup. In such a case, read Out-of-memory errors when opening a LUKS2 volume for problem resolution information.