Skip to content

Commit

Permalink
Merge pull request #2504 from vcrhonek/luks2
Browse files Browse the repository at this point in the history
Added initial LUKS2 support, see #2204
Added new parameter 'type' to 'crypt' keyword used in disklayout.conf.
Using this parameter allows to recreate the same version of LUKS as on the original system.
Added LUKS version detection, parsing depending on version and usage of 'type' parameter.
  • Loading branch information
jsmeix committed Oct 28, 2020
2 parents 011ea38 + 6c72d28 commit 8dfd1c1
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 35 deletions.
2 changes: 1 addition & 1 deletion doc/user-guide/06-layout-configuration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ lvmvol <volume_group> <name> <size(bytes)> <layout> [key:value ...]

=== LUKS Devices ===
----------------------------------
crypt /dev/mapper/<name> <device> [cipher=<cipher>] [key_size=<key size>] [hash=<hash function>] [uuid=<uuid>] [keyfile=<keyfile>] [password=<password>]
crypt /dev/mapper/<name> <device> [type=<type>] [cipher=<cipher>] [key_size=<key size>] [hash=<hash function>] [uuid=<uuid>] [keyfile=<keyfile>] [password=<password>]
----------------------------------

=== DRBD ===
Expand Down
7 changes: 1 addition & 6 deletions usr/share/rear/conf/default.conf
Original file line number Diff line number Diff line change
Expand Up @@ -1673,11 +1673,6 @@ LANG_RECOVER=C

# LUKS_CRYPTSETUP_OPTIONS contains additional options to cryptsetup
# which complement auto-detected options and enforce certain settings.
# Because LUKS2 is not (yet) supported by ReaR (cf. https://github.com/rear/rear/issues/2204)
# the option '--type luks1' is needed to enforce the LUKS1 header format
# because the default header format is LUKS1 with cryptsetup < 2.1.0
# but LUKS2 with cryptsetup ≥ 2.1.0 (cf. https://github.com/rear/rear/issues/2432)
# to ensure LUKS1 gets recreated as LUKS1 also with with newer cryptsetup versions.
# The default settings '--iter-time 2000 --use-random' increase security
# beyond the level attained by compiled-in cryptsetup defaults.
# On some systems using the /dev/random random generator may result in possibly long delays
Expand All @@ -1701,7 +1696,7 @@ LANG_RECOVER=C
# when a specified LVM volume size does no longer fit into a smaller LUKS data payload area,
# cf. https://github.com/rear/rear/issues/2389
# For details, see the cryptsetup(8) manual page of your particular Linux distribution.
LUKS_CRYPTSETUP_OPTIONS="--type luks1 --iter-time 2000 --use-random"
LUKS_CRYPTSETUP_OPTIONS="--iter-time 2000 --use-random"

##
# BACKUP=CDM (Rubrik CDM; Cloud Data Managemnt)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ create_crypt() {
value=${option#*=}

case "$key" in
type)
cryptsetup_options+=" --type $value"
;;
cipher)
cryptsetup_options+=" --cipher $value"
;;
Expand Down
60 changes: 32 additions & 28 deletions usr/share/rear/layout/save/GNU/Linux/260_crypt_layout.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ has_binary cryptsetup || return 0
Log "Saving Encrypted volumes"

# cryptsetup is required in the recovery system if disklayout.conf contains at least one 'crypt' entry
# but also in case of an incomplete commented '#crypt' entry from a LUKS2 volume
# so we include things in any case so that the user could do a manual setup if needed
# cf. https://github.com/rear/rear/issues/2491
# See the create_crypt function in layout/prepare/GNU/Linux/160_include_luks_code.sh
# what program calls are written to diskrestore.sh and
# see also https://github.com/rear/rear/issues/1963
Expand Down Expand Up @@ -40,42 +37,49 @@ while read target_name junk ; do
Log "Skipping $target_name (could not get its device in /sys/block/$sysfs_device/slaves/)"
continue
fi

if ! cryptsetup isLuks $source_device ; then
Log "Skipping $target_name (its $source_device is not a LUKS device)"

if ! blkid -p -o export $source_device >$TMP_DIR/blkid.output ; then
LogPrintError "Error: Cannot get attributes for $target_name ('blkid -p -o export $source_device' failed)"
continue
fi

if ! grep -q "TYPE=crypto_LUKS" $TMP_DIR/blkid.output ; then
Log "Skipping $target_name (no 'TYPE=crypto_LUKS' in 'blkid -p -o export $source_device' output)"
continue
fi

# Detect LUKS version:
# Remove all non-digits in particular to avoid leading or trailing spaces in the version string
# cf. "Beware of the emptiness" in https://github.com/rear/rear/wiki/Coding-Style
# that could happen if the blkid output contains "VERSION = 2" so that 'cut -d= -f2' results " 2".
version=$( grep "VERSION" $TMP_DIR/blkid.output | cut -d= -f2 | tr -c -d '[:digit:]' )
if ! test "$version" = "1" -o "$version" = "2" ; then
LogPrintError "Error: Unsupported LUKS version for $target_name ('blkid -p -o export $source_device' shows 'VERSION=$version')"
continue
fi
luks_type=luks$version

# Gather crypt information:
if ! cryptsetup luksDump $source_device >$TMP_DIR/cryptsetup.luksDump ; then
LogPrintError "Error: Cannot get LUKS values for $target_name ('cryptsetup luksDump $source_device' failed)"
continue
fi
cipher=$( grep "Cipher name" $TMP_DIR/cryptsetup.luksDump | sed -r 's/^.+:\s*(.+)$/\1/' )
mode=$( grep "Cipher mode" $TMP_DIR/cryptsetup.luksDump | cut -d: -f2- | awk '{printf("%s",$1)};' )
key_size=$( grep "MK bits" $TMP_DIR/cryptsetup.luksDump | sed -r 's/^.+:\s*(.+)$/\1/' )
hash=$( grep "Hash spec" $TMP_DIR/cryptsetup.luksDump | sed -r 's/^.+:\s*(.+)$/\1/' )
uuid=$( grep "UUID" $TMP_DIR/cryptsetup.luksDump | sed -r 's/^.+:\s*(.+)$/\1/' )
keyfile_option=$( [ -f /etc/crypttab ] && awk '$1 == "'"$target_name"'" && $3 != "none" && $3 != "-" && $3 != "" { print "keyfile=" $3; }' /etc/crypttab )

# LUKS version 2 is not yet suppported, see https://github.com/rear/rear/issues/2204
# When LUKS version 2 is used the above code fails at least to determine the hash value
# so we use an empty hash value as a simple test if gathering crypt information was successful:
if ! test "$hash" ; then
# Inform the user and write the available info as comment to disklayout.conf so that the user could manually adapt it
# but do not error out here because there is no user-friendly way to skip LUKS2 volumes during "rear mkrescue"
# and LUKS2 volumes must nnot be automatically (or even silently) skipped during "rear mkrescue"
# to let the user find out later (when it is too late) during "rear recover" that LUKS2 volumes are not supported.
# The only way to not let "rear mkrescue" process LUKS2 volumes is to 'umount' and 'cryptsetup luksClose' them
# before "rear mkrescue" is run so that those volumes are no longer listed by 'dmsetup ls --target crypt'
# cf. https://github.com/rear/rear/issues/2491
LogPrintError "Incomplete values for LUKS device '$target_name' at '$source_device' (only LUKS version 1 is supported) see $DISKLAYOUT_FILE"
echo "# Incomplete values for LUKS device '$target_name' at '$source_device' (only LUKS version 1 is supported):" >> $DISKLAYOUT_FILE
echo "#crypt /dev/mapper/$target_name $source_device cipher=$cipher-$mode key_size=$key_size hash=$hash uuid=$uuid $keyfile_option" >> $DISKLAYOUT_FILE
continue
if test $luks_type = "luks1" ; then
cipher_name=$( grep "Cipher name" $TMP_DIR/cryptsetup.luksDump | sed -r 's/^.+:\s*(.+)$/\1/' )
cipher_mode=$( grep "Cipher mode" $TMP_DIR/cryptsetup.luksDump | cut -d: -f2- | awk '{printf("%s",$1)};' )
cipher=$cipher_name-$cipher_mode
key_size=$( grep "MK bits" $TMP_DIR/cryptsetup.luksDump | sed -r 's/^.+:\s*(.+)$/\1/' )
hash=$( grep "Hash spec" $TMP_DIR/cryptsetup.luksDump | sed -r 's/^.+:\s*(.+)$/\1/' )
elif test $luks_type = "luks2" ; then
cipher=$( grep "cipher:" $TMP_DIR/cryptsetup.luksDump | sed -r 's/^.+:\s*(.+)$/\1/' )
# More than one keyslot may be defined - use key_size from the first slot
key_size=$( grep -m 1 "Cipher key" $TMP_DIR/cryptsetup.luksDump | sed -r 's/^.+:\s*(.+) bits$/\1/' )
hash=$( grep "Hash" $TMP_DIR/cryptsetup.luksDump | sed -r 's/^.+:\s*(.+)$/\1/' )
fi

echo "crypt /dev/mapper/$target_name $source_device cipher=$cipher-$mode key_size=$key_size hash=$hash uuid=$uuid $keyfile_option" >> $DISKLAYOUT_FILE
echo "crypt /dev/mapper/$target_name $source_device type=$luks_type cipher=$cipher key_size=$key_size hash=$hash uuid=$uuid $keyfile_option" >> $DISKLAYOUT_FILE

done < <( dmsetup ls --target crypt )

0 comments on commit 8dfd1c1

Please sign in to comment.