How to get a usable full disk encryption with different encryptions for different users

dm-cryptecryptfsencryptionSecurity

I want to have a full system encryption on my laptop. But I have two users, one for home and one for work and want a separate encryption for both. Sure I could do a full disk encryption with dm-crypt and use a second encryption layer with ecryptfs to encrypt the home directories. However this seems not to be a good idea for performance reasons. So how can I setup a system such that:

  • the entire hard drive is encrypted
  • when user 1 is logged in and user 2 not, the data of user 2 is encrypted for user 1 and vice versa
  • I need to type in one password on boot which decrypts the system (like in a usual LVM/dm-crypt setup) and only a second one which logs in user x and decrypts his partition
  • the performance is similar to a simple full disk-encryption
  • the solution should work together with an ssd i.e. it should support TRIM

I want to use ubuntu as a distro for this, if this matters.

Best Answer

  1. Don't encrypt the whole hard drive (as in /dev/sda, do it per partition (or more precisely per file system - see below).

  2. Have separate file systems mounted at homes for the two users. I'm intentionally avoiding writing separate partitions, since while that is the usual way of doing things, it is constraining in some aspects. It might be more convenient to have one large home partition, which holds big files that contain the encrypted file systems and are mounted as necessary. The advantage is easier resizing of users' homes while keeping them separated.

  3. Automounts on login are possible through PAM. Note that you don't want to use the same password for login and for the actual data encryption. Instead, you either use LUKS or imitate it by storing the encryption key in a file that itself is encrypted with the login password. That ensures that a change of the login password won't affect the encrypted data but only the encrypted key and thus yo won't have to take care of re-encrypting whole users home).

General instructions:

  • partitioning use gdisk (also known as gptfdisk sometimes), parted or any other appropriate program, read man pages for details (partitioning is a bit out of scope of this QA)

  • encrypted file-based file systems - I have some objections to the design of LUKS, so I'm generally using cryptsetup in the "plain" mode, which imitates LUKS in some aspects. If you choose LUKS, than you can just reduce the steps to the cryptsetup (with appropriately modified options)

    1. prepare the encryption key and password. This is an interesting part - for encrypting the data you want something with enough randomness (8 letter password really isn't enough) and for password something that you can change easily (without needing to re-encrypt the whole filesystem) and is reasonably easy to remember and type in. These requirements go quite against each other. Hence we'll use the same trick that LUKS does (and which can actually be considered a variation of a hybrid cryptosystem in some sense)). The encryption key can be more or less random - either use some really random data (e.g. from /dev/random), or a reasonably long hash like SHA-2 or SHA-3 (the first one was designed by NSA, if you wonder whether to use it or not in light of the recent events) of a reasonably long passphrase.

      Reasonably long in the first case (and in the case of really random data) means, that the length should be about the chosen key length for the cipher used plus the length of the initialization vector. In the second case it means that it should be difficult to brute-force it. Using a hash has the advantage of being able to recover the key if it gets damaged or lost (provided you remember the initial passphrase that was hashed, of course). This key is then encrypted and stored in a file. The passphrase for the encrypted key in your case will be the same ass the login password.

      # set up the encrypted encryption key
      printf "Reasonably long and complicated passphrase" \
          | openssl dgst -sha512 -binary \
          | openssl enc -bf > /path/to/key.enc
      

      openssl dgst -sha512 -binary produces binary form of the SHA-512 hash from its standard input, openssl enc -bf encrypts it using Blowfish - feel free to choose hash and cipher to your liking (Twofish or Rijndael are both rather well-tried, but other ciphers available in the kernel should be fine too).

      Keeping the key outside of the encrypted device has a disadvantage of needing additional thing apart from the encrypted data itself - LUKS stores the key in its headers, so it's self-contained. On the other hand you are bound to a particular set of tools. While it is not designed carelessly and is present on most installations, you need the special tools to access it.

      With a separate file on the other hand, you are free to choose any method of storing the key. You can even put it on removable media, insert it before login and remove it once the file system is mounted (you could probably even hook automatic login on the event of attaching the media to the computer). Of course all this should be well thought through since the security maxim "Do not invent your own crypto" applies (see e.g. this post on Security SE) - which might actually be an argument for using LUKS. Backing up the key is obviously easy.

    2. create an empty file that will hold the file system

      dd if=/dev/zero of=/path/to/backing_file.enc bs=1M count=X
      
    3. create the encrypted device

      openssl enc -bf -d -in /path/to/key.enc 2>/dev/null \
          | cryptsetup create \
                  -c twofish-cbc-essiv:sha256 \
                  -s 256 \
                  -h plain \
                  encryptedfs /path/to/backing_file.enc
      

      openssl enc -bf -d asks for password on stdin and tries to decrypt the encryption key. cryptsetup create ... encryptedfs /path/to/backing_file.enc created encrypted DM device called encryptedfs backed by the previously created file. Important option it the -c which selects the encryption cipher and its mode of operation

    4. fill the device with zeros - this effectively puts "random garbage" into the backing file and makes it less obvious, what the contents of the file might be (otherwise, you could tell where things have been written by scanning for blocks that are not zeroed from step 2).

      dd if=/dev/zero of=/dev/mapper/encryptedfs bs=1M
      
    5. Create a filesystem

      mkfs.[favourite_filesystem] [tuning options] /dev/mapper/encryptedfs
      
    6. Put a corresponding line into /etc/fstab in case you want to do everything on your own, or into /etc/crypttab if you want some sort of integration with system tools.

  • for automatic (un)mounting on login/logout, I'll refer you to the pam_mount documentation.

Related Question