Opening and mounting an encrypted volume at user login

Automatically opening one or more volumes at user login has the advantage that only a certain user can access the data.

Before you begin

Important: At the time of writing, LUKS2 support for pam_mount is provided by the following distributions:
  • Ubuntu 19.04
  • SUSE Linux Enterprise Server 12 SP5
  • SUSE Linux Enterprise Server 15 SP1

Without LUKS2 support, the functionality described in this topic does not work.

You must install the pam_mount package. See the web site at http://pam-mount.sourceforge.net/. Some Linux® distributions provide the pam_mount package.

Ensure that the pam_mount package is configured and the pam_mount.so PAM module is used in the auth and session sections of the PAM configuration files. Your Linux distribution might already perform this for you. See also the pam_mount man page for more information.

About this task

In the scenario you create a user called alice. The home directory for this user is stored on an encrypted volume. The encrypted volume is opened when the user logs in and respectively closed at logout. The encrypted volume in this example is /dev/mapper/disk10.

Procedure

  1. Create a user and set an initial password.
    For example, issue:
    
    # useradd -G users -m -s /bin/bash alice
    # passwd alice
    Enter new UNIX password: alice
    Retype new UNIX password: alice
    passwd: password updated successfully
    
  2. Create a secure key in the secure key repository for user alice with the zkey command.
    # zkey generate --name user-alice-xts --key-type CCA-AESCIPHER --keybits 256 --xts \
    --volumes /dev/mapper/disk10:enc-disk10 --volume-type LUKS2 \
    --apqns 03.0039,04.0039  --sector-size 4096
  3. Format and open the encrypted volume /dev/mapper/disk10 and create a file system that is later mounted as home directory for user alice.
    For example:
    
    # zkey cryptsetup --volumes /dev/mapper/disk10 --run
    Executing: cryptsetup luksFormat --type luks2 --pbkdf pbkdf2
    --master-key-file ’/etc/zkey/repository/user-alice-xts.skey’
    --key-size 2176 --cipher paes-xts-plain64 --sector-size 4096 /dev/mapper/disk10
    
    WARNING!
    ========
    This will overwrite data on /dev/mapper/disk10 irrevocably.
    
    Are you sure? (Type uppercase yes): YES
    Enter passphrase for /dev/mapper/disk10: disk10pw 
    Verify passphrase: disk10pw
    
    Executing: zkey-cryptsetup setvp /dev/mapper/disk10
    Enter passphrase for '/dev/mapper/disk10': disk10pw
    
    # cryptsetup luksOpen /dev/mapper/disk10 user-enc-alice
    
    # mkfs.ext4 -L USER_ALICE /dev/mapper/user-enc-alice
    
    # cryptsetup luksClose user-enc-alice 

    If you plan to open the volume automatically during system startup, ensure that the --pbkdf pbkdf2 option is generated for the cryptsetup luksFormat command. Otherwise, insert this option manually before running the command. Also use the --pbkdf pbkdf2 option with the cryptsetup luksAddKey command in the alternatives described in steps 4 and 5. 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, read Out-of-memory errors when opening a LUKS2 volume.

    You can optionally mount the file system temporarily to copy or migrate existing files for the user.

  4. Perform Alternative 1:
    Disk passphrase and user password can be different. Therefore, you must provide the disk passphrase in a key file. The pam_mount module retrieves it from there. The advantage is that the user can change his passphrase anytime without influencing the disk passphrase. However, the disk passphrase is available in clear text (in our example, in file /etc/pam_mount_keys/alice.key). You might have to create this /etc/pam_mount_keys/ directory in advance. Ensure to establish the correct access rights.
    1. Create a file containing the disk passphrase.
      This file should contain a disk passphrase or a random character sequence. Example: /etc/pam_mount_keys/alice.key
    2. Add the disk passphrase to a new LUKS2 key slot on your volume (see also step 6 in Creating a volume for pervasive encryption).
      # cryptsetup luksAddKey --pbkdf pbkdf2 /dev/mapper/disk10 /etc/pam_mount_keys/alice.key
    3. Edit the pam_mount configuration file /etc/security/pam_mount.conf.xml. Add a volume definition for alice.
      
      <volume user="alice" path="/dev/mapper/disk10" mountpoint="~"
                    fstype="crypt" fskeycipher="none" 
                    fskeypath="/etc/pam_mount_keys/alice.key" />
                            
      
      See also the pam_mount.conf man page for details.
  5. Perform Alternative 2:
    Disk passphrase is the same as the user password. In this case, you add an additional key-slot to the LUKS header on your volume. The advantage is the enhanced security: the disk passphrase is nowhere available in clear text.
    Note: When the user password changes, the passphrase for the encrypted volume must also be changed.
    1. Add the disk passphrase to a new LUKS2 key slot on your volume.
      You are prompted for the phassphrase that you have specified when formatting the volume in step 3. In this scenario, it is disk10pw.
      # cryptsetup luksAddKey --pbkdf pbkdf2 /dev/mapper/disk10
      Enter any existing passphrase: disk10pw
      Enter new passphrase for key slot: alice
      Verify passphrase: alice 
    2. Edit the pam_mount configuration file /etc/security/pam_mount.conf.xml.
      
      <volume user="alice" path="/dev/mapper/disk10" mountpoint="~"
              fstype="crypt" />
      

Results

Now alice can log in to the Linux instance. The pam_mount PAM module opens the encrypted volume and creates a device in the /dev/mapper/ directory, for example, /dev/mapper/_dev_dm_21 which is then mounted as /home/alice.
# ssh alice@localhost
alice@localhost's password: alice
Welcome to your favourite Linux distribution

Last login: Mon Aug 06 16:28:45 2018 from 127.0.0.1

alice@localhost:~$ df | grep alice
/dev/mapper/_dev_dm_21   20507216 45080 19397384 1% /home/alice

alice@localhost:~$