#!/bin/sh
#
# Tool to automaticaly create an encrypted image that can be burned to a CD or DVD
#
# Author: Matthias Jansen <mail at matthiasjansen dot de>
#
# Version 0.2 / 2006-07-06
#
#
# Requirements:
# - uuencode
# - gpg
# - mkisofs
# - aespipe
# 
# for CD-burning: cdrecord
# for DVD-burning: growisofs
#
# Changelog:
# 
# 2005-12-06:
#       - first release (0.1)
#
# 2006-07-06
#	- updated usage output
#	- fixed wrong error message (s/mkisofs/aespipe/)


# ---- functions -----

function usage {
	echo
	echo "This script creates an encrpyted CD/DVD using aespipe with a GPG file containing the key"
	echo
	echo "Usage: create_enc_image <options>"
	echo
	echo " -i | --iso <file>		The .iso file to be generated (*)"
	echo
	echo " -s | --source-dir <dir>	The source dir which contains the files to be burned (*)"
	echo
	echo " -d | --burn-dvd <device>	The dvd-burner device (e.g. /dev/dvdrw)"
	echo "				can't be combined with --burn-cd"
	echo
	echo " -c | --burn-cd <device>	The cd-burner device (e.g. /dev/cdrw)"
	echo "				can't be combined with --burn-dvd"
	echo
	echo " -k | --key-file <file>		The gpg-keyfile to be used - otherwise a new GPG file will be created temporarly"
	echo
	echo " -h | --help			Show this message"
	echo
	echo " -f | --force			Force overwriting the iso"
	echo
	echo " -fs | --follow-symlinks	follow symbolic links"
	echo
	echo " -m | --multi-key		Use 64 keys instead of one (only if not -k)"
	echo "				this is NOT supported by the normal kernel crypto-loop-device!"
	echo "				you need to install loop-aes from http://loop-aes.sourceforge.net"	
	echo
	echo " (*)				these options are needed!"
	echo
}

function create_image_start {
	yes "" | dd of="$ISO" bs=512 count=16
}

function create_iso_random_key {
	if [ $MULTI -eq 1 ]; then
		# multikey is not provided by the kernel crypto-loop-device
		head -c 2925 /dev/urandom | uuencode -m - | head -n 66 | tail -n 65 | gpg --symmetric -a | dd of="$ISO" conv=notrunc 
	else
		head -c 2925 /dev/urandom | uuencode -m - | head -n 66 | tail -n 1 | gpg --symmetric -a | dd of="$ISO" conv=notrunc 
	fi
}

function create_iso_key_from_file {
	dd if="$KEY" of="$ISO" conv=notrunc
}

function create_real_image {
	OLD_DIR=`pwd`
	cd "$SOURCEDIR"

	if [ $F_SYM -eq 1 ]; then
		F_SYM="-f"
	else
		F_SYM=""
	fi

	mkisofs $F_SYM -allow-multidot -iso-level 3 -l -r . | aespipe -e aes256 -w 5 -K "$ISO" -O 16 >> "$ISO"

	cd "$OLD_DIR"
}

function burn_dvd {
	growisofs -dvd-compat -Z $BURNDEVICE="$ISO"
}

function burn_cd {
	cdrecord dev=$BURNDEVICE -dao "$ISO"
}



# ------------------------ MAIN ---------------------

# define the global parameters
ISO=""
SOURCEDIR=""
BURN=""
BURNDEVICE=""
KEY=""
FORCE=0
F_SYM=0
MULTI=0

# check if all needed tools are installed

if ! which uuencode > /dev/null 2>&1; then
	echo
	echo " ERROR: Can't find uuencode in the PATH! (On Gentoo lease emerge app-arch/sharutils)"
	echo
	exit 7
fi

if ! which gpg > /dev/null 2>&1; then
	echo
	echo " ERROR: Can't find gpg in the PATH! (On Gentoo please emerge app-crypt/gnupg)"
	echo
	exit 7
fi

if ! which mkisofs > /dev/null 2>&1; then
	echo
	echo " ERROR: Can't find mkisofs in the PATH! (On Gentoo please emerge app-cdr/cdrtools)"
	echo
	exit 7
fi

if ! which aespipe > /dev/null 2>&1; then
	echo
	echo " ERROR: Can't find aespipe in the PATH! (On Gentoo please emerge app-crypt/aespipe)"
	echo
	exit 7
fi


# check for minimal number of arguments

if [ $# -lt 4 ]; then
	usage
	exit 1
fi

# getting the parameter

while [ "$1" != "" ]; do
	case $1 in
		-i | --iso )
				shift
				ISO=$1
				;;
		-s | --source-dir )	
				shift
				SOURCEDIR=$1
				;;
		-d | --burn-dvd )
				shift
				BURNDEVICE=$1
				BURN=DVD
				;;
		-c | --burn-cd )
				shift
				BURNDEVICE=$1
				BURN=CD
				;;
		-k | --gpg-key )
				shift
				KEY=$1
				;;
		-h | --help )           
				usage
				exit
				;;
		-f | --force )
				FORCE=1
				;;
		-fs | --follow-symlinks )
				F_SYM=1
				;;
		-m | --multi-key )
				MULTI=1
				;;
        	* )                     
				usage
				exit 1
	esac
	shift
done

# Checking the input

T_EXISTS=0

if [ "$SOURCEDIR" == "" ]; then
	usage
	echo " ERROR: You need to specify a source directory (-s <dir>)"
	echo
	exit 2
elif [ ! -d "$SOURCEDIR" ]; then
	echo
	echo " ERROR: \"$SOURCEDIR\" is not a valid source directory!"
	echo
	exit 2
fi

if [ "$ISO" == "" ]; then
	usage
	echo " ERROR: You need to specify a target file (-i <file>)"
	echo
	exit 3
elif [ -e "$ISO" ]; then
	T_EXISTS=1
	if [ $FORCE -eq 0 ]; then
		echo
		echo " ERROR: \"$ISO\" already exists! Use -f to overwrite"
		echo
		exit 3
	fi
fi

if ! touch "$ISO" > /dev/null 2>&1; then
	echo
	echo " ERROR: Could not write target file ($ISO)!"
	echo
	exit 3
fi

# remove the touched file because there may be other errors!
# but only if it hasn't been there before
if [ $T_EXISTS -eq 0 ]; then
	rm "$ISO"
fi

if [ ! "$BURNDEVICE" == "" -a ! -b "$BURNDEVICE" ]; then
	echo
	echo " ERROR: \"$BURNDEVICE\" is not a device!"
	echo
	exit 4
fi

if ([ "$BURN" == "DVD" ] && ! which growisofs > /dev/null 2>&1); then
	echo
	echo " ERROR: Could not find growisofs in the current PATH. Needed for burning DVDs. Please emerge app-cdr/dvd+rw-tools"
	echo
	exit 5
fi

if [ "$BURN" == "CD" ] && ! which cdrecord > /dev/null 2>&1; then
	echo
	echo " ERROR: Could not find cdrecord in the current PATH. Needed for burning CDs. Please emerge app-cdr/cdrtools"
	echo
	exit 5
fi

if [ ! "$KEY" == "" -a ! -e "$KEY" ]; then
	echo
	echo " ERROR: GPG Keyfile \"$KEY\" does not exist!"
	echo
	exit 6
fi

echo " Creating the first 8k of the image..."

create_image_start

if [ ! "$KEY" == "" ]; then
	echo " Appending the key-file: $KEY..."
	create_iso_key_from_file
else
	echo " Creating the random key. Please enter a SAVE keyword when prompted..."
	create_iso_random_key
fi

echo " Creating the encrypted data now. Please enter the keyword when prompted..."
create_real_image

if [ "$BURN" == "CD" ]; then
	echo " Burning the image to CD now..."
	burn_cd
elif [ "$BURN" == "DVD" ]; then
	echo " Burning the image to DVD now..."
	burn_dvd
fi

echo 
echo " Done."
echo " You should REALLY check the image/CD/DVD before going on!"
echo
if [ ! "$BURN" == "" ]; then
	echo " To mount the $BURN run:"
	echo " mount -t iso9660 $BURNDEVICE /mnt/crypted -o loop=/dev/loop0,encryption=AES256,gpgkey=$BURNDEVICE,offset=8192"
else
	echo " To mount the image run:"
	echo " mount -t iso9660 $ISO /mnt/crypted -o loop=/dev/loop0,encryption=AES256,gpgkey=$ISO,offset=8192"
fi
