Search:  
Gentoo Wiki

HOWTO_Burn_Encrypted_Optical_Media_With_Luks


This article is part of the HOWTO series.
Installation Kernel & Hardware Networks Portage Software System X Server Gaming Non-x86 Emulators Misc

Contents

Introduction

The purpose of this HOWTO is to learn how to burn encrypted optical media disc using Device Mapper and Cryptsetup-Luks.

Why Luks?

more information about Luks can be found here..

Alternatives

Visit HOWTO Burn Encrypted DVDs, just remember that using the Crypto-Loop method is not safe for journaling file systems like ext3/reiserfs.

Minimum Requirements

You can use zgrep <CONFIG> /proc/config.gz or grep <CONFIG> /usr/src/linux-$(uname -r)/.config to check whether your kernel meets the requirements. Look for the following options.

You can see the available ciphers by doing cat /proc/crypto.

Require Kernel Modules

Linux Kernel Configuration: Required

Each and all kernel options do not need to be build-in and can be setup as modules to avoid a reboot.

Device Drivers  --->
        Multi-device support (RAID and LVM)  --->
               <*>   Device mapper support
               <*>     Crypt target support

Don't forget to include support for the ciphers you want to use.

Cryptographic options  ---> 
        <M>   SHA256 digest algorithm
        <M>   AES cipher algorithms (x86_64)

Installing Needed Packages

emerge cryptsetup-luks device-mapper

Loading necessary modules

The modules you need to load depend on the ciphers you plan to use. Please see this subsection for some information about different available ciphers, and of course edit the commands accordingly.

Code: Loading modules
modprobe dm-crypt     # required
modprobe dm-mod       # required
modprobe aes_x86_64   # for amd64 users only, otherwise use aes
modprobe sha256 
modprobe blowfish     # we use this to encrypt our swap file
Tip! Loading the modules, Bash one-liner

for i in dm-crypt dm-mod serpent sha256 blowfish;do modprobe $i;done

Tip! cat /proc/crypto will show you the loaded modules.</tt>

Encrypting swap to be safer.

First you will encrypt swap. This is important because you don't want the encryption keys swapped to an unencrypted disk. (Optional)

Code: Encrypting swap for installation (not for suspend2 users)
 cryptsetup -c blowfish -h sha256 -d /dev/urandom create swap /dev/sdaX # X being your swap partition
 mkswap /dev/mapper/swap
 swapon /dev/mapper/swap
 

Start

Now let's begin with the encryption :)

Creating container

Code: Create an empty container large enough for the iso image
dd if=/dev/urandom of=cryptocd.iso bs=512 count=2048
dd if=/dev/urandom of=cryptocd.iso bs=512 count=1 seek=1M
 

Loop Device

Code: check for a free loop device for our image file:
losetup -f
 

Create a blockdevice from image file

losetup /dev/loop0 cryptocd.iso

Format loop device using luks

cryptsetup luksFormat /dev/loop0

Remember this password or you'll be SOL.

Create Luks Mapping

cryptsetup luksOpen /dev/loop0 cryptocd

Create ISO

Now create your iso file system using mkisofs and write it to the mapped device change -lots-of-options to something compatible. for example i use. -allow-leading-dots -joliet-long -iso-level 3 -l -J -r -V volume_ID for CD/DVD data files. -udf -v for Dual Layer Media & -dvd-video for DVD movies

Code: Create ISO

genisoimage -lots-of-options /my/data/ -o burnme.iso

Tip! (The number dd reports is important for further calculations!)

Copy ISO Image into device mapper

Code: Now we will pipe the burnme.iso image into the luks device mapper.
 
dd if=burnme.iso of=/dev/mapper/cryptocd bs=512 2>&1 | grep "records out" | cut -f1 -d+
  

Calculate Overhead

Code: Now calculate the overhead of the luks container.
 
blockdev --getsize /dev/loop0
blockdev --getsize /dev/mapper/cryptocd
  
Tip! Now add the size dd reported and you know where to truncate (used as $SIZE later)

Remove Mapping

For safety reasons, remove mapping and loopdevice. cryptsetup luksClose cryptocd ; losetup -d /dev/loop0

Replacing size of overhead

Code: replace $SIZE with sum of size dd reported and the luks overhead.
 
dd if=cryptocd.iso of=cryptocd.iso bs=512 count=0 skip=$SIZE seek=$SIZE
  

Test Encrypted Image

Code: Mount the loop image and open it with luks
 
losetup /dev/loop0 cryptocd.iso
cryptsetup luksOpen /dev/loop0 cryptocd
  

Finished

Now unmap again then burn the image with cdrecord or any other tool which you burn your isos with.

WARNING: Do not burn a CD in Track At Once mode (TAO) - this will destroy at minimum the last 2 sectors (q.v.: Burning encrypted ISO image to CD / readahead bug)!

Automation

I wrote a couple scripts to automate this process, read it before using it and modify it to your needs.


File: cryptocd
#!/bin/bash -x

#  CryptoCD - Optical Media Backup 0.3 - burn encrypted backup CD/DVDs
#  Created: Mon Oct 01 4:20:00 2007
#  Copyright  2007  Tim Niemueller [www.niemueller.de]
#  Based on work copyright by Gentoo Wiki User likewhoa
#  Revised by likewhoa on 20071001 4:20:00

#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU Library General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software Foundation,
#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.

#  C h a n g e L o g
#  2007-09-12   tim     0.1     initial revision for publication
#  2007-09-17   tim     0.2     added -G, added -f, fixed mkisofs param and copy iso bug
#  2007-10-01   likewhoa 0.3    
#	1. Code cleanup
#	2. Max data limits updated
#	3. Dependency checks
#	4. Minor code additions
#  2007-10-11   likewhoa 0.3-r1 - fixed free loop device line
#  2007-10-15   likewhoa 0.3-r2 - added flags for burn speed and fixed minor code bugs.
#  2007-10-19   likewhoa 0.3-r5 - minor tweaks and code adjustments.
# End C h a n g e L o g

export LANG=C

if [ $(whoami) != root ]; then echo "this script must be run as root."; exit 1; fi

# check dependencies.

for i in wodim genisoimage; do                                                                                                                                                         
if ! which $i &>/dev/null; then
        echo "ERROR: $i must be in your $PATH path!"                                                                                                                                                  $
        exit 1
        fi
done

declare -a SRCDIRA
declare -i SRCDIRI SRCDIRNUM
SRCDIRS=/mnt/crypto
SRCDIRI=0
VOLUMEID=${VOLUMEID:-420}
PRODUCER=${PRODUCER:-likewhoa}
GRAFTPOINTS=
DUALLAYER=0
GRAFTPOINTING=0
SHORT_GRAFTPOINTING=0
KEEPISO=0
SHOWUSAGE=0
CUSTOMISO=
FORCE=0
while getopts "V:P:d:DgGkhis:f" options; do
        case $options in
                V) VOLUMEID=$OPTARG;;
                P) PRODUCER=$OPTARG;;
                d) SRCDIRA[$SRCDIRI]="$OPTARG"; SRCDIRI+=1;;
                D) DUALLAYER=1;;
                g) GRAFTPOINTING=1;;
                G) GRAFTPOINTING=1; SHORT_GRAFTPOINTING=1;;
                k) KEEPISO=1;;
                h) SHOWUSAGE=1;;
                i) CUSTOMISO=$OPTARG;;
		s) BURNSPEED="$OPTARG";;
                f) FORCE=1;;
                *) echo "Unknown option '$options'";;
        esac
done

if [ $SHOWUSAGE == 1 ]; then
cat << EOF
        	Usage: $0 [options]
        
        	Options:
		  -s 16		   This tells $0 to burn at 16x speed. (Default 8)
        	  -i img.iso       Use given existing ISO image and put it into an
                  		   encrypted container. -d/-V/-P/-g are ignored.
        	  -V volid         ISO volume ID
        	  -P publisher     ISO publisher
        	  -d dir           Directory to backup, may be used multiple times
        	                   if not given, current directory is backed up.
         	  -D               Use dual layer DVD (used for size check)
        	  -g               Use graft-pointing (see man genisoimage)
        	  -G               Use short graft-points (basedir of source dir as dir on DVD)
        	  -k               Keep ISO image after burning
        	  -f               Force creation, delete crypto ISO image if it exists
        	  -h               This help message
EOF
        exit 0
fi
if [[ $SRCDIRNUM = 0 ]]; then
        SRCDIRS=$(pwd)
        SRCDIRNUM=1
        if [ $GRAFTPOINTING = 1 ]; then
                if [ $SHORT_GRAFTPOINTING = 1 ]; then
                        GRAFTPOINTS="$(echo $(basename $PWD) | sed -e 's/\\/\\\\/g' -e 's/=/\\=/g')=$PWD"
                else
                        GRAFTPOINTS="$(echo $PWD | sed -e 's/\\/\\\\/g' -e 's/=/\\=/g')=$PWD"
                fi
        fi
else
        for (( i=0; $i < ${SRCDIRNUM:-0}; i += 1 )); do
                if [[ ${SRCDIRA[$i]} =~ " " ]]; then
                        echo "Path may not contain spaces for now"
                        exit -1
                fi
                SRCDIRS="$SRCDIRS ${SRCDIRA[$i]}"
                if [ $GRAFTPOINTING = 1 ]; then
                        if [ $SHORT_GRAFTPOINTING = 1 ]; then
                                GRAFTPOINTS="$GRAFTPOINTS $(echo $(basename ${SRCDIRA[$i]}) | sed -e 's/\\/\\\\/g' -e 's/=/\\=/g')=${SRCDIRA[$i]}"
                        else
                                GRAFTPOINTS="$GRAFTPOINTS $(echo ${SRCDIRA[$i]} | sed -e 's/\\/\\\\/g' -e 's/=/\\=/g')=${SRCDIRA[$i]}"
                        fi
                fi
        done
fi

GENISOIMAGE_ARGS_DATA="-allow-leading-dots -joliet-long -iso-level 3 -l -J -R -D -v"            # Default arguments for genisoimage for data DVDs
GENISOIMAGE_ARGS_VIDEO="-dvd-video"                                                             # Default arguments for genisoimage for video DVDs
MOUNTDIR=/mnt/cdrom                                                                             # Directory to mount iso data
CDRECORDER=/dev/dvd1                                                                            # Optional path to your cdburner, set only if $BURNMEDIA equals 1
ISO=/mnt/dvdimage.iso    	                                                                # Name of the iso image (enough space needed there!)
TMPISO=/mnt/tmp.iso
CRYPT="-y -c aes-cbc-essiv:sha256 -h 256"                                                       # Encryption options for cryptsetup
MAPPER="cryptodvd"                                                                              # Name for mapped volume
LOOP=
SIZE=
SIZE_VOL1=
SIZE_LOOP=

if [ "$DUALLAYER" = "0" ]; then
        echo "Burning to regular DVD (4.7GB)"
        MAXSIZE=$(( 4700 *2 ))k                                                                 # Number of 512 blocks (can you see the k? ;-)
        b=4585590                                                                               # Safe size limit for DVDr media 4.4G 
else
        echo "Burning to dual layer DVD (8.5 GB)"
        MAXSIZE=$(( 8500 *2 ))k                                                                 # Number of 512 blocks (can you see the k? ;-)
        b=8298400                                                                               # Safe size limit for DVD-R DL media 8.5G 
	GENISOIMAGE_ARGS_DATA="${GENISOIMAGE_ARGS_DATA} -udf"					# UDF filesystem option set for DL media.
fi

if [[ "$SRCDIRNUM" == "1" && $(find $SRCDIRS -type d -name 'VIDEO_TS') ]]; then
        echo "detected dvd-video data structure"
        GENISOIMAGE=$GENISOIMAGE_ARGS_VIDEO
else
        GENISOIMAGE=$GENISOIMAGE_ARGS_DATA
fi

if [ "$PRODUCER" != "" ]; then
        GENISOIMAGE="$GENISOIMAGE -publisher \"$PRODUCER\""
fi
if [ "$VOLUMEID" != "" ]; then
        GENISOIMAGE="$GENISOIMAGE -volid \"$VOLUMEID\""
fi

if [ "$GRAFTPOINTS" != "" ]; then
        GENISOIMAGE="$GENISOIMAGE -graft-points"
else
        GRAFTPOINTS=$SRCDIRS
fi

if [ ! -d $(dirname $ISO) ]; then
        echo "Required ISO directory $(dirname $ISO) does not exist, aborting."
        exit -1
fi
if [ ! -d $(dirname $TMPISO) ]; then
        echo "Required temporary ISO directory $(dirname $TMPISO) does not exist, aborting."
        exit -1
fi

if [ -e $ISO ]; then
        if [ $FORCE == 1 ]; then
                echo "Removing old ISO image $ISO"
                rm -f $ISO
        else
                echo "ISO image $ISO does already exist, aborting"
                exit
        fi
fi

check_iso_size() {
        echo "Calculating ISO size (SRCDIRS: $SRCDIRS)"
        a=$(du -kcs $SRCDIRS | tail -n1 | awk '{ print $1 }')                                  # Size of src data directories

        if [ -a $ISO ]; then rm -fv $ISO; fi                                                    # Removing old ISO images if it exist
 
        if (( a > b )); then
                echo "maximum size limit of ${b}k for CDr Media excedded"
		exit 1
        fi
}

setup_crypto_volume() {
	# new methods doesn't work anymore :(
        # LOOP=$(losetup -f)

	for i in /dev/loop[0-7]; do
  		losetup $i >/dev/null 2>&1
  	if [ $? -eq 1 ] ; then LOOP=$i ;break ; fi
	done
 
        if [ -z "$LOOP" ]; then echo "no free loop device" >&2; exit; fi

        echo "Setting up crypto volume"
        dd if=/dev/urandom of=$ISO bs=512 count=2048
        dd if=/dev/urandom of=$ISO bs=512 count=1 seek=$MAXSIZE
        losetup $LOOP $ISO
        cryptsetup $CRYPT luksFormat $LOOP
        echo "Opening crypto volume"
        cryptsetup luksOpen  $LOOP $MAPPER
}

create_iso_image() {
        echo "Creating ISO image tmp file (may take a while)" 
        # Why eval?
        # If we pass parameters that contain spaces we want to get them interpreted as ONE parameter,
        # not as two, so we write "a b". To avoid mangling of the names (if used in $(...)) we use eval
        eval nice genisoimage $GENISOIMAGE -o $TMPISO $GRAFTPOINTS
}

copy_iso_image() {
        local COPYISO=$1
        echo "Copying ISO image $COPYISO into crypto volume"
        SIZE=$(nice dd if=$COPYISO of=/dev/mapper/$MAPPER bs=512 2>&1 | grep "records out" | cut -f1 -d+)
        SIZE_VOL1=$(blockdev --getsize /dev/mapper/$MAPPER)
        SIZE_LOOP=$(blockdev --getsize $LOOP)
}

remove_temp_iso_image() {
        echo "Removing temporary ISO image"
        rm -vf $TMPISO
        echo "SIZE=$SIZE  SIZE_VOL1=$SIZE_VOL1  SIZE_LOOP=$SIZE_LOOP"
}

close_crypto_volume() {
        echo "Closing crypto volume"
        cryptsetup luksClose $MAPPER
        losetup -d $LOOP
}
 
truncate_crypto_container() {
        SIZE=$(( $SIZE + ($SIZE_LOOP - $SIZE_VOL1) ))
        # echo "SIZE recalculated to $SIZE (SIZE=$SIZE + (SIZE_LOOP=$SIZE_LOOP - SIZE_VOL1=$SIZE_VOL1))"

        dd if=$ISO of=$ISO bs=512 count=0 skip=$SIZE seek=$SIZE
}

test_iso_image() {
        echo "Testing ISO image..."
        losetup $LOOP $ISO
        losetup $LOOP $ISO
 
        echo "Enter your luks password phrase"
        cryptsetup luksOpen $LOOP $MAPPER
 
        echo "Mounting encrypted optical media disc to $MOUNTDIR"
        if [ ! -d $MOUNTDIR ]; then
                mkdir -p $MOUNTDIR
        fi
        mount  /dev/mapper/$MAPPER $MOUNTDIR

        ls -al $ISO
        ls -al $MOUNTDIR
}

burn_abort_standby() {
cat << EOF
        	Now make sure data is good so we can continue...
        	Your options now:
        	   B  Burn    -  Burn image
        	   A  Abort   -  Abort, ISO will stay
        	   S  Standby -  Standby, will close crypto volume and
        	                 then waits for another key press, useful
        	                 for example if you want to add a key
        	                 (cryptsetup -y -i 3000 luksAddKey $LOOP)
EOF
	echo "What to do? Burn/Abort/Standby"; read c

        echo "Closing crypto volume"
        umount $MOUNTDIR 
        cryptsetup luksClose $MAPPER

        if [[ $c =~ [Ss][Tt][Aa][Nn][Dd][Bb][Yy]|[Ss] ]]; then
                echo "Waiting... enter Burn or Abort when done"
                read c
        fi

        losetup -d $LOOP

        if [[ $c =~ [Aa][Bb][Oo][Rr][Tt]|[Aa] ]]; then
		echo "Are you sure you want to abort?"; read d
			if [[ $d =~ [Yy]|[Yy][Ee][Ss] ]]; then
				echo "Aborting..."; exit 1
			fi
	fi    
  	
	if [ ! -b $CDRECORDER ]; then    
              	echo "CDr/DVDr Burner it's not a block device. exiting"
               	exit 1
        else
               	echo "Burning CryptoCD/DVD media"
		# using growisofs instead of wodim for now until upstream fixes bug.
               	#wodim -v -dao dev=$CDRECORDER speed=$BURNSPEED $ISO
		growisofs -Z ${CDRECORDER}=${ISO} -speed=${BURNSPEED:-8}
      	fi
        
	if [ $KEEPISO == 0 ]; then
                echo "Deleting ISO $ISO"
                rm -fv $ISO
        fi
}

# The real procedure...

if [ -z "$CUSTOMISO" ]; then
        check_iso_size
else
        echo "Using custom ISO image, NOT checking size"
fi
setup_crypto_volume
if [ -z "$CUSTOMISO" ]; then
        create_iso_image
fi
if [ ! -z "$CUSTOMISO" ]; then
        copy_iso_image $CUSTOMISO
else
        copy_iso_image $TMPISO
        remove_temp_iso_image
fi
close_crypto_volume
truncate_crypto_container
test_iso_image
burn_abort_standby

echo "all done. Enjoy your encrypted DVD/CD."
 

The two scripts below can be used to mount/umount your encrypted optical media.

File: cryptocd-mount
#!/bin/bash

if [ $(whoami) != root ]; then echo "this script must be run as root."; exit; fi

MOUNTDIR=/mnt/cryptocd                                          # Directory to mount iso data.
CDROM=/dev/dvd1                                                 # Optional path to your optical drive.
MAPPER="cryptocd"                                               # Name for mapped volume.
LOOP=$(losetup -f)                                              # Free loop device.

if [ -z "$LOOP" ]; then echo "no free loop device" >&2; exit; fi

[ ! -d $MOUNTDIR ] && mkdir $MOUNTDIR

losetup $LOOP $CDROM && echo $LOOP >/tmp/loop_device
cryptsetup luksOpen $LOOP $MAPPER
mount /dev/mapper/$MAPPER $MOUNTDIR
echo "all done."
 
File: cryptocd-umount
#!/bin/bash

if [ $(whoami) != root ]; then echo "this script must be run as root."; exit; fi

error() {
        echo "error occured, exiting."
        exit
}
 
MOUNTDIR=/mnt/cryptocd                                  # Directory to mount iso data
MAPPER="cryptocd"                                       # Name for mapped volume
LOOP=$(cat /tmp/loop_device)                            # Loop device from cryptocd-mount

umount $MOUNTDIR || error
cryptsetup luksClose /dev/mapper/$MAPPER
losetup -d $LOOP
echo "all done."
 

FAQ

Please see LUKSFaq as well.

Sorry but You're SOL buddy. :P

Tip! keep more than one luks password phrase just incase, this must be done before the burning process takes place. read the Luks FAQ for info on adding/deleting keyslots in luks mappings.

Ciphers

Some of the available ciphers found on the cryptographic kernel menu:


Credits

This project features code adapted and or merged from.

Change Log

TODO

--Likewhoa 12:44, 23 January 2007 (UTC)

Retrieved from "http://www.gentoo-wiki.info/HOWTO_Burn_Encrypted_Optical_Media_With_Luks"

Last modified: Thu, 04 Sep 2008 06:11:00 +0000 Hits: 11,564