[TriLUG] encrypted filesystems

Alan Porter porter at trilug.org
Thu Apr 27 16:03:12 EDT 2006


Ever since I played with Knoppix 3.3, I have been fascinated with
encrypted filesystems (Knoppix allows you to keep your persistent
data on a USB pen drive, either in the clear or encrypted).

If you have not played with encrypted filesystems, the magic is
done by the 'loop' device, /dev/loop#.  I won't go into it here,
but you can Google for 'cryptoloop'.

Recently, I read an article that showed how to do some neat tricks
with encrypted filesystems.  Most of the time you simply encrypt a
filesystem using a passphrase.  However, if you want to change your
passphrase, you have to create a second encrypted filesystem with
the new passphrase and then copy over all of your data.  Ugh.  This
article explained how to use a key file, and then encrypt that key
file with your passphrase.

This led me to experiment a little, and it eventually led to a
little shell script to automate the process.  I have included it
here, because I think the TriLUG community might find it useful.

You can play with it in your own home directory (it does not have
to be used on a USB pen drive, but that's a good situation where
an encrypted filesystem is handy).

Simply run the script to create an encrypted filesystem image:

   sudo ./crypto.sh create test1

It'll ask you a few questions and then create a big file that looks
like gibberish.  Then mount the filesystem:

   sudo ./crypto.sh mount test1

It'll create a mount point directory called "test1.mnt" and it will
mount the encrypted filesystem there.  When you're done, just unmount
it the same way.

   sudo ./crypto.sh umount test1

You can change the passphrase with the script as well.

   sudo ./crypto.sh password test1

None of this stuff is really new, and it's not really rocket science.
But I liked how the article used that key file, and I have found the
script to the useful.  Maybe you will, too.

If you have questions about the script or about encrypted filesystems
in general, email me (either on-list of off-list).

Alan


[1] One common gotcha is storing a journaled filesystem image on top
of another journaled filesystem -- this can lead to data corruption.
In my script, I use a non-journaled ext2 filesystem.  In practice, I
store this image on a FAT-based USB pen drive.

[2] This script was written for use on a Ubuntu system.  I have seen
problems under Fedora, since their version of losetup took different
command-line parameters.  I might not have had loop-aes-utils installed
properly.


--



#!/bin/sh

#-------------------------------------------------------------------------------

usage() {
   echo "$program_name [ mount | unmount | create | password ] <basename>"
   echo "   example: $program_name mount crypto"
   echo "            mounts the 'crypto.img' filesystem on 'crypto.mnt'"
   exit 0
}

#-------------------------------------------------------------------------------

find_available_loop_device () {
   for loop_device in `( cd /dev ; ls -1 loop[0-9]* )` ; do
      sudo losetup /dev/$loop_device 2> /dev/null
      if [ $? -gt 0 ] ; then
         return
      fi
   done
   loop_device=""
}

#-------------------------------------------------------------------------------

find_loop_device_in_use () {
   loop_device=`losetup -a | grep "\($image_file\)" | sed -e 
"s/^\/dev\///g" | sed -e "s/:.*$//g"`
}

#-------------------------------------------------------------------------------

crypto_mount () {
   # set up a loop device
   find_available_loop_device
   echo "Openssl will now ask for the password to the encrypted drive..."
   openssl aes-256-ecb -d -in $key_file | losetup -p 0 -e AES256 
/dev/$loop_device $image_file
   if [ $? -ne 0 ] ; then
      echo "Could not set up the loop device '$loop_device'."
      losetup -d /dev/$loop_device
      return
   fi
   echo "The loop device '$loop_device' has been set up."
   losetup /dev/$loop_device
   # create a mount point
   mkdir $mount_point
   # mount the filesystem
   mount -t ext2 /dev/$loop_device $mount_point
   if [ $? -ne 0 ] ; then
      echo "The encrypted drive was not mounted properly."
      losetup -d /dev/$loop_device
      return
   fi
   echo "The encrypted drive has been mounted OK."
}

#-------------------------------------------------------------------------------

crypto_unmount () {
   # unmount the filesystem
   umount $mount_point
   if [ $? -ne 0 ] ; then
      echo "Could not unmount the encrypted drive."
   else
      echo "The encrypted drive is unmounted."
   fi
   # remove the mount point
   rmdir $mount_point
   # de-configure the loop device
   find_loop_device_in_use
   for ld in $loop_device ; do
      losetup -d /dev/$ld
      if [ $? -ne 0 ] ; then
         echo "Could not deactivate the loop device '$ld'."
      else
         echo "The loop device '$ld' has been deactivated."
      fi
   done
   # change the timestamp so we know that the image file may have been 
modified
   touch $image_file
}

#-------------------------------------------------------------------------------

crypto_password () {
   echo "You are about to change the password for the encrypted drive."
   echo "Enter the old password..."
   plain=`openssl aes-256-ecb -d -in $key_file`
   echo "Your old key file will be saved as '$key_file.old'."
   mv $key_file $key_file.old
   echo "Enter the new password (twice)..."
   echo $plain | openssl aes-256-ecb -e -out $key_file
   echo "The password has been changed."
}

#-------------------------------------------------------------------------------

crypto_create () {
   # create the image file
   if [ -f $image_file ] ; then
      echo "File '$image_file' already exists... operation aborted."
      return
   fi
   echo -n "Enter the filesystem size in megabytes: "
   read size
   dd if=/dev/zero of=$image_file bs=1M count=$size
   # create the key file
   plain=`head -c 2880 /dev/urandom | uuencode -m - | head -n 65 | tail 
-n 64 | tr -d '\r\n'`
   echo "Enter the encryption password (twice)..."
   echo $plain | openssl aes-256-ecb -e -out $key_file
   # find an available loop device
   find_available_loop_device
   # configure the loop device
   echo $plain | losetup -p 0 -e AES256 /dev/$loop_device $image_file
   # create the filesystem
   mkfs.ext2 /dev/$loop_device
   # de-configure the loop device
   losetup -d /dev/$loop_device
}

#-------------------------------------------------------------------------------

crypto_test () {
   find_available_loop_device
   echo "available=[$loop_device]"
   find_loop_device_in_use
   echo "in_use=[$loop_device]"
}

#-------------------------------------------------------------------------------

# PERMISSIONS

if [ $EUID -ne 0 ] ; then
   echo "You must be root to run this script."
   exit
fi

# COMMAND-LINE OPTIONS

program_name=`basename $0`
if [ $# -ne 2 ] ; then
   usage
fi
action=$1
basename=$2

# CONFIGURATION

image_file="$basename.img"
key_file="$basename.key"
mount_point="$basename.mnt"

 # load mondules
modprobe aes
modprobe cryptoloop

# COMMAND-LINE PARAMETERS

case "$action" in
   mount)
      crypto_mount
      ;;
   unmount|umount)
      crypto_unmount
      ;;
   password|passwd)
      crypto_password
      ;;
   create)
      crypto_create
      ;;
   test)
      crypto_test
      ;;
   *)
      usage
      ;;
esac





More information about the TriLUG mailing list