summaryrefslogtreecommitdiffstats
path: root/tests/luks2-reencryption-test
diff options
context:
space:
mode:
Diffstat (limited to 'tests/luks2-reencryption-test')
-rwxr-xr-xtests/luks2-reencryption-test1550
1 files changed, 1550 insertions, 0 deletions
diff --git a/tests/luks2-reencryption-test b/tests/luks2-reencryption-test
new file mode 100755
index 0000000..92f223d
--- /dev/null
+++ b/tests/luks2-reencryption-test
@@ -0,0 +1,1550 @@
+#!/bin/bash
+
+PS4='$LINENO:'
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+FAST_PBKDF2="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
+FAST_PBKDF_ARGON="--pbkdf-force-iterations 4 --pbkdf-memory 32 --pbkdf-parallel 1"
+DEFAULT_ARGON="argon2i"
+
+DEV=""
+OVRDEV="123reenc321"
+DEVBIG="reenc2134"
+DEV_NAME=reenc9768
+DEV_NAME2=reenc97682
+IMG=reenc-data
+IMG_HDR=/tmp/$IMG.hdr
+KEY1=key1
+VKEY1=vkey1
+PWD1="93R4P4pIqAH8"
+PWD2="1cND4319812f"
+PWD3="1-9Qu5Ejfnqv"
+
+[ -f /etc/system-fips ] && FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
+
+function dm_crypt_features()
+{
+ VER_STR=$(dmsetup targets | grep crypt | cut -f2 -dv)
+ [ -z "$VER_STR" ] && fail "Failed to parse dm-crypt version."
+
+ VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
+ VER_MIN=$(echo $VER_STR | cut -f 2 -d.)
+ VER_PTC=$(echo $VER_STR | cut -f 3 -d.)
+
+ [ $VER_MAJ -lt 1 ] && return
+ [ $VER_MAJ -gt 1 ] && {
+ DM_PERF_CPU=1
+ DM_SECTOR_SIZE=1
+ return
+ }
+
+ [ $VER_MIN -lt 14 ] && return
+ DM_PERF_CPU=1
+ if [ $VER_MIN -ge 17 -o \( $VER_MIN -eq 14 -a $VER_PTC -ge 5 \) ]; then
+ DM_SECTOR_SIZE=1
+ fi
+}
+
+function dm_delay_features()
+{
+ local _ver_str=$(dmsetup targets | grep delay | cut -f2 -dv)
+ [ -z "$_ver_str" ] && return 1
+ return 0
+}
+
+# $1 path to scsi debug bdev
+scsi_debug_teardown() {
+ local _tries=15;
+
+ while [ -b "$1" -a $_tries -gt 0 ]; do
+ rmmod scsi_debug 2> /dev/null
+ if [ -b "$1" ]; then
+ sleep .1
+ _tries=$((_tries-1))
+ fi
+ done
+
+ test ! -b "$1" || rmmod scsi_debug 2> /dev/null
+}
+
+function remove_mapping()
+{
+ [ -b /dev/mapper/$DEV_NAME ] && {
+ dmsetup resume $DEV_NAME
+ dmsetup remove --retry $DEV_NAME
+ }
+ [ -b /dev/mapper/$DEV_NAME2 ] && {
+ dmsetup resume $DEV_NAME2
+ dmsetup remove --retry $DEV_NAME2
+ }
+ [ -b /dev/mapper/$DEV_NAME-overlay ] && {
+ dmsetup resume $DEV_NAME-overlay
+ dmsetup remove --retry $DEV_NAME-overlay
+ }
+ [ -b /dev/mapper/$DEV_NAME-hotzone-forward ] && {
+ dmsetup resume $DEV_NAME-hotzone-forward
+ dmsetup remove --retry $DEV_NAME-hotzone-forward
+ }
+ [ -b /dev/mapper/$DEV_NAME-hotzone-backward ] && {
+ dmsetup resume $DEV_NAME-hotzone-backward
+ dmsetup remove --retry $DEV_NAME-hotzone-backward
+ }
+ [ -b /dev/mapper/$OVRDEV ] && dmsetup remove --retry $OVRDEV 2>/dev/null
+ [ -b /dev/mapper/$OVRDEV-err ] && dmsetup remove --retry $OVRDEV-err 2>/dev/null
+ [ -n "$LOOPDEV" ] && losetup -d $LOOPDEV
+ unset LOOPDEV
+ rm -f $IMG $IMG_HDR $KEY1 $VKEY1 $DEVBIG >/dev/null 2>&1
+ rmmod scsi_debug 2> /dev/null
+ scsi_debug_teardown $DEV
+}
+
+function fail()
+{
+ local frame=0
+ [ -n "$1" ] && echo "$1"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ remove_mapping
+ exit 2
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ remove_mapping
+ exit 77
+}
+
+function fips_mode()
+{
+ [ -n "$FIPS_MODE" ] && [ "$FIPS_MODE" -gt 0 ]
+}
+
+function add_scsi_device() {
+ scsi_debug_teardown $DEV
+ modprobe scsi_debug $@ delay=0
+ if [ $? -ne 0 ] ; then
+ echo "This kernel seems to not support proper scsi_debug module, test skipped."
+ exit 77
+ fi
+
+ sleep 1
+ DEV="/dev/"$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
+ [ -b $DEV ] || fail "Cannot find $DEV."
+}
+
+function open_crypt() # $1 pwd, $2 hdr
+{
+ if [ -n "$2" ] ; then
+ echo "$1" | $CRYPTSETUP luksOpen $DEV $DEV_NAME --header $2 || fail
+ elif [ -n "$1" ] ; then
+ echo "$1" | $CRYPTSETUP luksOpen $DEV $DEV_NAME || fail
+ else
+ $CRYPTSETUP luksOpen -d $KEY1 $DEV $DEV_NAME || fail
+ fi
+}
+
+function wipe_dev() # $1 dev
+{
+ if [ -b $1 ] ; then
+ blkdiscard --zeroout $1 2>/dev/null || dd if=/dev/zero of=$1 bs=1M conv=notrunc >/dev/null 2>&1
+ else
+ local size=$(stat --printf="%s" $1)
+ truncate -s 0 $1
+ truncate -s $size $1
+ fi
+}
+
+function wipe() # $1 pass, $2 hdr
+{
+ open_crypt $1 $2
+ wipe_dev /dev/mapper/$DEV_NAME
+ udevadm settle >/dev/null 2>&1
+ $CRYPTSETUP luksClose $DEV_NAME || fail
+}
+
+function prepare() # $1 dev1_siz
+{
+ remove_mapping
+
+ if [ ! -e $KEY1 ]; then
+ dd if=/dev/urandom of=$KEY1 count=1 bs=32 >/dev/null 2>&1
+ fi
+
+ if [ ! -e $VKEY1 ]; then
+ echo -n $'\x44\xc6\x74\x4f\x41\x4e\x50\xc0\x79\xc2\x2d\x5b\x5f\x68\x84\x17' >$VKEY1
+ echo -n $'\x9c\x03\xba\xbe\x4d\x0f\x9a\x75\xb3\x90\x70\x32\x0a\xf8\xae\xc4'>>$VKEY1
+ fi
+
+ add_scsi_device $@
+}
+
+function preparebig() # $1 dev1_siz
+{
+ remove_mapping
+
+ if [ ! -e $KEY1 ]; then
+ dd if=/dev/urandom of=$KEY1 count=1 bs=32 >/dev/null 2>&1
+ fi
+
+ truncate -s "$1"M $DEVBIG
+ LOOPDEV=$(losetup -f)
+ losetup -f $DEVBIG || fail
+ DEV=$LOOPDEV
+}
+
+function check_hash_dev() # $1 dev, $2 hash
+{
+ HASH=$(sha256sum $1 | cut -d' ' -f 1)
+ [ $HASH != "$2" ] && fail "HASH differs (expected: $2) (result $HASH)"
+}
+
+function check_hash() # $1 pwd, $2 hash, $3 hdr
+{
+ open_crypt $1 $3
+ check_hash_dev /dev/mapper/$DEV_NAME $2
+ $CRYPTSETUP remove $DEV_NAME || fail
+}
+
+function check_hash_head() # $1 pwd, $2 len, $3 hash, $4 hdr
+{
+ open_crypt $1 $4
+ if [ -n "$4" ]; then
+ echo $1 | $CRYPTSETUP resize $DEV_NAME --size $2 --header $4 || fail
+ else
+ echo $1 | $CRYPTSETUP resize $DEV_NAME --size $2 || fail
+ fi
+ check_hash_dev /dev/mapper/$DEV_NAME $3
+ $CRYPTSETUP remove $DEV_NAME || fail
+}
+
+function resize_file() # $1 dev, $2 shrink bytes
+{
+ local size=$(stat --printf="%s" $1)
+ truncate -s $(($size + $2)) $1
+ losetup -c $LOOPDEV
+}
+
+function error_writes() { # $1 dmdev, $2 data dev, $3 offset, $4 size
+ local _dev_size=$(blockdev --getsz /dev/mapper/$1)
+ local _offset=$(($3+$4))
+ local _size=$((_dev_size-_offset))
+ local _err=$1-err
+ local _table=
+ dmsetup create $_err --table "0 $_dev_size error" || fail
+
+ if [ $3 -ne 0 ]; then
+ _table="0 $3 linear $2 0\n"
+ fi
+
+ _table=$_table"$3 $4 delay $2 $3 0 /dev/mapper/$_err $3 0"
+
+ if [ $_size -ne 0 ]; then
+ _table="$_table\n$_offset $_size linear $2 $_offset"
+ fi
+
+ echo -e "$_table" | dmsetup load $1 || fail
+ dmsetup resume $1 || fail
+ blockdev --setra 0 /dev/mapper/$1
+ blockdev --setra 0 /dev/mapper/$_err
+}
+
+function fix_writes() { # $1 dmdev, $2 data dev
+ local _dev_size=$(blockdev --getsz /dev/mapper/$1)
+ dmsetup load $1 --table "0 $_dev_size linear $2 0" || fail
+ dmsetup resume $1 || fail
+ dmsetup remove --retry $1-err 2>/dev/null || fail
+}
+
+function prepare_linear_dev() {
+ local _sizemb=$1
+ shift
+
+ if [ "$_sizemb" -gt 32 ]; then
+ preparebig $_sizemb
+ else
+ prepare dev_size_mb=$_sizemb $@
+ fi
+
+ dmsetup create $OVRDEV --table "0 $((_sizemb*1024*2)) linear $DEV 0" || fail
+
+ OLD_DEV=$DEV
+ DEV=/dev/mapper/$OVRDEV
+}
+
+function get_error_offsets() # $1 devsize, $2 minimal offset, $3 sector_size [512 if omitted], $4 max offset
+{
+ local _devsize=$(($1*1024*2))
+ local _sector_size=${3:-512}
+ local _max_offset=${4:-$_devsize}
+ _sector_size=$((_sector_size/512))
+
+ # 8 sectors minimal size (4096)
+ ERRLENGTH=$((($RANDOM%56)+8))
+ ERRLENGTH=$(($ERRLENGTH-($ERRLENGTH%$_sector_size)))
+
+ ERROFFSET=$(($2+((2*$RANDOM)%($_max_offset-$2-$ERRLENGTH))))
+ ERROFFSET=$(($ERROFFSET-($ERROFFSET%$_sector_size)))
+}
+
+function reencrypt_recover() { # $1 sector size, $2 resilience, $3 digest, [$4 header]
+ echo -n "resilience mode: $2 ..."
+ local _hdr=""
+ test -z "$4" || _hdr="--header $4"
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV $_hdr --hotzone-size 1M --resilience $2 --sector-size $1 -q $FAST_PBKDF_ARGON >/dev/null 2>&1 && fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ echo $PWD1 | $CRYPTSETUP -q repair $DEV $_hdr || fail
+
+ check_hash $PWD1 $3 $4
+
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV $_hdr --resilience $2 --sector-size $1 -q $FAST_PBKDF_ARGON || fail
+ check_hash $PWD1 $3 $4
+
+ echo "[OK]"
+}
+
+function reencrypt_recover_online() { # $1 sector size, $2 resilience, $3 digest, [$4 header]
+ echo -n "resilience mode: $2 ..."
+ local _hdr=""
+ test -z "$4" || _hdr="--header $4"
+
+ echo $PWD1 | $CRYPTSETUP open $DEV $_hdr $DEV_NAME || fail
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt --active-name $DEV_NAME $_hdr --hotzone-size 1M --resilience $2 --sector-size $1 -q $FAST_PBKDF_ARGON >/dev/null 2>&1 && fail
+ $CRYPTSETUP status $DEV_NAME $_hdr | grep -q "reencryption: in-progress" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ # recovery during activation
+ echo $PWD1 | $CRYPTSETUP open $DEV $_hdr $DEV_NAME || fail
+ check_hash_dev /dev/mapper/$DEV_NAME $3
+
+ $CRYPTSETUP luksDump ${4:-$DEV} | grep -q "online-reencrypt"
+ if [ $? -eq 0 ]; then
+ $CRYPTSETUP status $DEV_NAME $_hdr | grep -q "reencryption: in-progress" || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt --active-name $DEV_NAME $_hdr --resilience $2 --resume-only -q || fail
+ check_hash_dev /dev/mapper/$DEV_NAME $3
+ fi
+
+ $CRYPTSETUP close $DEV_NAME || fail
+ echo "[OK]"
+}
+
+function encrypt_recover() { # $1 sector size, $2 reduce size, $3 digest, $4 device size in sectors, $5 origin digest
+ wipe_dev $DEV
+ check_hash_dev $DEV $5
+
+ echo -n "resilience mode: datashift ..."
+
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --reduce-device-size $2 --sector-size $1 -q $FAST_PBKDF_ARGON --init-only >/dev/null 2>&1 || fail
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q >/dev/null 2>&1 && fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ echo $PWD1 | $CRYPTSETUP -q repair $DEV || fail
+
+ $CRYPTSETUP luksDump $DEV | grep -q "online-reencrypt"
+ if [ $? -eq 0 ]; then
+ check_hash $PWD1 $3
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --sector-size $1 -q $FAST_PBKDF_ARGON || fail
+ fi
+
+ check_hash_head $PWD1 $4 $3
+
+ echo "[OK]"
+}
+
+function encrypt_recover_online() { # $1 sector size, $2 reduce size, $3 digest, $4 device size in sectors, $5 origin digest
+ wipe_dev $DEV
+ check_hash_dev $DEV $5
+
+ echo -n "resilience mode: datashift ..."
+
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --reduce-device-size $2 --sector-size $1 -q $FAST_PBKDF_ARGON --init-only > /dev/null || fail
+ echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q >/dev/null 2>&1 && fail
+ $CRYPTSETUP status $DEV_NAME | grep -q "reencryption: in-progress" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ # recovery in activation
+ echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+
+ $CRYPTSETUP luksDump $DEV | grep -q "online-reencrypt"
+ if [ $? -eq 0 ]; then
+ $CRYPTSETUP status $DEV_NAME | grep -q "reencryption: in-progress" || fail
+ check_hash_dev /dev/mapper/$DEV_NAME $3
+ echo $PWD1 | $CRYPTSETUP reencrypt --resume-only --active-name $DEV_NAME -q || fail
+ fi
+
+ $CRYPTSETUP close $DEV_NAME || fail
+ check_hash_head $PWD1 $4 $3
+
+ echo "[OK]"
+}
+
+function encrypt_recover_detached() { # $1 sector size, $2 resilience, $3 digest, $4 hdr
+ wipe_dev $DEV
+ check_hash_dev $DEV $3
+
+ echo -n "resilience mode: $2 ..."
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --hotzone-size 1M --header $4 --resilience $2 --sector-size $1 -q $FAST_PBKDF_ARGON 2>/dev/null && fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ echo $PWD1 | $CRYPTSETUP repair $DEV --header $4 || fail
+
+ check_hash $PWD1 $3 $4
+
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --header $4 --resilience $2 --sector-size $1 -q $FAST_PBKDF_ARGON || fail
+ check_hash $PWD1 $3 $4
+
+ echo "[OK]"
+}
+
+function encrypt_recover_detached_online() { # $1 sector size, $2 resilience, $3 digest, $4 hdr
+ wipe_dev $DEV
+ check_hash_dev $DEV $3
+
+ echo -n "resilience mode: $2 ..."
+
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --hotzone-size 1M --header $4 --resilience $2 --sector-size $1 -q $FAST_PBKDF_ARGON --init-only || fail
+ echo $PWD1 | $CRYPTSETUP open $DEV --header $4 $DEV_NAME || fail
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $DEV --header $4 --hotzone-size 1M 2>/dev/null && fail
+ $CRYPTSETUP status $DEV_NAME --header $4 | grep -q "reencryption: in-progress" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ echo $PWD1 | $CRYPTSETUP open $DEV --header $4 $DEV_NAME || fail
+ check_hash_dev /dev/mapper/$DEV_NAME $3
+
+ $CRYPTSETUP luksDump $4 | grep -q "online-reencrypt"
+ if [ $? -eq 0 ]; then
+ $CRYPTSETUP status $DEV_NAME --header $4 | grep -q "reencryption: in-progress" || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt --active-name $DEV_NAME --resume-only --header $4 --resilience $2 -q || fail
+ check_hash_dev /dev/mapper/$DEV_NAME $3
+ fi
+
+ $CRYPTSETUP close $DEV_NAME || fail
+
+ echo "[OK]"
+}
+
+function decrypt_recover_detached() { # $1 sector size, $2 resilience, $3 digest, $4 hdr
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size $1 --header $4 $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1 $4
+ check_hash $PWD1 $3 $4
+
+ echo -n "resilience mode: $2 ..."
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --decrypt --hotzone-size 1M --header $4 --resilience $2 -q 2>/dev/null && fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ echo $PWD1 | $CRYPTSETUP repair $DEV --header $4 || fail
+
+ $CRYPTSETUP luksDump $4 | grep -q "online-reencrypt"
+ if [ $? -eq 0 ]; then
+ check_hash $PWD1 $3 $4
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --resume-only --header $4 --resilience $2 -q || fail
+ fi
+
+ check_hash_dev $DEV $3
+
+ echo "[OK]"
+}
+
+function decrypt_recover_detached_online() { # $1 sector size, $2 resilience, $3 digest, $4 hdr
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size $1 --header $4 $FAST_PBKDF_ARGON $DEV || fail
+ echo $PWD1 | $CRYPTSETUP open $DEV --header $4 $DEV_NAME || fail
+ wipe_dev /dev/mapper/$DEV_NAME
+ check_hash_dev /dev/mapper/$DEV_NAME $3
+
+ echo -n "resilience mode: $2 ..."
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --decrypt --hotzone-size 1M --header $4 --resilience $2 -q 2>/dev/null && fail
+ $CRYPTSETUP status $DEV_NAME --header $4 | grep -q "reencryption: in-progress" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ # recovery during activation
+ echo $PWD1 | $CRYPTSETUP open $DEV --header $4 $DEV_NAME || fail
+
+ $CRYPTSETUP luksDump $4 | grep -q "online-reencrypt"
+ if [ $? -eq 0 ]; then
+ $CRYPTSETUP status $DEV_NAME --header $4 | grep -q "reencryption: in-progress" || fail
+ check_hash_dev /dev/mapper/$DEV_NAME $3
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --header $4 --resilience $2 -q || fail
+ fi
+
+ $CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 && fail
+ check_hash_dev $DEV $3
+
+ echo "[OK]"
+}
+
+# sector size (bytes)
+# reenc dev size (sectors)
+# reenc dev digest
+# resilience
+# orig size
+# orig size digest
+# hdr (optional)
+function reencrypt_offline_fixed_size() {
+ local _esz=$(($1>>9))
+ local _hdr=""
+ test -z "$7" || _hdr="--header $7"
+
+ # reencrypt with fixed device size
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --sector-size $1 --device-size $2s --resilience $4 || fail
+ check_hash_head $PWD1 $2 $3 $7
+ wipe $PWD1 $7
+
+ # try to reencrypt device size + 1 encryption sector size
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --sector-size $1 --init-only || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --device-size $(($5+_esz))s --resilience $4 2>/dev/null && fail
+ check_hash $PWD1 $6 $7
+
+ # misaligned reencryption size
+ if [ $_esz -gt 1 ]; then
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --device-size $(($2+_esz-1))s --resilience $4 2>/dev/null && fail
+ $CRYPTSETUP luksDump ${7:-$DEV} | grep -q "2: crypt" || fail
+ $CRYPTSETUP luksDump ${7:-$DEV} | grep -q "3: crypt" && fail
+ check_hash $PWD1 $6 $7
+ fi
+}
+
+# sector size (bytes)
+# reenc dev size (sectors)
+# reenc dev digest
+# resilience
+# orig size
+# orig size digest
+# hdr
+function encrypt_offline_fixed_size() {
+ local _esz=$(($1>>9))
+
+ # reencrypt with fixed device size
+ wipe_dev $DEV
+ echo $PWD1 | $CRYPTSETUP reencrypt --encrypt -q $FAST_PBKDF_ARGON $DEV --header $7 --sector-size $1 --device-size $2s --resilience $4 || fail
+ check_hash_head $PWD1 $2 $3 $7
+
+ # try to reencrypt device size + 1 encryption sector size
+ wipe_dev $DEV
+ echo $PWD1 | $CRYPTSETUP reencrypt --encrypt -q $FAST_PBKDF_ARGON $DEV --header $7 --sector-size $1 --init-only || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV --header $7 --device-size $(($5+_esz))s --resilience $4 2>/dev/null && fail
+ check_hash $PWD1 $6 $7
+
+ # misaligned reencryption size
+ if [ $_esz -gt 1 ]; then
+ echo $PWD1 | $CRYPTSETUP reencrypt --encrypt -q $FAST_PBKDF_ARGON $DEV --header $7 --sector-size $1 --init-only || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $DEV --header $7 --device-size $(($2+_esz-1))s --resilience $4 2>/dev/null && fail
+ $CRYPTSETUP luksDump $7 | grep -q "2: crypt" || fail
+ $CRYPTSETUP luksDump $7 | grep -q "3: crypt" && fail
+ check_hash $PWD1 $6 $7
+ fi
+}
+
+# sector size (bytes)
+# reenc dev size (sectors)
+# reenc dev digest
+# resilience
+# orig size
+# orig size digest
+# hdr
+function decrypt_offline_fixed_size() {
+ local _esz=$(($1>>9))
+
+ # decrypt with fixed device size
+ echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 -q $FAST_PBKDF_ARGON $DEV --header $7 --sector-size $1 || fail
+ wipe $PWD1 $7
+ echo $PWD1 | $CRYPTSETUP reencrypt --decrypt -q $DEV --header $7 --device-size $2s --resilience $4 || fail
+
+ dmsetup load $OVRDEV --table "0 $2 linear $OLD_DEV 0" || fail
+ dmsetup resume $OVRDEV || fail
+ check_hash_dev $DEV $3
+ dmsetup load $OVRDEV --table "0 $5 linear $OLD_DEV 0" || fail
+ dmsetup resume $OVRDEV || fail
+
+ # try to decrypt device size + 1 encryption sector size
+ echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 -q $FAST_PBKDF_ARGON $DEV --header $7 --sector-size $1 || fail
+ wipe $PWD1 $7
+ echo $PWD1 | $CRYPTSETUP reencrypt --decrypt -q $FAST_PBKDF_ARGON $DEV --header $7 --init-only || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV --header $7 --device-size $(($5+_esz))s --resilience $4 2>/dev/null && fail
+ check_hash $PWD1 $6 $7
+
+ # misaligned reencryption size
+ if [ $_esz -gt 1 ]; then
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $DEV --header $7 --device-size $(($2+_esz-1))s --resilience $4 2>/dev/null && fail
+ $CRYPTSETUP luksDump $7 | grep -q "2: linear\|2: crypt" || fail
+ $CRYPTSETUP luksDump $7 | grep -q "3: crypt\|3: linear" && fail
+ check_hash $PWD1 $6 $7
+ fi
+}
+
+# sector size (bytes)
+# reenc dev size (sectors)
+# reenc dev digest
+# resilience
+# orig size
+# orig size digest
+# hdr (optional)
+function reencrypt_online_fixed_size() {
+ local _esz=$(($1>>9))
+ local _hdr=""
+ test -z "$7" || _hdr="--header $7"
+
+ if [ -z "$_hdr" ]; then
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --sector-size 512 --type luks2 --offset 16384 $FAST_PBKDF_ARGON $DEV || fail
+ else
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --sector-size 512 --type luks2 $_hdr $FAST_PBKDF_ARGON $DEV || fail
+ fi
+ wipe $PWD1 $7
+
+ # reencrypt with fixed device size
+ echo $PWD1 | $CRYPTSETUP open $DEV $_hdr $DEV_NAME || fail
+ echo $PWD1 | $CRYPTSETUP resize $DEV_NAME $_hdr --size $2 || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --sector-size $1 --resilience $4 || fail
+ $CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "$2 sectors" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ check_hash_head $PWD1 $2 $3 $7
+ wipe $PWD1 $7
+
+ # active device != requested reencryption size
+ echo $PWD1 | $CRYPTSETUP open $DEV $_hdr $DEV_NAME || fail
+ echo $PWD1 | $CRYPTSETUP resize $DEV_NAME $_hdr --size $2 || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --sector-size $1 --init-only || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --device-size $(($2-_esz))s --resilience $4 2>/dev/null && fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --device-size $2s --resilience $4 || fail
+ $CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "$2 sectors" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ check_hash_head $PWD1 $2 $3 $7
+
+ # misaligned reencryption size
+ if [ $_esz -gt 1 ]; then
+ if [ -z "$_hdr" ]; then
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --sector-size 512 --type luks2 --offset 16384 $FAST_PBKDF_ARGON $DEV || fail
+ else
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --sector-size 512 --type luks2 $_hdr $FAST_PBKDF_ARGON $DEV || fail
+ fi
+ wipe $PWD1 $7
+ check_hash $PWD1 $6 $7
+
+ echo $PWD1 | $CRYPTSETUP open $DEV $_hdr $DEV_NAME || fail
+ echo $PWD1 | $CRYPTSETUP resize $DEV_NAME $_hdr --size $(($2+_esz-1)) || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --sector-size $1 --init-only || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --resilience $4 2>/dev/null && fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ check_hash $PWD1 $6 $7
+ fi
+}
+
+function setup_luks2_env() {
+ echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 -c aes-xts-plain64 $FAST_PBKDF_ARGON $DEV || fail
+ echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+ HAVE_KEYRING=$($CRYPTSETUP status $DEV_NAME | grep "key location: keyring")
+ if [ -n "$HAVE_KEYRING" ]; then
+ HAVE_KEYRING=1
+ else
+ HAVE_KEYRING=0
+ fi
+ DEF_XTS_KEY=$($CRYPTSETUP status $DEV_NAME | grep "keysize:" | sed 's/\( keysize: \)\([0-9]\+\)\(.*\)/\2/')
+ [ -n "$DEF_XTS_KEY" ] || fail "Failed to parse xts mode key size."
+ $CRYPTSETUP close $DEV_NAME || fail
+}
+
+function valgrind_setup()
+{
+ which valgrind >/dev/null 2>&1 || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+fips_mode && skip "This test cannot be run in FIPS mode."
+modprobe --dry-run scsi_debug || exit 77
+modprobe dm-crypt || fail "dm-crypt failed to load"
+modprobe dm-delay > /dev/null 2>&1
+dm_crypt_features
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ TEST_SECTORS="512 4096"
+else
+ TEST_SECTORS="512"
+fi
+
+modinfo scsi_debug -p | grep -q opt_xferlen_exp && OPT_XFERLEN_EXP="opt_xferlen_exp=6"
+
+export LANG=C
+
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+
+# REENCRYPTION tests
+
+# 28 MiBs of zeros (32MiBs - 4MiB LUKS2 header)
+HASH1=f8280c81b347b01405277bf9e8bf0685ae8be863ff104797c65b7169f8203fd2
+# 1 MiB of zeros
+HASH2=30e14955ebf1352266dc2ff8067e68104607e750abb9d3b36582b8af909fcb58
+# 256 MiBs of zeros
+HASH3=a6d72ac7690f53be6ae46ba88506bd97302a093f7108472bd9efc3cefda06484
+# 64 MiBs of zeroes
+HASH4=3b6a07d0d404fab4e23b6d34bc6696a6a312dd92821332385e5af7c01c421351
+# 56 MiBs of zeroes
+HASH5=8afcb7e7189ce4d112fd245eaa60c3cfcf5a5d5e1d6bf4eb85941d73ef8cfbd5
+# 43 MiBs of zeroes
+HASH6=39f7c6d38af574fe2c90ef400dfaba8ef8edccd11bdac998a3f8143a86837331
+# 31 MiBs of zeroes
+HASH7=18a393d1a505e22ccf3e29effe3005ea8627e4c36b7cca0e53f58121f49b67e1
+# 60 MiBs of zeroes
+HASH8=cf5ac69ca412f9b3b1a8b8de27d368c5c05ed4b1b6aa40e6c38d9cbf23711342
+
+prepare dev_size_mb=32
+setup_luks2_env
+
+echo "[1] Reencryption"
+echo -n "[512 sector]"
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 -c aes-cbc-essiv:sha256 --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON 2>&1 | tail -1 | grep -q "not supported" && skip " No reenryption support, test skipped."
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 256 -c twofish-cbc-essiv:sha256 --resilience journal $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience none $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 128 -c aes-cbc-essiv:sha256 --resilience checksum $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+# simple test --active-name can consume absolute path to mapping
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -c aes-xts-plain64 --init-only $FAST_PBKDF_ARGON || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP reencrypt --active-name /dev/mapper/$DEV_NAME --resilience none -q || fail
+XTS_KEY=$($CRYPTSETUP status $DEV_NAME | grep "keysize:" | sed 's/\( keysize: \)\([0-9]\+\)\(.*\)/\2/')
+[ "$XTS_KEY" -eq "$DEF_XTS_KEY" ] || fail "xts mode has wrong key size after reencryption ($XTS_KEY != expected $DEF_XTS_KEY)"
+echo $PWD1 | $CRYPTSETUP close $DEV_NAME || fail
+echo -n "[OK][4096 sector]"
+prepare sector_size=4096 dev_size_mb=32
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 -c aes-cbc-essiv:sha256 --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 256 -c twofish-cbc-essiv:sha256 --resilience journal $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience none $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 128 -c aes-cbc-essiv:sha256 --resilience checksum $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON --sector-size 4096 || fail
+ check_hash $PWD1 $HASH1
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 256 -c twofish-cbc-essiv:sha256 --resilience journal --sector-size 2048 $FAST_PBKDF_ARGON || fail
+ check_hash $PWD1 $HASH1
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience none $FAST_PBKDF_ARGON --sector-size 1024 || fail
+ check_hash $PWD1 $HASH1
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 128 -c aes-cbc-essiv:sha256 --resilience checksum --sector-size 512 $FAST_PBKDF_ARGON || fail
+ check_hash $PWD1 $HASH1
+fi
+echo -n "[OK][4096/512 sector]"
+prepare sector_size=512 physblk_exp=3 dev_size_mb=32
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 -c aes-cbc-essiv:sha256 --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 256 -c twofish-cbc-essiv:sha256 --resilience journal $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience none $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 128 -c aes-cbc-essiv:sha256 --resilience checksum $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo "[OK]"
+
+# reencrypt minimal device size (FIXME: change data device size to single encryption sector size)
+# temporary small device size is default luks2 hdr size + 1MiB
+echo -n "[small device reencryption]"
+prepare dev_size_mb=5
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 -c aes-cbc-essiv:sha256 --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+check_hash $PWD1 $HASH2
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH2
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 256 -c twofish-cbc-essiv:sha256 --resilience journal $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH2
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience none $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH2
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 128 -c aes-cbc-essiv:sha256 --resilience checksum $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH2
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON --sector-size 4096 || fail
+ check_hash $PWD1 $HASH2
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 256 -c twofish-cbc-essiv:sha256 --resilience journal --sector-size 2048 $FAST_PBKDF_ARGON || fail
+ check_hash $PWD1 $HASH2
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience none $FAST_PBKDF_ARGON --sector-size 1024 || fail
+ check_hash $PWD1 $HASH2
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 128 -c aes-cbc-essiv:sha256 --resilience checksum --sector-size 512 $FAST_PBKDF_ARGON || fail
+ check_hash $PWD1 $HASH2
+fi
+echo "[OK]"
+
+echo "[2] Encryption with data shift"
+# well, movin' zeroes :-)
+preparebig 64
+wipe_dev $DEV
+check_hash_dev $DEV $HASH4
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt -c aes-cbc-essiv:sha256 -s 128 --reduce-device-size 8M -q $FAST_PBKDF_ARGON || fail
+check_hash_head $PWD1 $((56*1024*2)) $HASH5
+wipe_dev $DEV
+check_hash_dev $DEV $HASH4
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt -c twofish-cbc-essiv:sha256 -s 128 --reduce-device-size 21M -q $FAST_PBKDF_ARGON || fail
+check_hash_head $PWD1 $((43*1024*2)) $HASH6
+wipe_dev $DEV
+# offset 21504 equals 10,5MiBs, equals --reduce-device-size 21M from test above (30M is ignored here, we'll reduce it to 21M in cryptsetup anyway)
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt -c twofish-cbc-essiv:sha256 -s 128 --offset 21504 --reduce-device-size 30M -q $FAST_PBKDF_ARGON > /dev/null || fail
+check_hash_head $PWD1 $((43*1024*2)) $HASH6
+wipe_dev $DEV
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --reduce-device-size 33M -q $FAST_PBKDF_ARGON || fail
+check_hash_head $PWD1 $((31*1024*2)) $HASH7
+wipe_dev $DEV
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --reduce-device-size 64M -q $FAST_PBKDF_ARGON > /dev/null 2>&1 && fail
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --reduce-device-size 8M --init-only -q $FAST_PBKDF_ARGON $DEV || fail
+resize_file $DEVBIG -512
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV 2> /dev/null && fail
+resize_file $DEVBIG 512
+wipe_dev $DEV
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt -c aes-cbc-essiv:sha256 -s 128 --offset 32760 --reduce-device-size 8M -q $FAST_PBKDF_ARGON --init-only >/dev/null 2>&1 && fail
+# data offset at 21MiB
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --header $IMG_HDR --offset 43008 --reduce-device-size 21M -q $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH6 $IMG_HDR
+$CRYPTSETUP luksHeaderRestore --header-backup-file $IMG_HDR $DEV -q || fail
+check_hash $PWD1 $HASH6
+
+# Device activation after encryption initialization
+wipe_dev $DEV
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --init-only -c aes-cbc-essiv:sha256 -s 128 -S11 --reduce-device-size 8M -q $FAST_PBKDF_ARGON $DEV_NAME >/dev/null || fail
+$CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 || fail
+check_hash_dev /dev/mapper/$DEV_NAME $HASH5
+echo $PWD1 | $CRYPTSETUP reencrypt --resume-only $DEV -q || fail
+check_hash_dev /dev/mapper/$DEV_NAME $HASH5
+
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt -c aes-cbc-essiv:sha256 -s 128 --reduce-device-size 8M -q $FAST_PBKDF_ARGON $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP close $DEV_NAME
+check_hash_head $PWD1 $((56*1024*2)) $HASH5
+
+# Device activation using key file
+wipe_dev $DEV
+echo -n $PWD1 > $KEY1
+$CRYPTSETUP reencrypt $DEV --encrypt --init-only -c aes-cbc-essiv:sha256 -s 128 --reduce-device-size 8M --key-file $KEY1 -q $FAST_PBKDF_ARGON $DEV_NAME >/dev/null || fail
+$CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 || fail
+$CRYPTSETUP close $DEV_NAME
+echo $PWD1 | $CRYPTSETUP open $DEV --test-passphrase || fail
+
+echo "[3] Encryption with detached header"
+preparebig 256
+wipe_dev $DEV
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt -c aes-cbc-essiv:sha256 -s 128 --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+check_hash $PWD1 $HASH3 $IMG_HDR
+wipe_dev $DEV
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --resilience journal --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+check_hash $PWD1 $HASH3 $IMG_HDR
+wipe_dev $DEV
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt -c twofish-cbc-essiv:sha256 -s 128 --resilience none --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+check_hash $PWD1 $HASH3 $IMG_HDR
+wipe_dev $DEV
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt -c serpent-xts-plain --resilience checksum --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+check_hash $PWD1 $HASH3 $IMG_HDR
+
+# Device activation after encryption initialization
+wipe_dev $DEV
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --init-only -c aes-cbc-essiv:sha256 -s 128 --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV $DEV_NAME >/dev/null || fail
+$CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 || fail
+check_hash_dev /dev/mapper/$DEV_NAME $HASH3
+echo $PWD1 | $CRYPTSETUP reencrypt --resume-only --header $IMG_HDR --active-name $DEV_NAME -q || fail
+check_hash_dev /dev/mapper/$DEV_NAME $HASH3
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt -c aes-cbc-essiv:sha256 -s 128 --reduce-device-size 8M -q $FAST_PBKDF_ARGON $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP close $DEV_NAME
+check_hash $PWD1 $HASH3 $IMG_HDR
+
+# Device activation using key file
+wipe_dev $DEV
+echo -n $PWD1 > $KEY1
+$CRYPTSETUP reencrypt $DEV --encrypt --init-only -c aes-cbc-essiv:sha256 -s 128 --header $IMG_HDR --key-file $KEY1 -q $FAST_PBKDF_ARGON $DEV_NAME >/dev/null || fail
+$CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 || fail
+$CRYPTSETUP close $DEV_NAME
+echo $PWD1 | $CRYPTSETUP open --header $IMG_HDR $DEV --test-passphrase || fail
+
+echo "[4] Reencryption with detached header"
+wipe $PWD1 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt -c aes-cbc-essiv:sha256 -s 128 --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+check_hash $PWD1 $HASH3 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt --resilience journal --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+check_hash $PWD1 $HASH3 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt -c twofish-cbc-essiv:sha256 -s 128 --resilience none --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+check_hash $PWD1 $HASH3 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt -c serpent-xts-plain --resilience checksum --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+check_hash $PWD1 $HASH3 $IMG_HDR
+# trivial check for detached header misuse
+dd if=/dev/zero of=$IMG bs=4k count=1 >/dev/null 2>&1
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 -c aes-cbc-essiv:sha256 -s 128 --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+echo $PWD1 | $CRYPTSETUP open $IMG $DEV_NAME --header $IMG_HDR || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME2 --header $IMG_HDR || fail
+echo $PWD1 | $CRYPTSETUP reencrypt --active-name $DEV_NAME --header $IMG_HDR -q || fail
+# key description mismatch in active device
+echo $PWD1 | $CRYPTSETUP reencrypt --active-name $DEV_NAME2 --header $IMG_HDR >/dev/null 2>&1 && fail
+# also check it can abort initialization in this case
+$CRYPTSETUP luksDump $IMG_HDR | grep -q "online-reencrypt" && fail
+$CRYPTSETUP close $DEV_NAME || fail
+$CRYPTSETUP close $DEV_NAME2 || fail
+
+echo "[5] Decryption with detached header"
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 -c aes-cbc-essiv:sha256 -s 128 --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt -q --decrypt --header $IMG_HDR $DEV || fail
+check_hash_dev $DEV $HASH3
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt -q --decrypt --resilience journal --header $IMG_HDR $DEV || fail
+check_hash_dev $DEV $HASH3
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 -c twofish-cbc-essiv:sha256 -s 128 --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt -q --decrypt --resilience none --header $IMG_HDR $DEV || fail
+check_hash_dev $DEV $HASH3
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 -c serpent-xts-plain --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt -q --decrypt --resilience checksum --header $IMG_HDR $DEV || fail
+check_hash_dev $DEV $HASH3
+
+# check deferred remove works as expected after decryption
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 -c serpent-xts-plain --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+open_crypt $PWD1 $IMG_HDR
+dmsetup create $DEV_NAME2 --table "0 1 linear /dev/mapper/$DEV_NAME 0" || fail
+echo $PWD1 | $CRYPTSETUP reencrypt -q --decrypt --resilience checksum --header $IMG_HDR --active-name $DEV_NAME || fail
+$CRYPTSETUP status $DEV_NAME >/dev/null || fail
+dmsetup remove --retry $DEV_NAME2
+$CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 && fail
+
+# check tool can block some funny user ideas
+preparebig 64
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 -c serpent-xts-plain -q $FAST_PBKDF_ARGON $DEV || fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt $DEV -q 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt $DEV --header $DEV -q 2>/dev/null && fail
+open_crypt $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt --active-name $DEV_NAME -q 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt --active-name $DEV_NAME --header $DEV -q 2>/dev/null && fail
+$CRYPTSETUP status $DEV_NAME | grep -q "reencryption: in-progress" && fail
+$CRYPTSETUP close $DEV_NAME
+
+if ! dm_delay_features; then
+ echo "dm-delay target is missing, skipping recovery tests."
+ remove_mapping
+ exit 0
+fi
+
+echo "[6] Reencryption recovery"
+# (check opt-io size optimization in reencryption code does not affect recovery)
+# device with opt-io size 32k
+prepare_linear_dev 32 opt_blks=64 $OPT_XFERLEN_EXP
+OFFSET=8192
+
+echo "sector size 512->512"
+
+get_error_offsets 32 $OFFSET
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+check_hash $PWD1 $HASH1
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+reencrypt_recover 512 checksum $HASH1
+reencrypt_recover 512 journal $HASH1
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 512->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover 4096 checksum $HASH1
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+ reencrypt_recover 4096 journal $HASH1
+
+ echo "sector size 4096->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 --sector-size 4096 -c aes-cbc-essiv:sha256 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover 4096 checksum $HASH1
+ reencrypt_recover 4096 journal $HASH1
+fi
+
+echo "[7] Reencryption recovery (online i/o error)"
+
+echo "sector size 512->512"
+
+get_error_offsets 32 $OFFSET
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+check_hash $PWD1 $HASH1
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+reencrypt_recover_online 512 checksum $HASH1
+reencrypt_recover_online 512 journal $HASH1
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 512->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover_online 4096 checksum $HASH1
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+ reencrypt_recover_online 4096 journal $HASH1
+
+ echo "sector size 4096->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 --sector-size 4096 -c aes-cbc-essiv:sha256 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover_online 4096 checksum $HASH1
+ reencrypt_recover_online 4096 journal $HASH1
+fi
+
+echo "[8] Reencryption with detached header recovery"
+prepare_linear_dev 31 opt_blks=64 $OPT_XFERLEN_EXP
+
+echo "sector size 512->512"
+
+get_error_offsets 31 0
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1 $IMG_HDR
+check_hash $PWD1 $HASH7 $IMG_HDR
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+reencrypt_recover 512 checksum $HASH7 $IMG_HDR
+reencrypt_recover 512 journal $HASH7 $IMG_HDR
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 512->4096"
+
+ get_error_offsets 31 0 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1 $IMG_HDR
+ check_hash $PWD1 $HASH7 $IMG_HDR
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover 4096 checksum $HASH7 $IMG_HDR
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1 $IMG_HDR
+ check_hash $PWD1 $HASH7 $IMG_HDR
+ reencrypt_recover 4096 journal $HASH7 $IMG_HDR
+
+ echo "sector size 4096->4096"
+
+ get_error_offsets 31 0 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 4096 --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1 $IMG_HDR
+ check_hash $PWD1 $HASH7 $IMG_HDR
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover 4096 checksum $HASH7 $IMG_HDR
+ reencrypt_recover 4096 journal $HASH7 $IMG_HDR
+fi
+
+echo "[9] Reencryption with detached header recovery (online i/o error)"
+
+echo "sector size 512->512"
+
+get_error_offsets 31 0
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1 $IMG_HDR
+check_hash $PWD1 $HASH7 $IMG_HDR
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+reencrypt_recover_online 512 checksum $HASH7 $IMG_HDR
+reencrypt_recover_online 512 journal $HASH7 $IMG_HDR
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 512->4096"
+
+ get_error_offsets 31 0 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1 $IMG_HDR
+ check_hash $PWD1 $HASH7 $IMG_HDR
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover_online 4096 checksum $HASH7 $IMG_HDR
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1 $IMG_HDR
+ check_hash $PWD1 $HASH7 $IMG_HDR
+ reencrypt_recover_online 4096 journal $HASH7 $IMG_HDR
+
+ echo "sector size 4096->4096"
+
+ get_error_offsets 31 0 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 4096 --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1 $IMG_HDR
+ check_hash $PWD1 $HASH7 $IMG_HDR
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover_online 4096 checksum $HASH7 $IMG_HDR
+ reencrypt_recover_online 4096 journal $HASH7 $IMG_HDR
+fi
+
+echo "[10] Encryption recovery"
+prepare_linear_dev 64
+OFFSET=$((2*1024*2))
+
+echo "sector size 512"
+
+get_error_offsets 64 $OFFSET 512 $((62*1024*2))
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+encrypt_recover 512 4M $HASH8 $((60*1024*2)) $HASH4
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 4096"
+
+ get_error_offsets 64 $OFFSET 4096 $((62*1024*2))
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ encrypt_recover 4096 4M $HASH8 $((60*1024*2)) $HASH4
+fi
+
+echo "[11] Encryption recovery (online i/o error)"
+
+echo "sector size 512"
+
+get_error_offsets 64 $OFFSET 512 $((62*1024*2))
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+encrypt_recover_online 512 4M $HASH8 $((60*1024*2)) $HASH4
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 4096"
+
+ get_error_offsets 64 $OFFSET 4096 $((62*1024*2))
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ encrypt_recover_online 4096 4M $HASH8 $((60*1024*2)) $HASH4
+fi
+
+echo "[12] Encryption with detached header recovery"
+prepare_linear_dev 31 opt_blks=64 $OPT_XFERLEN_EXP
+
+get_error_offsets 31 0
+
+echo "sector size 512"
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+encrypt_recover_detached 512 checksum $HASH7 $IMG_HDR
+encrypt_recover_detached 512 journal $HASH7 $IMG_HDR
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ get_error_offsets 31 0 4096
+
+ echo "sector size 4096"
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ encrypt_recover_detached 4096 checksum $HASH7 $IMG_HDR
+ encrypt_recover_detached 4096 journal $HASH7 $IMG_HDR
+fi
+
+echo "[13] Encryption with detached header recovery (online i/o error)"
+
+get_error_offsets 31 0
+
+echo "sector size 512"
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+encrypt_recover_detached_online 512 checksum $HASH7 $IMG_HDR
+encrypt_recover_detached_online 512 journal $HASH7 $IMG_HDR
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ get_error_offsets 31 0 4096
+
+ echo "sector size 4096"
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ encrypt_recover_detached_online 4096 checksum $HASH7 $IMG_HDR
+ encrypt_recover_detached_online 4096 journal $HASH7 $IMG_HDR
+fi
+
+echo "[14] Decryption with detached header recovery"
+
+echo "sector size 512"
+
+# TODO: What should decryption do when it finishes decryption during recovery (with open)
+get_error_offsets 31 2049
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+decrypt_recover_detached 512 journal $HASH7 $IMG_HDR
+decrypt_recover_detached 512 checksum $HASH7 $IMG_HDR
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 4096"
+
+ # TODO: What should decryption do when it finishes decryption during recovery (with open)
+ get_error_offsets 31 2048 4096
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ decrypt_recover_detached 4096 checksum $HASH7 $IMG_HDR
+ decrypt_recover_detached 4096 journal $HASH7 $IMG_HDR
+fi
+
+echo "[15] Decryption with detached header recovery (online i/o error)"
+
+echo "sector size 512"
+
+# TODO: What should decryption do when it finishes decryption during recovery (with open)
+get_error_offsets 31 2049
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+decrypt_recover_detached_online 512 journal $HASH7 $IMG_HDR
+decrypt_recover_detached_online 512 checksum $HASH7 $IMG_HDR
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 4096"
+
+ # TODO: What should decryption do when it finishes decryption during recovery (with open)
+ get_error_offsets 31 2048 4096
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ decrypt_recover_detached_online 4096 checksum $HASH7 $IMG_HDR
+ decrypt_recover_detached_online 4096 journal $HASH7 $IMG_HDR
+fi
+
+echo "[16] Offline reencryption with fixed device size."
+preparebig 68
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --offset 16384 $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+check_hash $PWD1 $HASH8
+
+for test_ss in $TEST_SECTORS; do
+printf "sector size %4s: " $test_ss
+for test_res in checksum journal none; do
+ echo -n "[$test_res]"
+ reencrypt_offline_fixed_size $test_ss 2048 $HASH2 $test_res $((60*1024*2)) $HASH8
+ reencrypt_offline_fixed_size $test_ss $((28*1024*2)) $HASH1 $test_res $((60*1024*2)) $HASH8
+ reencrypt_offline_fixed_size $test_ss $((31*1024*2)) $HASH7 $test_res $((60*1024*2)) $HASH8
+ echo -n "[OK]"
+done
+echo ""
+done
+
+echo "[17] Online reencryption with fixed device size."
+for test_ss in $TEST_SECTORS; do
+printf "sector size %4s: " $test_ss
+for test_res in checksum journal none; do
+ echo -n "[$test_res]"
+ reencrypt_online_fixed_size $test_ss 2048 $HASH2 $test_res $((60*1024*2)) $HASH8
+ reencrypt_online_fixed_size $test_ss $((28*1024*2)) $HASH1 $test_res $((60*1024*2)) $HASH8
+ reencrypt_online_fixed_size $test_ss $((31*1024*2)) $HASH7 $test_res $((60*1024*2)) $HASH8
+ echo -n "[OK]"
+done
+echo ""
+done
+
+echo "[18] Offline reencryption with fixed device size (detached header)."
+preparebig 60
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1 $IMG_HDR
+check_hash $PWD1 $HASH8 $IMG_HDR
+
+for test_ss in $TEST_SECTORS; do
+printf "sector size %4s: " $test_ss
+for test_res in checksum journal none; do
+ echo -n "[$test_res]"
+ reencrypt_offline_fixed_size $test_ss 2048 $HASH2 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ reencrypt_offline_fixed_size $test_ss $((28*1024*2)) $HASH1 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ reencrypt_offline_fixed_size $test_ss $((31*1024*2)) $HASH7 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ echo -n "[OK]"
+done
+echo ""
+done
+
+echo "[19] Online reencryption with fixed device size (detached header)."
+for test_ss in $TEST_SECTORS; do
+printf "sector size %4s: " $test_ss
+for test_res in checksum journal none; do
+ echo -n "[$test_res]"
+ reencrypt_online_fixed_size $test_ss 2048 $HASH2 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ reencrypt_online_fixed_size $test_ss $((28*1024*2)) $HASH1 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ reencrypt_online_fixed_size $test_ss $((31*1024*2)) $HASH7 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ echo -n "[OK]"
+done
+echo ""
+done
+
+echo "[20] Offline encryption with fixed device size (detached header)."
+for test_ss in $TEST_SECTORS; do
+printf "sector size %4s: " $test_ss
+for test_res in checksum journal none; do
+ echo -n "[$test_res]"
+ encrypt_offline_fixed_size $test_ss 2048 $HASH2 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ encrypt_offline_fixed_size $test_ss $((28*1024*2)) $HASH1 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ encrypt_offline_fixed_size $test_ss $((31*1024*2)) $HASH7 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ echo -n "[OK]"
+done
+echo ""
+done
+
+echo "[21] Offline decryption with fixed device size (detached header)."
+prepare_linear_dev 60
+for test_ss in $TEST_SECTORS; do
+printf "sector size %4s: " $test_ss
+for test_res in checksum journal none; do
+ echo -n "[$test_res]"
+ decrypt_offline_fixed_size $test_ss 2048 $HASH2 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ decrypt_offline_fixed_size $test_ss $((28*1024*2)) $HASH1 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ decrypt_offline_fixed_size $test_ss $((31*1024*2)) $HASH7 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ echo -n "[OK]"
+done
+echo ""
+done
+
+echo "[22] Multi-keyslot device reencryption"
+prepare dev_size_mb=17
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --offset 32768 $FAST_PBKDF_ARGON $DEV || fail
+echo -e "$PWD1\n$PWD2" | $CRYPTSETUP -q luksAddKey $FAST_PBKDF2 $DEV || fail
+echo -e "$PWD1\n$PWD3" | $CRYPTSETUP -q luksAddKey $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+check_hash $PWD1 $HASH2
+
+echo -e "$PWD1\n$PWD2\n$PWD3" | $CRYPTSETUP reencrypt $DEV -q || fail
+check_hash $PWD1 $HASH2
+check_hash $PWD2 $HASH2
+check_hash $PWD3 $HASH2
+
+# check at least pbkdf type is preserved
+$CRYPTSETUP luksDump $DEV | grep -e "3: luks2" -A5 | grep -q "argon2" || fail
+$CRYPTSETUP luksDump $DEV | grep -e "4: luks2" -A5 | grep -q "pbkdf2" || fail
+$CRYPTSETUP luksDump $DEV | grep -e "5: luks2" -A5 | grep -q "argon2" || fail
+
+echo $PWD1 | $CRYPTSETUP -q luksAddKey $FAST_PBKDF2 $DEV $KEY1 || fail
+
+# with more keyslots, specific has to be selected
+$CRYPTSETUP reencrypt $DEV -d $KEY1 -q 2>/dev/null && fail
+$CRYPTSETUP reencrypt $DEV -d $KEY1 -q -S0 || fail
+open_crypt
+check_hash_dev /dev/mapper/$DEV_NAME $HASH2
+$CRYPTSETUP close $DEV_NAME
+
+# there should be single keyslot now
+$CRYPTSETUP reencrypt $DEV -d $KEY1 -q || fail
+echo $PWD1 | $CRYPTSETUP -q luksAddKey $FAST_PBKDF2 $DEV -S1 -d $KEY1 || fail
+
+echo $PWD3 | $CRYPTSETUP -q luksAddKey $FAST_PBKDF2 $DEV -S2 --unbound --key-size 32 || fail
+echo $PWD3 | $CRYPTSETUP -q luksAddKey $FAST_PBKDF2 $DEV -S22 --unbound --key-size 32 || fail
+echo $PWD3 | $CRYPTSETUP -q luksAddKey $FAST_PBKDF2 $DEV -S23 --unbound --key-size 32 || fail
+
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -S1 -q || fail
+$CRYPTSETUP open --test-passphrase -d $KEY1 $DEV 2>/dev/null && fail
+echo $PWD3 | $CRYPTSETUP open --test-passphrase -S2 $DEV || fail
+echo $PWD3 | $CRYPTSETUP open --test-passphrase -S22 $DEV || fail
+check_hash $PWD1 $HASH2
+
+# fill 31 keyslots
+COUNT=27
+while [ $COUNT -gt 0 ]; do
+ echo -e "$PWD1\n$PWD1" | $CRYPTSETUP luksAddKey $DEV -q $FAST_PBKDF_ARGON || fail
+ COUNT=$((COUNT-1))
+done
+
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -S0 -q 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksKillSlot $DEV 30 || fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -S0 || fail
+
+COUNT=14
+while [ $COUNT -gt 0 ]; do
+ echo -e "$PWD1\n$PWD1" | $CRYPTSETUP luksAddKey $DEV -q $FAST_PBKDF_ARGON || fail
+ COUNT=$((COUNT-1))
+done
+
+echo -e "$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1" | $CRYPTSETUP reencrypt $DEV -q 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksKillSlot $DEV 1 || fail
+# one wrong passphrase
+echo -e "$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD2" | $CRYPTSETUP reencrypt $DEV -q 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --resume-only -q 2>/dev/null && fail
+echo -e "$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1" | $CRYPTSETUP reencrypt $DEV -q || fail
+
+echo "[23] Reencryption with specified new volume key"
+prepare dev_size_mb=32
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 256 -c aes-cbc-essiv:sha256 --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
+echo -e "$PWD1\n$PWD3" | $CRYPTSETUP -q luksAddKey $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -S0 $FAST_PBKDF_ARGON --master-key-file $VKEY1 -s 128 || fail
+check_hash $PWD1 $HASH1
+$CRYPTSETUP luksErase -q $DEV || fail
+echo $PWD1 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_ARGON --master-key-file $VKEY1 -s 128 $DEV || fail
+check_hash $PWD1 $HASH1
+
+echo "[24] Reencryption with initial cipher_null"
+# aka custom encryption
+prepare dev_size_mb=32
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 -c cipher_null-ecb --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -c aes-xts-plain64 -q $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+
+# online
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 -c cipher_null-ecb --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -c aes-xts-plain64 -q $FAST_PBKDF_ARGON || fail
+check_hash_dev /dev/mapper/$DEV_NAME $HASH1
+if [ $HAVE_KEYRING -gt 0 ]; then
+ $CRYPTSETUP status $DEV_NAME | grep -q "key location: keyring" || fail
+fi
+$CRYPTSETUP close $DEV_NAME
+
+# simulate LUKS2 device with cipher_null in both keyslot and segment (it can be created only by up conversion from LUKS1)
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 -s 128 -c cipher_null-ecb --offset 8192 $FAST_PBKDF2 $DEV || fail
+$CRYPTSETUP convert -q --type luks2 $DEV || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON >/dev/null || fail
+check_hash $PWD1 $HASH1
+# both keyslot and segment cipher must not be null after reencryption with default params
+$CRYPTSETUP luksDump $DEV | grep -q "cipher_null" && fail
+
+# multistep reencryption with initial cipher_null
+preparebig 64
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 $DEV -c null --offset 16384 -q $FAST_PBKDF_ARGON || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME
+wipe_dev /dev/mapper/$DEV_NAME
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --hotzone-size 1M --resilience none -q $FAST_PBKDF_ARGON >/dev/null || fail
+$CRYPTSETUP close $DEV_NAME
+check_hash $PWD1 $HASH5
+
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 $DEV -c null --offset 16384 -q $FAST_PBKDF_ARGON || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --hotzone-size 1M --resilience none -q $FAST_PBKDF_ARGON >/dev/null || fail
+check_hash $PWD1 $HASH5
+
+echo "[25] Reencryption recovery with cipher_null"
+# (check opt-io size optimization in reencryption code does not affect recovery)
+# device with opt-io size 32k
+prepare_linear_dev 32 opt_blks=64 $OPT_XFERLEN_EXP
+OFFSET=8192
+
+echo "sector size 512->512"
+
+get_error_offsets 32 $OFFSET
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+check_hash $PWD1 $HASH1
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+reencrypt_recover 512 checksum $HASH1
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+reencrypt_recover 512 journal $HASH1
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 512->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover 4096 checksum $HASH1
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+ reencrypt_recover 4096 journal $HASH1
+
+ echo "sector size 4096->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 4096 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover 4096 checksum $HASH1
+ reencrypt_recover 4096 journal $HASH1
+fi
+
+echo "[26] Reencryption recovery with cipher_null (online i/o error)"
+
+echo "sector size 512->512"
+
+get_error_offsets 32 $OFFSET
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 -c null --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+check_hash $PWD1 $HASH1
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+reencrypt_recover_online 512 checksum $HASH1
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 -c null --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+reencrypt_recover_online 512 journal $HASH1
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 512->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover_online 4096 checksum $HASH1
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+ reencrypt_recover_online 4096 journal $HASH1
+
+ echo "sector size 4096->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 4096 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ check_hash $PWD1 $HASH1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover_online 4096 checksum $HASH1
+ reencrypt_recover_online 4096 journal $HASH1
+fi
+
+remove_mapping
+exit 0