These days our computer enables access to a lot of personal information that we don’t want random strangers to access, things like financial login information comes to mind. The problem is that it’s hard to make sure this information isn’t leaked somewhere in your home directory like the cache file for your web browser. Obviously, in the event your computer gets stolen you want your data at rest to be secure; for this reason you should encrypt your hard drive. Sometimes this is not a good solution as you may want to share your device with someone who you might not want to give your encryption password to. In this case, you can encrypt only the home directory for your specific account.
Note: This article focuses on security for data at rest after that information is forever out of your reach, there are other threat models that may require different strategies.
Improving Upon Linux Encryption
I have found the home directory encryption feature of most Linux distributions to be lacking in some way. My main concern is that I can’t change my password as it’s used to directly unlock the encrypted directory. So, what I would like is the ability to have is a pass phrase that is used as a encryption key, but is itself encrypted with my password. This way, I can change my password by re-encrypting my pass phrase with a different password. I want it to be a pass phrase because that makes it possible to back it up in my global password manager which protects me in the case the file holding the key gets corrupted, and it allows me to share it with my IT admin who can then put it in cold storage.
Generate a Pass Phrase
So, how do we do this? First generate the key, for that I have slightly modified a Bitcoin wallet pass phrase generator that I use to generate the key as follows:
$ git clone https://github.com/Bluebugs/bitcoin-passphrase-generator.git $ cd bitcoin-passphrase-generator $ ./bitcoin-passphrase-generator.sh 32 2>/dev/null | openssl aes256 -md sha512 -out my-key
This will prompt you for the password to encrypt your pass phrase, and this will become your user password. Once this command has been called, it will generate a file that contains a pass phrase using 32 words out of your system dictionary. On Arch Linux, this dictionary contains 77,649 words, so one possibility in 77649^32. Anything more than 2^256, should be secure enough for some time. To check the content of your pass phrase and back it up, run the following:
$ openssl aes256 -md sha512 -d -in my-key
Once you have entered your password it will output your pass phrase: a line of words that you can now backup in your password manager.
Encrypt Your Home Directory
Now, let’s encrypt the home directory. I have chosen to use ext4 per directory encryption because it enables you to share the hard drive with other users in the future instead of requiring you to split it into different partitions. To initialize your home directory, first move your current one out of the way (This means stopping all processes that are running under your user ID and login under another ID). After this, load the key into the kernel:
$ openssl aes256 -md sha512 -d -in my-key | e4crypt add_key 2>1
This will ask you for the password you used to protect your pass phrase; once entered, it adds it to your current user kernel key ring. With this, you can now create you home directory, but first get the key handle with the following command:
$ keyctl show | grep ext4 12345678 --alsw-v 0 0 \_ logon: ext4:abcdef1234567890
The key handle is the text that follows ext4 at the end of the 2nd line above, this can now be used to create your new encrypted home directory :
$ mkdir /home/user $ e4crypt set_policy abcdef1234567890 /home/user
After this, you can copy all of the data from your old user directory to the new directory and it will be properly encrypted.
Setup PAM to Unlock and Lock Your Home Directory
Now, we need to play with the PAM session handle to get it to load the key and unlock the home directory. I will assume that you have stored my-key at /home/keys/user/my-key. We’ll use pam_mount to run a custom script that will add the key in the system at login and remove it at log out. The script for mounting and unmounting can be found on GitHub.
The interesting bit that I’ve left out of the mounting script is the possibility to get the key from an external device or maybe even your phone. Also, you’ll notice the need to be part of the wheel group to cleanly unmount the directory as otherwise the file will still be in cache after log out, and it will be possible to navigate the directory and create files until they are removed. I think a clean way to handle this might be to have a script for all users that can flush the cache without asking for a sudo password; this will be an easy improvement to make. Finally, modify the pam system-login file as explained in the Arch Linux documentation with just one additional change to disable pam_keyinit.so.
In /etc/pam.d/system-login, paste the following:
#%PAM-1.0 auth required pam_tally.so onerr=succeed file=/var/log/faillog auth required pam_shells.so auth requisite pam_nologin.so auth optional pam_mount.so auth include system-auth account required pam_access.so account required pam_nologin.so account include system-auth password optional pam_mount.so password include system-auth session optional pam_loginuid.so #session optional pam_keyinit.so force revoke session [success=1 default=ignore] pam_succeed_if.so service = systemd-user quiet session optional pam_mount.so session include system-auth session optional pam_motd.so motd=/etc/motd session optional pam_mail.so dir=/var/spool/mail standard quiet -session optional pam_systemd.so session required pam_env.so
Now, if you want to change your password, you need to decrypt the key, change the password, and re-encrypt it. The following command will do just that:
$ openssl aes256 -md sha512 -d -in my-old-key | openssl aes256 -md sha512 -out my-new-key
Et voila !