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: Mon Aug 08 11:37:20 CEST 2005
8 ################################################################################
15 #. /etc/grml/sysexits-sh
24 DEV_MAPPER_="/dev/mapper"
25 CRYPTSETUP_="cryptsetup"
36 DM_PREFIX_="grml-crypt_"
38 OVERWRITE_SOURCE_DEV_='/dev/urandom'
39 OPTIMIZED_MODE_SET_='false'
42 CIPHER_="aes-cbc-essiv:sha256"
44 ADDITIONAL_CRYPTSETUP_ARGS_=""
46 ADDITIONAL_MOUNT_ARGS_=""
47 BATCH_MODE_="--batch-mode"
56 Usage: "$PROG_NAME__" [OPTIONS] action <device/file> [mountpoint]
58 $PROG_NAME__ is a wrapper arround cryptsetup with LUKS support to format a device
61 -s size of the loop-filesystem to create, in MB (default=$SIZE_)
62 -t type of filesystem (default=$FSTYPE_)
63 -r read only mode (fully supported only by start)
64 -z insecure mode, using /dev/zero for most of the initialisation (INSECURE!)
65 -o optimized initialisation mode (should be as secure as the default but faster)
66 -y verifies the passphrase by asking for it twice
67 -f force file overwriting in format mode and/or disable confirmation dialog
68 -m additional arguments to mount
69 -v verbose (show what is going on, v++)
72 CRYPTSETUP FORMAT OPTIONS:
73 -S cipher size, could be 128, 192 or 256 (default=$CIPHER_SIZE_)
74 -C cipher, should be aes-plain for pre-2.6.10 (default=$CIPHER_)
75 -I iteration time spend with PBKDF2 password processing in seconds (default=$ITERATION_TIME_)
76 -A additional arguments for cryptsetup (only supportet by format)
79 format <device/file> [mountpoint]
80 Format a device or a file (is created with the given size if it
81 does not exist) with the given filesystem and mount it, if a
83 start <device/file> <mountpoint>
84 Mount the device/file in the mountpoint.
86 Umount the given mountpoint (umount, luksClose, losetup -d)
92 losetup does _NOT_ work on unionfs => grml-crypt with a filesystem image does ONLY
93 work if the image is on a tmpfs (eg. in /home/grml or /tmp).
103 # first trying normal devicename
104 tmp_="${DM_PREFIX_}${device_}"
105 if [ ! -e "$tmp_" ]; then
110 # second trying uuid of luks
111 #uuid_=`execute "$CRYPTSETUP_ luksUUID $1"`
112 #if [[ $? == 0 ]]; then
113 # echo "$prefix_$uuid_"
116 warn "could not create device-mapper name for $1"
121 function formatDevice
123 type_="$1" # could be donothing or init
126 args_="$VERIFY_PW_ $BATCH_MODE_ --key-size $CIPHER_SIZE_ --cipher $CIPHER_ --iter-time $ITERATION_TIME_ $ADDITIONAL_CRYPTSETUP_ARGS_"
127 #args_=`echo "$args_" |tr -s ' '`
128 execute "$CRYPTSETUP_ $args_ luksFormat $TARGET_" warn || return 1
130 execute "$CRYPTSETUP_ luksOpen $TARGET_ $DM_NAME_" warn \
131 "could not open $DM_PATH_ to create a filesystem on it!" || return 1
132 if [[ $type_ == 'init' && $OPTIMIZED_MODE_SET_ == 'true' ]]; then
133 echo "finishing optimized initialisation (this could take some time)"
135 execute "dd if=/dev/zero of=$DM_PATH_ bs=1M &>/dev/null" # || \
136 # warn "could not finish optimized initialisation properly"
138 # cutted out because of no space left on device error :(
139 #if [[ $ret_ != 0 ]]; then
140 # execute "$CRYPTSETUP_ luksClose $DM_NAME_" warn
145 execute "$MKFS_ $DM_PATH_ >/dev/null" warn
146 if [[ $? != 0 ]]; then
147 execute "$CRYPTSETUP_ luksClose $DM_NAME_"
148 warn "could not create filesystem on $DM_PATH_" 1
151 echo "Successully created $FSTYPE_ on encrypted $TARGET_"
161 # no mountpoint, by-by
162 if [[ "$MOUNT_POINT_" == "" ]]; then
164 die 'no mountpoint given'
166 if [ ! -d "$MOUNT_POINT_" ]; then
167 die "mountpoint $MOUNT_POINT_ does not exist"
169 # removed due to unionfs problem isLuks does not work with filesystem images
171 #$CRYPTSETUP_ isLuks $TARGET_ || die "$TARGET_ is not a luks partition"
173 # TARGET (is/should be) a filesystem image
174 if [ ! -b "$TARGET_" ]; then
175 notice "Operating on a file"
176 isExistent "$TARGET_" die "image does not exist"
177 TARGET_=`findNextFreeLoop` || die "could not find a free loop device"
179 # TARGET_ is now /dev/loop<x>
180 execute "losetup $TARGET_ $ORIG_TARGET_" die
183 $READONLY_SET_ && cargs_='--readonly'
184 execute "$CRYPTSETUP_ $cargs_ luksOpen $TARGET_ $DM_NAME_" warn || execute "losetup -d $TARGET_" || \
185 die "could not luksOpen $TARGET_"
187 $READONLY_SET_ && margs_='-r'
188 execute "mount $margs_ $ADDITIONAL_MOUNT_ARGS_ $DM_PATH_ $MOUNT_POINT_" die
197 isExistent "$mp_" die
198 tmp_=`realpath $mp_` || die "could not get realpath of $mp_"
199 dprint "realpath_=\"$tmp_\""
201 dm_path_=`mount |grep "$tmp_ "` || die "$tmp_ is not mounted"
202 dprint "dm_path_=\"$dm_path_\""
203 dm_path_=`echo $dm_path_ |awk '{print $1}'` || die "could not get devicemapper name for $tmp_"
204 dprint "dm_path_=\"$dm_path_\""
206 dm_name_="${dm_path_##*/}"
207 dprint "dm_name_=\"$dm_name_\""
209 dmsetup info $dm_name_ >/dev/null ||die "$dm_name_ is not aktive"
210 device_=`$CRYPTSETUP_ status $dm_name_ |awk '/device:/{print $2}'` || \
211 die "could not get underlying device of $dm_path_"
212 dprint "device_=\"$device_\""
214 execute "umount $dm_path_" die "could not unmount $device_"
215 execute "$CRYPTSETUP_ luksClose $dm_name_" die "could not close $dm_path_"
216 echo "$device_" |grep loop &>/dev/null && execute "losetup -d $device_" \
217 die "could not delete loop device $device_" || \
218 execute "losetup -d $device_ &>/dev/null" eprint "could not delete loop device $device_, \
219 this device could possible not be a loop device => maybe bogus error"
220 notice "$mp_ successfully unmountet/closed/deleted"
230 echo -n " (type uppercase yes): " >&2
232 if [[ $input == 'YES' ]]; then
239 function actionFormat
245 if (( $SIZE_ < 3 )); then
246 die "the minimum size of an encrypted luks partition should be 2"
249 # TARGET (is/should be) a filesystem image
250 if [ ! -b "$TARGET_" ]; then
251 notice "Operating on a file"
253 if [ -e "$TARGET_" ]; then
254 $FORCE_ || die "file $TARGET_ does allready exist"
255 warn "overwriting file $TARGET_"
258 echo -n "Initialising file with "
259 if [[ $OPTIMIZED_MODE_SET_ == 'true' ]]; then
260 echo "optimized SECURE mode"
261 execute "dd if=/dev/zero of=$TARGET_ bs=1M count=${SIZE_} &>/dev/null" \
262 die "could not initialise $TARGET_ with /dev/zero"
264 if [[ $OVERWRITE_SOURCE_DEV_ == '/dev/zero' ]]; then
265 echo "INSERCURE mode"
267 echo "SECURE mode (taking /dev/urandom as source, this could take some time)"
269 execute "dd if=$OVERWRITE_SOURCE_DEV_ of=$TARGET_ bs=1M count=${SIZE_} &>/dev/null" ||\
270 die "could not initialise $TARGET_ with $OVERWRITE_SOURCE_DEV_"
274 TARGET_=`findNextFreeLoop` || die "could not find a free loop device"
276 # TARGET_ is now /dev/loop<x>
277 execute "losetup $TARGET_ $ORIG_TARGET_" die
278 if [[ $OPTIMIZED_MODE_SET_ == 'true' || $OVERWRITE_SOURCE_DEV_ == '/dev/zero' ]]; then
279 execute "dd if=/dev/urandom of=$TARGET_ bs=1M count=2 &>/dev/null" \
280 die "could not initialise the fist 2MB of $TARGET_ with /dev/urandom"
282 formatDevice "$init_"
285 $FORCE_ || (yesDialog "Are you shure you want to overwrite $TARGET_ ?" || die 'You are not sure')
286 notice 'Operating on a device'
287 echo -n 'Initialising device with '
288 if [[ $OPTIMIZED_MODE_SET_ == 'true' ]]; then
289 echo "optimised SECURE mode"
290 execute "dd if=/dev/urandom of=$TARGET_ bs=1M count=2 &>/dev/null" ||\
291 die "could not initialise the first 2MB of $TARGET_ with /dev/urandom"
292 elif [[ $OVERWRITE_SOURCE_DEV_ != '/dev/zero' ]]; then
294 echo "SECURE mode (taking $OVERWRITE_SOURCE_DEV_ as source, this could take some time)"
295 execute "dd if=$OVERWRITE_SOURCE_DEV_ of=$TARGET_ bs=1M &>/dev/null" #||\
296 # skipped because "no space left on device" from dd
297 # die "could not initialise $TARGET_ with $OVERWRITE_SOURCE_DEV_"
299 echo 'INSECURE mode (only initialising the fist 2MB with /dev/urandom)'
300 execute "dd if=/dev/urandom of=$TARGET_ bs=1M count=2 &>/dev/null" \
301 die "could not initialise the first 2MB of $TARGET_ with /dev/urandom"
304 formatDevice "$init_"
308 # formatDevice was successfully
309 if (( $ret_ == 0 )); then
310 # a mountpoint was given (don't luksClose the device)
311 local mount_point_exists_='true'
312 test -d "$MOUNT_POINT_" || mount_point_exists_='false'
314 if [[ $MOUNT_POINT_ != "" && "$mount_point_exists_" == 'true' ]]; then
315 $READONLY_SET_ && margs_='-r'
316 execute "mount $margs_ $ADDITIONAL_MOUNT_ARGS_ $DM_PATH_ $MOUNT_POINT_" die
318 if [[ $MOUNT_POINT_ != "" ]]; then
319 $mount_point_exists_ || warn "mountpoint $MOUNT_POINT_ does not exist, not mounting. please use \"grml-crypt start $ORIG_TARGET_ <mountpoint>\" to start the device"
321 execute "$CRYPTSETUP_ luksClose $DM_NAME_" warn
322 $IS_IMAGE_ && execute "losetup -d $TARGET_" warn
325 execute "$CRYPTSETUP_ luksClose $DM_NAME_" warn
326 $IS_IMAGE_ && execute "losetup -d $TARGET_" warn
336 while getopts "s:t:rzoyfm:hvS:C:I:A:" opt; do
338 s) SIZE_="$OPTARG"; SIZE_SET_='true' ;;
339 t) FSTYPE_="$OPTARG" ;;
340 r) READONLY_SET_='true' ;;
341 z) let OPTIMIZING_LEVEL_=$OPTIMIZING_LEVEL_+1
342 OVERWRITE_SOURCE_DEV_='/dev/zero'
343 warn 'initialising from INSECURE source /dev/zero' ;;
344 o) let OPTIMIZING_LEVEL_=$OPTIMIZING_LEVEL_+1
345 OPTIMIZED_MODE_SET_='true' ;;
346 y) VERIFY_PW_="--verify-passphrase" ;;
348 m) ADDITIONAL_MOUNT_ARGS_="$OPTARG" ;;
349 h) printUsage; exit ;;
350 v) let verbose_=$verbose_+1 ;;
351 S) CIPHER_SIZE_="$OPTARG" ;;
352 C) CIPHER_="$OPTARG" ;;
353 I) ITERATION_TIME_="$OPTARG" ;;
354 A) ADDITIONAL_CRYPTSETUP_ARGS_="$OPTARG" ;;
355 ?) printUsage; exit 64 ;;
358 shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter
361 checkRoot die "You have to be root to use this program"
364 if [[ $1 == 'help' ]]; then
368 if (( $# < 2 )); then
370 die "wrong number of arguments ($#)" 1
372 if (( $OPTIMIZING_LEVEL_ > 1 )); then
374 die "please choose ONE initialisation methode"
378 MKFS_="/sbin/mkfs.$FSTYPE_"
379 if [ ! -x "$MKFS_" ]; then
380 die "invalid filesystem type \"$FSTYPE_\"" 1
383 # use batch-mode if available
384 $CRYPTSETUP_ $BATCH_MODE_ --help &>/dev/null;
387 0) dprint "your cryptsetup understands --batch-mode" ;;
388 1) BATCH_MODE_=""; notice "your cryptsetup does NOT understand --batch-mode, trying without" ;;
389 127) die "could not execute cryptsetup" 127 ;;
390 *) warn "problems executing $CRYPTSETUP_" $ret_
393 DM_NAME_="`getDMName $TARGET_`"
394 DM_PATH_="$DEV_MAPPER_/$DM_NAME_"
395 ORIG_TARGET_="$TARGET_"
399 format) ACTION_='format'; actionFormat ;;
400 start) ACTION_='start'; actionStart ;;
401 stop) ACTION_='stop'; actionStop "$TARGET_" ;;
406 ################################################################################
407 # vim:foldmethod=marker tabstop=2 expandtab shiftwidth=2