Enhanced startup script to encrypt and mount truecrypt disks

The below script can be used to mount truecrypt-encrypted disks at system startup and dismount them at system shutdown. It optionally includes a target to encrypt a disk (by running /etc/init.d/tc.sh create_encrypted_disk sdX). To use, copy the code sction into /etc/init.d/tc and create a simple configuration file /etc/tc.conf (sample provided below).

This is tested on Debian-like systems, but can be adapted for use in other Linux distributions.

The mounted disks are exposed as /dev/mapper/truecrypt${SLOT} devices.

Additional references:
1. Create encrypted disk using truecrypt. See encrypting a disk using truecrypt.
2. Create encrypted file container using truecrypt. See encrypted file container using truecrypt.
3. An earlier version of the below script. See mount encrypted disk at startup.

#!/bin/bash
# Mount and unmount encrypted disks and partitions.
#
### BEGIN INIT INFO
# Provides: tc
# Required-Start: $remote_fs $syslog $time
# Required-Stop: $remote_fs $syslog $time
# Default-Start: 2 3 4 5
# Default-Stop: 1
# Short-Description: Encryted volume support
# Description: tc provide support for mounting
# encrypted disks and disk volumes
### END INIT INFO

test -f /usr/bin/truecrypt || exit 0
. /lib/lsb/init-functions

CONFIG="/etc/tc.conf"

get_disk_uuid() {
local _disk=$1
local _resultvar=$2
local _result=`ls -lah /dev/disk/by-id | grep -E '^.*?scsi..*?'${_disk}'$' | cut -d' ' -f11`
eval $_resultvar="'$_result'"
}

create_truecrypt_key() {
local _disk=$1
local _resultvar=$2
local _diskid=
local _keyfile

get_disk_uuid ${_disk} _diskid
_keyfile=/etc/`hostname`-${_diskid}.key

truecrypt --create-keyfile ${_keyfile} \
--hash=Whirlpool \
--random-source=/dev/urandom

chown 600 ${_keyfile}
echo "Created truecrypt keyfile=${_keyfile}."
KEYFILE=${_keyfile}
}

create_encrypted_disk() {
local _disk=$1
local _keyfile=
local _diskid=

create_truecrypt_key ${_disk} _keyfile
_keyfile=$KEYFILE

get_disk_uuid ${_disk} _diskid

truecrypt --filesystem=none --volume-type=normal --encryption=AES-Twofish-Serpent --hash=SHA-512 --random-source=/dev/urandom --keyfiles=${_keyfile} --password='' --create /dev/disk/by-id/${_diskid}
log_daemon_msg "Finished encrypting the disk with uuid=${_diskid} (${_disk}) with the keyfile=${_keyfile}" "tc"
}

mount_truecrypt_disk() {
local _device=$1
local _slot=$2
local _diskid=
local _keyfile=

log_daemon_msg "Mounting device=${_device} to slot=${_slot}" "tc"
echo

get_disk_uuid ${_device} _diskid
_keyfile=/etc/`hostname`-${_diskid}.key

truecrypt --filesystem=none --password='' --keyfiles=${_keyfile} --slot=${_slot} --protect-hidden=no --mount /dev/disk/by-id/${_diskid}
log_end_msg $?
}

parse_config_line() {
local _in_line=$1
local _device=
local _slot=
local _mount_indicator=
local _key_files=

_device=$(echo ${_in_line} | cut -f1 -d ' ')
_slot=$(echo ${_in_line} | cut -f2 -d ' ')
_mount_indicator=$(echo ${_in_line} | cut -f3 -d ' ')
_device=$(echo ${_in_line} | cut -f1 -d ' ')
_slot=$(echo ${_in_line} | cut -f2 -d ' ')
_mount_indicator=$(echo ${_in_line} | cut -f3 -d ' ')
if [ ${_mount_indicator} == "Y" ]; then
mount_truecrypt_disk ${_device} ${_slot}
fi
}

mount_disks() {
while read line; do
[[ ${line:0:1} == "#" || ${line:0:1} == "" ]] && continue
parse_config_line "$line"
done < "$CONFIG"
}

unmount_disks() {
while read line; do
[[ ${line:0:1} == "#" || ${line:0:1} == "" ]] && continue
_device=$(echo ${line} | cut -f1 -d ' ')
_mount_indicator=$(echo ${line} | cut -f3 -d ' ')
if [ ${_mount_indicator} == "Y" ]; then
truecrypt --dismount /dev/disk/by-id/_device
fi
done < "$CONFIG"
truecrypt --dismount $TC_DEVICE_1
}

case "$1" in
create_encrypted_disk) log_daemon_msg "Creating TC-encrypted disk" "tc"
echo
create_encrypted_disk $2
;;

start) log_daemon_msg "Mounting disk volumes" "tc"
echo
mount_disks
log_end_msg $?
;;
stop) log_daemon_msg "Umounting disk volumes" "tc"
echo
unmount_disks
log_end_msg $?
;;
*) log_action_msg "Usage: /etc/init.d/tc.sh {start|stop}"
log_action_msg "To encrypt a disk, use: /etc/init.d/tc.sh create_encrypted_disk sdX"
exit 2
;;
esac
exit 0

A sample configuration file:

# Truecrypt configuration file
# The format is:
# Device Slot Mount
sda 1 Y
sdb 2 Y
sdc 3 Y
sdd 4 Y

Create encrypted file container using truecrypt (Ubuntu)

1. Create the key:

truecrypt --create-keyfile /etc/tc.key \
--hash=Whirlpool \
--random-source=/dev/urandom

2. Change permissions on the key:

chown 600 /etc/tc.key

3. Create the encrypted file container

  • save the truecrypt file in /root/tc.volume
  • encrypt with triple encryption algorithm AES-Twofish-Serpent (slower than just AES but arguably more secure, since the data is encrypted three times by a cascading algorithm, with three different keys: first with AES, then by Twofish, and then by Serpent)
  • use Whirlpool hash
  • format filesystem to ext4
  • do not use the password
  • use the generated key file /etc/tc.key
  • volume is 1G = 1073741824 bytes
truecrypt -c /root/tc.volume \
--volume-type="normal" \
--encryption="AES-Twofish-Serpent" \
--hash=Whirlpool \
--filesystem=ext4 \
-p "" \
--keyfiles=/etc/tc.key \
--size=1073741824 \
--random-source=/dev/urandom

4. Create a mountpoint:

mkdir -p /u

5. Mount the encrypted file container:

truecrypt /root/tc.volume /u --keyfiles=/etc/tc.key

6. Verify that the encrypted volume is mounted:

truecrypt --list

This should produce the output similar to the below:

1: /root/tc.volume /dev/mapper/truecrypt1 /u

Encrypt disk using truecrypt

1. Create the key file to be used for encrypting the disk:

truecrypt --create-keyfile \
--random-source=/dev/urandom \
/etc/tc-keyfile

2. Change permissions on the key file:

chmod 600 /etc/tc-keyfile

3. Encrypt the disk with AES/SHA-512 encryption scheme (this may take a long time (hours) for larger disks, especially if chain encryption schemes are used, e.g. AES-Twofish-Serpent):

truecrypt --filesystem=none \
--volume-type=normal \
--encryption=AES \
--hash=SHA-512 \
--random-source=/dev/urandom \
--keyfiles=/etc/tc-keyfile \
--password="" \
--create /dev/disk/by-id/[YOUR_DISK_ID_HERE]

4. Mount the encrypted disk: no defined filesystem, no password, a pre-created key file, slot=2 (maps the disk to /dev/mapper/truecrypt2),

truecrypt \
--mount \
--filesystem=none \
--password="" \
--keyfiles=/etc/tc-keyfile \
--protect-hidden=no \
--slot=2 \
/dev/disk/by-id/[YOUR_DISK_ID_HERE]

5. List encrypted disks

truecrypt --list

This should produce the output similar to the below:

2: /dev/disk/by-id/ABC /dev/mapper/truecrypt2 -

Mount truecrypt-encrypted disks at startup (Ubuntu)

Prerequisites:

1. Truecrypt is installed on the target machine. See http://www.truecrypt.org
2. An encrypted disk was created using truecrypt. See encrypting a disk using truecrypt.
3. Commands are run under the root shell (sudo -s).

Steps:

1. Create the following script, save it to /etc/init.d/tc.sh, and make it executable (chmod +x /etc/init.d/tc.sh). The script assumes the following:

  • the encrypted disk device is /dev/sdX (replace with your own); it is probably better to use /dev/disk/by-id links, as they will work better if the BIOS disk order changes at some point, e.g. when a new hard drive is added to the system
  • the disk is to be mounted into slot number 1 (and therefore will be exposed to the OS by /dev/mapper/truecrypt1)
  • the disk was is not formatted for a particular filesystem (it is useful when you would like to use some “exotic” file system which truecrypt does not natively support, e.g. ZFS
  • the disk is secured with the keyfile(s) rather than passwords
#!/bin/sh
# Mount and unmount encrypted disks and partitions.
#
### BEGIN INIT INFO
# Provides: tc
# Required-Start: $remote_fs $syslog $time
# Required-Stop: $remote_fs $syslog $time
# Default-Start: 2 3 4 5
# Default-Stop: 1
# Short-Description: Encrypted disk volume support
# Description: tc provides support for mounting
# encrypted disks and disk volumes
### END INIT INFO

TC_DEVICE="/dev/sdX"
TC_SLOT_NUMBER=1

test -f /usr/bin/truecrypt || exit 0
. /lib/lsb/init-functions

case "$1" in
start) log_daemon_msg "Mounting disk volumes" "tc"
echo
truecrypt \
--filesystem=none \
--password="" \
--keyfiles=/etc/tc.key \
--slot=$TC_SLOT_NUMBER \
--protect-hidden=no \
--mount $TC_DEVICE
log_end_msg $?
;;
stop) log_daemon_msg "Umounting disk volumes" "tc"
echo
truecrypt --dismount $TC_DEVICE
log_end_msg $?
;;
*) log_action_msg "Usage: /etc/init.d/tc.sh {start|stop}"
exit 2
;;
esac
exit 0

2.  Install the startup script using the update-rc.d command. The command below adds tc to be started at runlevels 2, 3, 4, 5 and stopped at runlevels 1 and 6. When starting, the priority 10 ensures that the encrypted disk is mounted before other startup services are run (such as ZFS mounts). When stopping at runlevels 1 and 6, the priority 90 ensures that the encrypted disk is dismounted after all other filesystems are dismounted.

cd /etc/init.d
update-rc.d tc defaults 10 90

3. Test the script

service tc start

This should mount the encrypted disk and make it available under /dev/mapper/truecrypt1. Verify by running the command:

truecrypt --list

This should produce the output similar to the below:

1: /dev/sdX /dev/mapper/truecrypt1 -

Test the script/service by rebooting the machine and ensuring that the encrypted disks survive the hard reboot.