3 # Purpose: Program to format, mount and unmount encrypted devices/files
4 # Authors: Michael Gebetsroither <gebi@grml.org>
5 # Bug-Reports: see http://grml.org/bugs/
6 # License: This file is licensed under the GPL v2.
7 # Latest change: Don Jul 26 19:57:28 CEST 2007 [mika]
8 ################################################################################
15 #. /etc/grml/sysexits-sh
24 DEV_MAPPER_="/dev/mapper"
25 CRYPTSETUP_="cryptsetup"
36 DM_PREFIX_="grml-crypt_"
40 ENTROPY_SOURCE_='/dev/urandom'
41 OPTIMIZED_MODE_SET_='false'
44 CIPHER_="aes-cbc-essiv:sha256"
45 ITERATION_TIME_="1000"
46 ADDITIONAL_CRYPTSETUP_ARGS_=""
48 ADDITIONAL_MOUNT_ARGS_=""
49 BATCH_MODE_="--batch-mode"
59 Usage: "$PROG_NAME__" [OPTIONS] action <device/file> [mountpoint]
61 $PROG_NAME__ is a wrapper around cryptsetup with LUKS support to format a device
64 -s size of the loop-filesystem to create, in MB (default=$SIZE_)
65 -t type of filesystem (default=$FSTYPE_)
66 -r read only mode (fully supported only by start)
67 -z insecure mode, using /dev/zero for most of the initialisation (INSECURE!)
68 -o optimised initialisation mode (should be as secure as the default but faster)
69 -y verifies the passphrase by asking for it twice
70 -f force file overwriting in format mode and/or disable confirmation dialog
71 -F only for action start: run fsck before mounting the filesystem.
72 Use fsck's -f option if given twice.
73 -X Read next argument as a list of options to pass to fsck:
74 'grml-crypt -FF -X "-y -T" start /dev/ice' will run fsck with options -y and -T.
75 -m additional arguments to mount
76 -v verbose (show what is going on, v++)
79 CRYPTSETUP FORMAT OPTIONS:
80 -S cipher size, could be 128, 192 or 256 (default=$CIPHER_SIZE_)
81 -C cipher, should be aes-plain for pre-2.6.10 (default=$CIPHER_)
82 -I iteration time spend with PBKDF2 password processing in seconds (default=$ITERATION_TIME_)
83 -A additional arguments for cryptsetup (only supportet by format)
86 format <device/file> [mountpoint]
87 Format a device or a file (is created with the given size if it
88 does not exist) with the given filesystem and mount it, if a
90 start <device/file> [mountpoint]
91 Mount the device/file in the mountpoint or to a default mountpoint.
93 Umount the given mountpoint (umount, luksClose, losetup -d)
99 losetup does _NOT_ work on unionfs => grml-crypt with a filesystem image does ONLY
100 work if the image is on a tmpfs (eg. in /home/grml or /tmp).
111 # first trying normal devicename
112 tmp_="${DM_PREFIX_}${device_}"
113 if [ ! -e "$tmp_" ]; then
118 # second trying uuid of luks
119 #uuid_=`execute "$CRYPTSETUP_ luksUUID $1"`
120 #if [[ $? == 0 ]]; then
121 # echo "$prefix_$uuid_"
124 warn "could not create device-mapper name for $1"
129 function formatDevice
131 type_="$1" # could be donothing or init
133 local ddcmd_="dd if=/dev/zero of=$DM_PATH_ bs=1M &>/dev/null"
134 if [[ -x "$PV_" && $verbose_ -ge 3 ]] ; then
135 ddcmd_="dd if=/dev/zero bs=1M 2>/dev/null | $PV_ | dd of=$DM_PATH_ bs=1M &>/dev/null"
138 args_="$VERIFY_PW_ $BATCH_MODE_ --key-size $CIPHER_SIZE_ --cipher $CIPHER_ --iter-time $ITERATION_TIME_ $ADDITIONAL_CRYPTSETUP_ARGS_"
139 #args_=`echo "$args_" |tr -s ' '`
140 execute "$CRYPTSETUP_ $args_ luksFormat $TARGET_" warn || return 1
142 execute "$CRYPTSETUP_ luksOpen $TARGET_ $DM_NAME_" warn \
143 "could not open $DM_PATH_ to create a filesystem on it!" || return 1
144 if [[ $type_ == 'init' && $OPTIMIZED_MODE_SET_ == 'true' ]]; then
145 echo "finishing optimised initialisation (this could take some time)"
147 execute "$ddcmd_" # || \
148 # warn "could not finish optimised initialisation properly"
150 # cutted out because of no space left on device error :(
151 #if [[ $ret_ != 0 ]]; then
152 # execute "$CRYPTSETUP_ luksClose $DM_NAME_" warn
157 execute "$MKFS_ $DM_PATH_ >/dev/null" warn
158 if [[ $? != 0 ]]; then
159 execute "$CRYPTSETUP_ luksClose $DM_NAME_"
160 warn "could not create filesystem on $DM_PATH_" 1
163 echo "Successully created $FSTYPE_ on encrypted $TARGET_"
173 if [[ "$MOUNT_POINT_" == "" ]]; then
174 MOUNT_POINT_="/mnt/$DM_NAME_"
176 # error out if mountpoint was given but doesn't exist
177 if [ ! -d "$MOUNT_POINT_" ]; then
178 die "mountpoint $MOUNT_POINT_ does not exist"
181 # removed due to unionfs problem isLuks does not work with filesystem images
183 #$CRYPTSETUP_ isLuks $TARGET_ || die "$TARGET_ is not a luks partition"
185 # TARGET (is/should be) a filesystem image
186 if [ ! -b "$TARGET_" ]; then
187 notice "Operating on a file"
188 isExistent "$TARGET_" die "image does not exist"
189 TARGET_=`findNextFreeLoop` || die "could not find a free loop device"
191 # TARGET_ is now /dev/loop<x>
192 execute "losetup $TARGET_ $ORIG_TARGET_" die
195 $READONLY_SET_ && cargs_='--readonly'
196 execute "$CRYPTSETUP_ $cargs_ luksOpen $TARGET_ $DM_NAME_" warn || execute "losetup -d $TARGET_" || \
197 die "could not luksOpen $TARGET_"
198 if [[ "$FSCK_" == "true" ]] ; then
199 execute "fsck $FSCK_EXTRA_OPTS_ -C $DM_PATH_" || die "fsck failed on $DM_PATH_"
200 elif [[ "$FSCK_" == "trueforce" ]] ; then
201 execute "fsck -f $FSCK_EXTRA_OPTS_ -C $DM_PATH_" || die "fsck failed on $DM_PATH_"
204 $READONLY_SET_ && margs_='-r'
205 # mountpoint was not given so we use the default one which we need to create first
206 if [ ! -d "$MOUNT_POINT_" ]; then
207 execute "mkdir -p '$MOUNT_POINT_'" || die "failed to create mountpoint $MOUNT_POINT_"
210 execute "mount $margs_ $ADDITIONAL_MOUNT_ARGS_ $DM_PATH_ $MOUNT_POINT_" die
219 isExistent "$mp_" die
220 tmp_=`realpath $mp_` || die "could not get realpath of $mp_"
221 dprint "realpath_=\"$tmp_\""
223 dm_path_=`mount |grep "$tmp_ "` || die "$tmp_ is not mounted"
224 dprint "dm_path_=\"$dm_path_\""
225 dm_path_=`echo $dm_path_ |awk '{print $1}'` || die "could not get devicemapper name for $tmp_"
226 dprint "dm_path_=\"$dm_path_\""
230 for dmapper in /dev/mapper/grml-crypt* ; do
231 link=$(readlink -f "$dmapper")
232 dprint "looping device mapper devices, dmapper=$dmapper => link=$link"
233 if [ "$link" = "$dm_path_" ] ; then
234 tmp_dm_path_="$dmapper"
238 if [ -n "$tmp_dm_path_" ] ; then
239 dm_path_="$tmp_dm_path_"
243 dm_name_="${dm_path_##*/}"
244 dprint "dm_name_=\"$dm_name_\""
246 dmsetup info $dm_name_ >/dev/null ||die "$dm_name_ is not active"
247 device_=`$CRYPTSETUP_ status $dm_name_ |awk '/device:/{print $2}'` || \
248 die "could not get underlying device of $dm_path_"
249 dprint "device_=\"$device_\""
251 execute "umount $dm_path_" die "could not unmount $device_"
252 if [[ "$MOUNT_POINT_" == "/mnt/$dm_name_" ]]; then
253 rmdir "$MOUNT_POINT_"
255 execute "$CRYPTSETUP_ luksClose $dm_name_" die "could not close $dm_path_"
256 echo "$device_" |grep loop &>/dev/null && execute "losetup -d $device_" \
257 die "could not delete loop device $device_" || \
258 execute "losetup -d $device_ &>/dev/null" eprint "could not delete loop device $device_, \
259 this device possibly is not a loop device => maybe bogus error"
260 notice "$mp_ successfully unmountet/closed/deleted"
270 echo -n " (type uppercase yes): " >&2
272 if [[ $input == 'YES' ]]; then
279 function actionFormat
286 if (( $SIZE_ < 3 )); then
287 die "the minimum size of an encrypted luks partition should be 2"
290 # TARGET (is/should be) a filesystem image
291 if [ ! -b "$TARGET_" ]; then
292 notice "Operating on a file"
294 if [ -e "$TARGET_" ]; then
295 $FORCE_ || die "$TARGET_ does already exist"
296 warn "overwriting file $TARGET_"
299 echo -n "Initialising file with "
300 if [[ $OPTIMIZED_MODE_SET_ == 'true' ]]; then
301 echo "optimised SECURE mode"
302 execute "dd if=/dev/zero of=$TARGET_ bs=1M count=${SIZE_} &>/dev/null" \
303 die "could not initialise $TARGET_ with /dev/zero"
305 if [[ $ENTROPY_SOURCE_ == '/dev/zero' ]]; then
306 echo "INSERCURE mode"
308 echo "SECURE mode (taking /dev/urandom as source, this could take some time)"
310 execute "dd if=$ENTROPY_SOURCE_ of=$TARGET_ bs=1M count=${SIZE_} &>/dev/null" ||\
311 die "could not initialise $TARGET_ with $ENTROPY_SOURCE_"
315 TARGET_=`findNextFreeLoop` || die "could not find a free loop device"
317 # TARGET_ is now /dev/loop<x>
318 execute "losetup $TARGET_ $ORIG_TARGET_" die
319 if [[ $OPTIMIZED_MODE_SET_ == 'true' || $ENTROPY_SOURCE_ == '/dev/zero' ]]; then
320 execute "dd if=/dev/urandom of=$TARGET_ bs=1M count=2 &>/dev/null" \
321 die "could not initialise the fist 2MB of $TARGET_ with /dev/urandom"
323 formatDevice "$init_"
326 $FORCE_ || (yesDialog "Are you shure you want to overwrite $TARGET_ ?" || die 'You are not sure')
327 notice 'Operating on a device'
328 echo -n 'Initialising device with '
329 if [[ $OPTIMIZED_MODE_SET_ == 'true' ]]; then
330 echo "optimised SECURE mode"
331 execute "dd if=/dev/urandom of=$TARGET_ bs=1M count=2 &>/dev/null" ||\
332 die "could not initialise the first 2MB of $TARGET_ with /dev/urandom"
333 elif [[ $ENTROPY_SOURCE_ != '/dev/zero' ]]; then
335 echo "SECURE mode (taking $ENTROPY_SOURCE_ as source, this could take some time)"
336 ddcmd_="dd if=$ENTROPY_SOURCE_ of=$TARGET_ bs=1M &>/dev/null"
337 if [[ -x "$PV_" && $verbose_ -ge 3 ]] ; then
338 ddcmd_="dd if=$ENTROPY_SOURCE_ bs=1M 2>/dev/null | $PV_ | dd of=$TARGET_ bs=1M &>/dev/null"
340 execute "$ddcmd_" # ||\
341 # skipped because "no space left on device" from dd
342 # die "could not initialise $TARGET_ with $ENTROPY_SOURCE_"
344 echo 'INSECURE mode (only initialising the fist 2MB with /dev/urandom)'
345 execute "dd if=/dev/urandom of=$TARGET_ bs=1M count=2 &>/dev/null" \
346 die "could not initialise the first 2MB of $TARGET_ with /dev/urandom"
349 formatDevice "$init_"
353 # formatDevice was successfully
354 if (( $ret_ == 0 )); then
355 # a mountpoint was given (don't luksClose the device)
356 local mount_point_exists_='true'
357 test -d "$MOUNT_POINT_" || mount_point_exists_='false'
359 if [[ $MOUNT_POINT_ != "" && "$mount_point_exists_" == 'true' ]]; then
360 $READONLY_SET_ && margs_='-r'
361 execute "mount $margs_ $ADDITIONAL_MOUNT_ARGS_ $DM_PATH_ $MOUNT_POINT_" die
363 if [[ $MOUNT_POINT_ != "" ]]; then
364 $mount_point_exists_ || warn "mountpoint $MOUNT_POINT_ does not exist, not mounting. please use \"grml-crypt start $ORIG_TARGET_ <mountpoint>\" to start the device"
366 execute "$CRYPTSETUP_ luksClose $DM_NAME_" warn
367 $IS_IMAGE_ && execute "losetup -d $TARGET_" warn
370 execute "$CRYPTSETUP_ luksClose $DM_NAME_" warn
371 $IS_IMAGE_ && execute "losetup -d $TARGET_" warn
381 while getopts "s:t:rzoyfFm:hvS:C:I:A:X:" opt; do
383 s) SIZE_="$OPTARG"; SIZE_SET_='true' ;;
384 t) FSTYPE_="$OPTARG" ;;
385 r) READONLY_SET_='true' ;;
386 z) let OPTIMIZING_LEVEL_=$OPTIMIZING_LEVEL_+1
387 ENTROPY_SOURCE_='/dev/zero'
388 warn 'initialising from INSECURE source /dev/zero' ;;
389 o) let OPTIMIZING_LEVEL_=$OPTIMIZING_LEVEL_+1
390 OPTIMIZED_MODE_SET_='true' ;;
391 y) VERIFY_PW_="--verify-passphrase" ;;
393 F) if [[ "$FSCK_" == "true" ]] ; then
399 X) FSCK_EXTRA_OPTS_="$OPTARG" ;;
400 m) ADDITIONAL_MOUNT_ARGS_="$OPTARG" ;;
401 h) printUsage; exit ;;
402 v) let verbose_=$verbose_+1 ;;
403 S) CIPHER_SIZE_="$OPTARG" ;;
404 C) CIPHER_="$OPTARG" ;;
405 I) ITERATION_TIME_="$OPTARG" ;;
406 A) ADDITIONAL_CRYPTSETUP_ARGS_="$OPTARG" ;;
407 ?) printUsage; exit 64 ;;
410 shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter
413 checkRoot die "You have to be root to use this program"
416 if [[ $1 == 'help' ]]; then
420 if (( $# < 2 )); then
422 die "wrong number of arguments ($#)" 1
424 if (( $OPTIMIZING_LEVEL_ > 1 )); then
426 die "please choose ONE initialisation methode"
430 MKFS_="/sbin/mkfs.$FSTYPE_"
431 if [ ! -x "$MKFS_" ]; then
432 die "invalid filesystem type \"$FSTYPE_\"" 1
435 # use batch-mode if available
436 $CRYPTSETUP_ $BATCH_MODE_ --help &>/dev/null;
439 0) dprint "your cryptsetup understands --batch-mode" ;;
440 1) BATCH_MODE_=""; notice "your cryptsetup does NOT understand --batch-mode, trying without" ;;
441 127) die "could not execute cryptsetup" 127 ;;
442 *) warn "problems executing $CRYPTSETUP_" $ret_
445 DM_NAME_="`getDMName $TARGET_`"
446 DM_PATH_="$DEV_MAPPER_/$DM_NAME_"
447 ORIG_TARGET_="$TARGET_"
451 format) ACTION_='format'; actionFormat ;;
452 start) ACTION_='start'; actionStart ;;
453 stop) ACTION_='stop'; actionStop "$TARGET_" ;;
458 ################################################################################
459 # vim:foldmethod=marker tabstop=2 expandtab shiftwidth=2