Protecting Files at Home Using Encrypted Containers

Many people encrypt partitions or drives to keep data safe, but if you're looking for something a little simpler but still safe, try using containers.

Chances are you have some type of information on your desktop or
laptop computer that someone else wants--for the wrong reasons. For the
most part, your information is relatively safe in your home. However,
if someone was to break into your house and steal a computer,
what would he or she walk away with? Medical information? Bank account
information? Tax records? With the loss of any of these to the wrong
person, you could be facing years of trying to get your life straightened
out due to identity theft.

Concerned about this type of situation, I decided to engineer a way of protecting my family's
critical information. But before I started, I had to set a few goals
for whatever it was that I built:

It had to be as simple as possible to
use.

Data loss was not acceptable.

The data had to be protected even if a computer
physically was stolen.

The first goal, simple to use, was absolutely necessary. I wouldn't be
the only one using the system, so it had to be geared toward someone
non-technical. Setting it up could be difficult, but in the long run
it wouldn't be used or useful if the solution itself was difficult. Data loss
also was an important criterion. Protected data is worthless if you have no
way of getting it back in the event of a hard drive failure. The last
criterion was the main point of doing this whole project: if a computer was stolen,
how long would it take before I could get a full night's sleep knowing
that someone had access to all the information necessary to steal the
identity of one of my family members?

Once my goals were set, I went about researching my options and evaluating
ideas. I finally settled on using an encrypted "container" that could
function like any other storage device, but only when needed. To prevent data
loss, it would be backed up to my home server. On the home server, the same technology
would be used to protect my backups and where I centrally could burn
a CD or DVD for off-site storage.

The first step to protecting my data was to figure out how to create an
encrypted container. After doing some research, I discovered there were
two ways to do this. I could use either cryptoloop or its successor,
dm_crypt. A considerable amount of information is available for
using cryptoloop, but I quickly discovered that it has been deprecated
and replaced by the more secure dm_crypt kernel module.

Prerequisites

To complete the encrypted container configuration presented in this
article, you must satisfy the following short list of prerequisites:

Kernel version 2.6.4-rc2 or higher must be
installed.

KDE version 3.3 or higher must be
installed.

You must have root access to complete the initial
setup.

I currently am running this configuration under kernel version 2.6.12
on several Gentoo systems, both x86 and AMD64. I also have used it on kernels
starting around version 2.6.6. The scripts I present here for making
the system easy to use have been used under KDE versions 3.3.x and
3.4.x. Older versions of KDE also may work, but they have not been tested
by me.

Configuring Your System

To use dm-crypt, a few modules must be compiled or built into the
kernel. You first must enable the device-mapper module that lets you
create new logical block devices from portions of existing devices. The
block devices then are "mapped" to devices that for our use are treated like normal
drive partitions. Once device-mapper is enabled, you then can enable
dm-crypt itself; it goes by the name Crypt Target Support
in the kernel configuration menu. dm-crypt is the kernel module that we
actually use to handle the encryption/decryption using the crypto API
available in the 2.6 version kernels.

To use an encrypted container for our files instead of an entire drive
or partition, loopback device support also needs to be enabled in the
kernel. The loopback device kernel module allows us to use ordinary files
as if they were real block devices. Finally, you must have the encryption
type you want to use compiled into the kernel or set as a module. In the
examples given here, I use the AES encryption algorithm, but many other
options are available.

Once you have enabled the required kernel modules, compile the kernel
and install it. Because I did not build the modules directly into the
kernel, I added the necessary modules--dm-mod, dm-crypt and aes-i586--to
/etc/modules.autoload/kernel-2.6 on my Gentoo boxes so they would be
loaded automatically at boot. Below is a list of kernel modules you need
to enable in the kernel:

For other systems where there may not be a central location to
load kernel modules automatically at boot, you could add the appropriate
modprobe commands to a startup script. For Debian-based systems such
as Ubuntu, the script to use is the /etc/init.d/bootmisc.sh startup
script. For other distributions you can use /etc/init.d/rc.local. Here
are suggested commands to add to startup scripts for non-Gentoo
distributions:

modprobe dm-mod
modprobe dm-crypt
modprobe aes

Now that the kernel has been configured, two packages must be installed
that will be used to ease the creation and use of
the encrypted container as a device. The first package you need to
install is the device-mapper utilities. Under Gentoo, simply executing
emerge device-mapper automatically downloads,
compiles and installs the package. It already may be installed in other
Linux distributions. An easy way to tell if you already have the
device-mapper package installed is to look to see if /dev/mapper
and /dev/mapper/control already exist. If they do, the device mapper is
installed. Otherwise, for Debian-based systems such as Ubuntu, you
can execute apt-get install libdevmapper.
If you're using a different distribution, check your package management
system and see if it can be installed easily. If not, refer to the
Resources section for a link to where you can download it directly.

The second package you need to install is the cryptsetup utility. Under
Gentoo, it can be installed by executing emerge
cryptsetup. Again, if you are using a different Linux
distribution, cryptsetup already may be installed for you
or available through the package management system. You can determine if
the package already is installed by checking to see if the cryptsetup command
is available, most likely in the /bin directory. Otherwise, refer to the
dm-crypt listing in Resources for the link to the download.

Creating the Encrypted Container

After rebooting with your new kernel, you are ready to create the
container for your files and mount it. Select a partition with enough
space to create the container and make the container large enough to
support all the files you want to put into it. Don't forget to make
it large enough to hold new files. Keep in mind that at the time
this article was written, it was not possible to increase the container
size once it's created. Instead, you have to create a new, larger drive
container, copy everything from the old one to the new one and then delete
the old container.

To create the container file, use the dd command; it typically is
used to copy drive partitions. In the example below, I specified a
block size of 1MB and that the container should be 2,048 blocks
in size. This equates to a container that is 2GB in size--1MB block size X 2,048 blocks.

As a source for the dd command, I used a special device that outputs
nothing but zeros when read. Others have suggested that using /dev/random
may be better, because it makes it impossible to determine how much of
the container actually is being used. The choice is up to you. I also
used a partition (/encrypted) that I set aside specifically for storing
my containers.

dd if=/dev/zero of=/encrypted/data.crypt bs=1m count=2048

Now, create a loopback device using your container file. If you use
multiple containers, you have to use a different /dev/loopX
device--where X is a unique number--if you want them all to be mounted
at the same time. I chose to put specific containers on specific numbers in my
scripts (details below) so I know which one is using which loopback
device.

losetup /dev/loop0 /encrypted/data.crypt

Next, create the encrypted device. In the example given below, I chose
to use the AES encryption algorithm, which was compiled as a kernel module during
kernel configuration. When the device is created, you must specify
a password, otherwise known as a key, that is used to encrypt and
decrypt everything in the container. This can be a secure password that
you specify on the command line. In my case, I used /dev/random to
generate a 32-character random string (256 bits) that I stored in a file
named /home/pritchey/crypto.key temporarily; more on this later.

You now have something that acts like a normal drive partition. In order
to mount and use it, you must create a filesystem on it. I chose to
use the ext2 filesystem, but others can be be used. Once
the filesystem is created, it can be mounted like a regular drive
partition.

Once mounted, your encrypted device acts the exact same way that a normal
drive partition does. You can copy files to it, delete them, edit them
and so on. The only difference is you must remember to unmount the
device properly and destroy the loopback setup when you are done with it:

This solves the problem of protecting our data. But, for non-technical
users, these commands are difficult to remember and scary looking--not
to mention they require root access. The next step is to automate the
mounting/unmounting of the encrypted containers in a way that is easy
to do yet not obvious to someone who might not think to look for them.

Automation Creation, Part I

To automate the mounting/unmounting of the encrypted container, I turned
to my favorite search engine and a coworker. The problem I encountered
when trying to create a script for the above commands was root access
is required to set up everything. I wanted others in the house to be
able to use the encrypted containers, but they're not experienced enough
yet to be trusted with root-level access. Carlos, a co-worker, once had
to solve a similar problem that required root access to run a script,
yet didn't warrant the use of sudo. He found a Perl script that did the
trick when the sticky bit was set, essentially acting as a wrapper
around the real script. I searched the Web and couldn't find the Perl
script, but I did stumble upon exactly what I needed: a tiny program written in
C that acts as a wrapper (see Resources) around a script that needs
root privileges. All that was required was changing the commands the
program was supposed to run, compiling the program and copying it into place
with the sticky bit set.

To use the wrapper, you need to change three values before compiling
it. First, set the variable myprog to the script that you want to
execute. The second variable, named myarg1, contains the name of the
loopback device (/dev/loopX) to be used. The last variable,
myarg2, is set to the name of the container that you want to mount. For
my naming scheme, I add a .crypt to the end of my container file
names. I also named my key files in a similar manner, ending them with
.key. Here is the C source code for wrapper.c:

Once the appropriate changes are made, compile the program, copy it into place
and be sure to set the permissions correctly. I chose to create a
special group in /etc/group only for users that should be able to mount
the encrypted container (named crypto). The permissions and
ownership of the directory the encrypted device is mounted to, created in
a previous step as /mnt/encrypted, is also set this way. This prevents
other users who have accounts on the computer from mounting or accessing
the encrypted devices.

To handle unmounting the encrypted containers, you need to use the
wrapper program again--named encryptoff in the sample scripts. This
time, though, it calls a script containing the appropriate commands to
undo the encrypted container. Here is a sample script for unmounting a
mounted encrypted container:

The script called from the above wrapper is written so that when
called with two parameters, it would be able to mount any encrypted
container. That way I could have as many wrappers as needed that are
unique to each specific encrypted container but only have one script that
actually performs the mounting and unmounting. The script assumes that
the encrypted container ends in .crypt and the key file ends in .key,
but both have the same beginning name that's passed as the second parameter.

To help increase security, I also decided to store the key (password)
used for the encryption device on a USB thumb drive. It's never a good
idea to store passwords in files, but in this case the key is impossible
to remember. As long as the thumb drive is kept separate from the
computer it belongs to--locked in a safe, for example--it would be an
adequate solution. If the computer is stolen, the likelihood of the thief
taking the USB key along with the computer and knowing what to do with it
is small. And with a 256-bit (32-character) key, the system would be difficult
to crack by brute force methods.

So the automation script also is responsible for
mounting the USB thumb drive and unmounting it when done. This minimizes
the amount of time the thumb drive needs to be connected to the
computer. Hopefully, this helps minimize the chances of someone leaving
it connected, as the drive can be removed immediately after logging in (detailed later).

This design partially solves the ease of use requirement, but it still
requires someone to remember a command, which could be named anything I
want in order to hide it. I had an idea, and searching the Web revealed
that KDE has two special directories that can contain scripts or links
to executables the user wants run when he or she first logs in or out.
Every user's home directory contains a hidden directory named .kde. This is
where the two directories used for login/logout are located. The directory
used on login is called Autostart, note the capital letter A. Simply
place a script here that executes as many of your wrappers as needed.
Here is the sample script I placed in my /home/pritchey/.kde/Autostart
directory:

#!/bin/bash
/bin/mysecretcommand
/bin/mysecretcommand2
...

Similarly, we can use the directory .kde/shutdown with another script
to unmount and clean up automatically any encrypted containers. This is
the final piece that solves the ease of use issue. To use the system,
all you need to do is power on the computer, plug in the USB thumb
drive with the keys to the encrypted containers and log into KDE. Once
logged in, unplug the thumb drive and return it immediately to its hiding
spot. If you log in before remembering to plug in the thumb drive, you
either can log out and back in again with the thumb drive attached
or execute the wrapper command from a shell prompt.

Almost Done

One remaining requirement needs to be addressed: protecting ourselves
from data loss. I had solved this problem before, so it simply
was a matter of integrating the encrypted containers into my
backup system. All of my systems are set to back up users' home
directories when they log out of KDE, which is triggered by a script in
.kde/shutdown. All I needed to do was modify the script to handle the
encrypted containers when they are mounted. This script executes rsync
and saves any changed files to a server. I modified the backup script
to take parameters specifying the directory to be synced. The default
is to sync the user's home directory with the backup location on the
server. The script in the user's shutdown directory then was modified
to detect if the encrypted containers were mounted and if so, rsync it
before unmounting. Syncing the mounted data is much faster than trying
to sync the large container file itself, even on a quiet home network.
Here is the script I placed in /home/pritchey/.kde/shutdown:

#!/bin/bash
# Look to see if our encrypted partitions have been mounted
# and if so back them up before unmounting them.
is_projects_mounted=`df | grep encrypted_projects`
is_encrypted_mounted=`df | grep encrypted | grep -v projects`
if [ "$is_projects_mounted" != "" ]; then
/home/pritchey/scripts/backup_rsync.sh /mnt/encrypted_projects
fi
if [ "$is_encrypted_mounted" != "" ]; then
/home/pritchey/scripts/backup_rsync.sh /mnt/encrypted
fi
# Now that they have been properly backed up, umount the
# encrypted partitions. Call the wrapper that calls the
# script with the commands to 'undo' the mounted containers.
/bin/encryptoff
# Now backup non-encrypted data so we have an off computer backup.
/home/pritchey/scripts/backup_rsync.sh

And here is the general purpose directory backup script referenced in my KDE
shutdown script:

I have read many articles on encrypting entire partitions and drives,
but I chose to use containers instead. By using containers, I have the
flexibility to move them around, back them up to CD or DVD and not
mount them when I don't need them. If the situation was different,
I may have chosen the route of using encrypted partitions or drives. In
the beginning I also was concerned about the performance impact of using
an encrypted system. In a year's worth of use, though, I have not noticed
any performance problems.

The backup script I use obviously can be expanded to be much more robust.
For my home use, it's proven to be reliable enough. But in a work
environment, I would take the time to add additional safety checks. I
also chose not to go into too much detail here about the use of rsync.
Many good articles detailing the use of rsync are available, and you
might decide to use another method for performing backups.

In order to complete the protection of my systems, I also have included the
commands used to unmount the encrypted containers in the system shutdown
scripts. This way, if a system is shutdown remotely or the UPS software
shuts the system down, the encrypted containers are unmounted properly and
cleanly.

I would like to thank Carlos for the pointer to the idea of using an suid
wrapper and Darryl for testing the scripts and installation procedure
presented here. I have enjoyed working with both of them over the years,
and they have proven to be great resources of information for things
nobody else can figure out.

First, I'd like to thank all of you who have taken the time to read the article, and especially those who have taken the time to respond.

Rather than respond to each individual comment, I'll post my comments in this single post instead since there seems to be just a few themes...

1. KDE is not needed. KDE Just happens to be my current desktop of choice and in order to meet the requirements I set my solution to the problem needed to be integrated into it (primarily for other family memebers who are less technical). And no, I am in no way associated with the KDE project :-) I've used Gnome, Enlightenment and KDE at various times. KDE just happens to be the one in use right now.

2. The key is NOT stored on the hard drive, down towards the bottom of the article I present a few scripts that I use that execute everything based on the key being on a USB thumb drive. Most thiefs probably wouldn't know what to do with a linux box if they stole one, but I did decide to go the extra step and keep the key on something physically separate rather than rely completely on security by obscurity.

3. Brett Neumeier provided a much more elegant solution to generating the key from /dev/random by using the dd command. Thanks you! I keep forgetting about that command, much less the fact it would have made key generation easier!

4. LUKS as an alternative: Thank you for posting about this project. I wasn't aware of it before. Unfortunately when I actually implemented this LUKS didn't exist at the time.....

5. Dave Vehrs posted a warning that the commands used to mount/unmount the encrypted containers may appear in your shell's history. That is correct, if you issue the commands by hand. I just checked and the commands do not appear if you use the automated capability provided by the KDE Autostart and shutdown directories. For many, encrypted the entire drive may be a better solution. In my case I decided that wasn't the solution I needed and chose to go the encrypted container route.

6. There was a comment about my backups. My backup server is using the same setup - the backups reside in an encrypted container that gets 'undone' on shutdown automatically OR undone on startup in the event the power cord is pulled. There is NO automation on the backup server to automaticaly remount the encrypted containers, and the server is locked down tight (as are the desktop boxes). The only item I'm missing is performing the rsync over an SSH tunnel, which for a home hardwired network isn't really necessary. Keep in mind, this is meant to provide adequate protection for a _home_ environment. For a work environment I would do some things differently in order to provide a more robust system, but those items are beyond the scope of this article.

7. Thank you for reminding me about ENCFS. I seem to remember looking at it when I started implementing this, but I can't remember why I decided not to use it. It is definitely worth looking at though.

Just a few observations for the new user trying to implement this in Fedora Core 3.

1- The use of /dev/random for some reason does get the job done. I tried and it stopped at some point but didn't get what I wanted in size. So I used /dev/zero as suggested by the article.

2- cut will not cut exactly 32 bytes, so instead I usedhead -c 32 foo

3- dd didn't take the bs=1m, the m has to be capitalized, like this bs=1M

4- cryptsetup is not in /bin but in /sbin so change scripts accordingly.

5- You don't need KDE in order to run the scripts when the session starts and finishes. You can do same thing from the file in your home directory called .Xclients
Just add it before and after this part:
script_to_mount
exec $HOME/.Xclients-default
script_to_umount

And you should be done. If you don't have that file, use the program
switchdesk KDE|GNOME|ICEWM|ETC

and it will create it.

If you want to do it permanently for all users and new users, modify the "template" file found in /usr/share/switchdesk/Xclients.toplevel

1. You are correct. KDE is not needed. But it does show a way of integrating it the whole process using the startup/shutdown capability provided by KDE on login. The same idea could be used for other desktop environments or even terminal logins (via the default shell's config files).

2. You are incorrect. Under the section titled Automation Creation, Part II 2nd paragraph the author states that he is using a USB thumb drive to store the key which is kept physically separate from the computer.

This is something I need to give more thought to before I try to implement a transparent encryption scheme on my own computers.... but the skeleton given here is a great starting point, thanks!

The main flaw in the design I see, is this. Ignoring the "security boundaries" arguments for a moment (or assuming this has been solved by control) -- that is, even assuming that your sensitive data never leave the container in a cleartext form:

How exactly does this protect your data from a thief?

The encryption key has been left on the computer along with the containers! Can't the theif just take the hard drive out, mount it in their own system, discover the encrypted containers, these mounting scripts and the key and then mount the containers to get at the data? Sure, this would take a clueful thief, probably not something your average house-breaker could manage, but well within the abilities of an experienced identity-theft criminal.

I would have liked to see a way of keeping the key safe from being stolen (or discovered) along with the computer, such as on a USB drive or a floppy, or by encrypting the key with a pass-phrase.

These approaches are not perfect either, I admit: you have to remember to insert and remove the medium containing the key, or enter a pass-phrase to decrypt the container key before mounting, which would break the "simple to use" requirement, I suppose.

Assuming that /home is mounted on a physical disk, both foo and crypto.key are on disk and the rm command does not remove them from disk. (rm simply removes the pointers. The data is still on disk and easily recovered.) If You must create the key files on disk you need to use wipe rather than rm to clean them off your disk. A better idea is to create them on a USB drive in the first place.

Read the section Automation Creation, Part II. A USB thumb drive is used for storing the key, and the scripts provided handle the automounting of the USB drive, mounting the encrypted container and then unmounting the USB drive so it can be removed from the computer and put back to its hiding place.

Have a look at LUKS before doing everything by hand as suggested in this article. Additionally LUKS has sophisticated key management features, e.g. it is possible to define multiple keys for a container.

I might be missing something but when you rsync the files to your server they are mounted and unencrypted. This means unencrypted copies of your files are sitting on the server. What happens if someone takes the server instead of the laptop or if the server is compromised in some other way.

About what security we can discuss, if the crypto key is stored in the FILE residing on THE SAME system?! Or for the storage of crypto keys other crypto storage is intended to be made? (it seems that LUKS also is not storing the keys necessaary to access the respective crypto device which is right by my understandig of how the crypto-things works)

Funny, I implemented almost the same solution to burn encrypted DVDs.
Here are some things I encountered that other users might hit when they try this at home:

Container sizes are fixed, and existing containers cannot be resized. Especially when making backups you must know the overall backup size before creating the container.

Filesize limits for the container file. Most filesystems have limits to filesize, especially the filesystem type used for DVDR and CDR (iso9660) is 4G. Well, in reality the limit depends on your hardware and/or software. But on my system 4G files work. So you should not use too large containers if you want to be able to burn it to DVD.

The key file (crypto.key) is small, but very important. I am storing multiple copies of the key file for redundancy since I burn the stuff to DVD, and one of the key files might get corrupted.

There is a nice new format called LUKS which stores the key redundant in the container. I have not tried it yet though.

Another way of avoiding root privileges is to use the utility "cryptmount" (see here), which allows setup of device-mapper targets for both raw partitions and looopback files. Root privileges are only needed for the initial setup, and dm-crypt keys are stored in encrypted form (using openssl).

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.