Do not allow nested encryption in LUKS reencrypt.

Try to avoid accidental nested encryption via
cryptsetup reencrypt --new/--encrypt command.

If detached header or data device is already reported
as LUKS1 or LUKS2 device operation gets aborted.

Fixes: #713.
This commit is contained in:
Ondrej Kozina
2022-03-09 14:58:29 +01:00
committed by Milan Broz
parent 5bd5462a9e
commit 47f31205cf
2 changed files with 76 additions and 33 deletions

View File

@@ -236,12 +236,11 @@ static enum device_status_info load_luks(struct crypt_device **r_cd, const char
static int action_encrypt_luks2(struct crypt_device **cd, const char *data_device, const char *device_name)
{
char *tmp;
const char *type;
int keyslot, r, fd;
uuid_t uuid;
size_t passwordLen;
char *msg, uuid_str[37], header_file[PATH_MAX] = { 0 }, *password = NULL;
char *tmp, uuid_str[37], header_file[PATH_MAX] = { 0 }, *password = NULL;
uint32_t activate_flags = 0;
const struct crypt_params_luks2 luks2_params = {
.sector_size = ARG_UINT32(OPT_SECTOR_SIZE_ID) ?: SECTOR_SIZE
@@ -301,23 +300,6 @@ static int action_encrypt_luks2(struct crypt_device **cd, const char *data_devic
ARG_SET_STR(OPT_UUID_ID, tmp);
}
/* Check the data device is not LUKS device already */
if ((r = crypt_init(cd, data_device)))
return r;
r = crypt_load(*cd, CRYPT_LUKS, NULL);
crypt_free(*cd);
*cd = NULL;
if (!r && !ARG_SET(OPT_BATCH_MODE_ID)) {
r = asprintf(&msg, _("Detected LUKS device on %s. Do you want to encrypt that LUKS device again?"), data_device);
if (r == -1)
return -ENOMEM;
r = yesDialog(msg, _("Operation aborted.\n")) ? 0 : -EINVAL;
free(msg);
if (r < 0)
return r;
}
if (!ARG_SET(OPT_HEADER_ID)) {
r = snprintf(header_file, sizeof(header_file), "LUKS2-temp-%s.new", ARG_STR(OPT_UUID_ID));
if (r < 0 || (size_t)r >= sizeof(header_file))
@@ -1022,33 +1004,75 @@ out:
static int _encrypt(int action_argc, const char **action_argv)
{
enum device_status_info hdr_st, dev_st;
struct stat st;
const char *type = luksType(device_type);
bool luks1_in_reencrypt = false;
struct crypt_device *check_cd = NULL;
dev_st = load_luks(&check_cd, CRYPT_LUKS, NULL, uuid_or_device(action_argv[0]));
crypt_free(check_cd);
check_cd = NULL;
if (dev_st == DEVICE_INVALID)
return -EINVAL;
if (dev_st == DEVICE_LUKS2 || dev_st == DEVICE_LUKS1) {
log_err(_("Device %s is already LUKS device."), uuid_or_device(action_argv[0]));
return -EINVAL;
}
/* explicit request for LUKS2 encryption */
if (ARG_SET(OPT_HEADER_ID)) {
luks1_in_reencrypt = reencrypt_luks1_in_progress(ARG_STR(OPT_HEADER_ID)) == 0;
if (luks1_in_reencrypt && isLUKS2(type)) {
log_err(_("Device %s already in LUKS1 reencryption."), ARG_STR(OPT_HEADER_ID));
if (stat(ARG_STR(OPT_HEADER_ID), &st) < 0 && errno == ENOENT)
hdr_st = DEVICE_NOT_LUKS;
else {
hdr_st = load_luks(&check_cd, CRYPT_LUKS, NULL, ARG_STR(OPT_HEADER_ID));
crypt_free(check_cd);
if (hdr_st == DEVICE_INVALID)
return -EINVAL;
if (hdr_st == DEVICE_LUKS1_UNUSABLE && isLUKS2(type)) {
log_err(_("Device %s is already in LUKS1 reencryption."), ARG_STR(OPT_HEADER_ID));
return -EINVAL;
}
if (hdr_st == DEVICE_LUKS2_REENCRYPT && isLUKS1(type)) {
log_err(_("Device %s is already in LUKS2 reencryption."), ARG_STR(OPT_HEADER_ID));
return -EINVAL;
}
if (hdr_st == DEVICE_LUKS2 || hdr_st == DEVICE_LUKS1) {
log_err(_("Device %s is already LUKS device."), ARG_STR(OPT_HEADER_ID));
return -EINVAL;
}
}
if (dev_st == DEVICE_LUKS2_REENCRYPT || dev_st == DEVICE_LUKS1_UNUSABLE) {
log_err(_("Data device %s is already in LUKS reencryption."), uuid_or_device(action_argv[0]));
return -EINVAL;
}
}
if (!luks1_in_reencrypt)
luks1_in_reencrypt = reencrypt_luks1_in_progress(uuid_or_device(action_argv[0])) == 0;
dev_st = hdr_st;
} else {
if (dev_st == DEVICE_LUKS1_UNUSABLE && isLUKS2(type)) {
log_err(_("Device %s is already in LUKS1 reencryption."), ARG_STR(OPT_HEADER_ID));
return -EINVAL;
}
/* explicit request for LUKS2 encryption */
if (luks1_in_reencrypt && isLUKS2(type)) {
log_err(_("Device %s already in LUKS1 reencryption."), action_argv[0]);
return -EINVAL;
if (dev_st == DEVICE_LUKS2_REENCRYPT && isLUKS1(type)) {
log_err(_("Device %s already in LUKS2 reencryption."), ARG_STR(OPT_HEADER_ID));
return -EINVAL;
}
}
if (!type)
type = crypt_get_default_type();
if (isLUKS1(type) || luks1_in_reencrypt)
if (isLUKS1(type) || dev_st == DEVICE_LUKS1_UNUSABLE) {
return reencrypt_luks1(action_argv[0]);
else if (isLUKS2(type))
} else if (isLUKS2(type) || dev_st == DEVICE_LUKS2_REENCRYPT)
return encrypt_luks2(action_argc, action_argv);
return -EINVAL;

View File

@@ -433,6 +433,8 @@ function encrypt_recover_detached() { # $1 sector size, $2 resilience, $3 digest
echo $PWD1 | $CRYPTSETUP reencrypt $DEV --header $4 --resilience $2 --sector-size $1 -q $FAST_PBKDF_ARGON || fail
check_hash $PWD1 $3 $4
[ -f $4 ] && rm -f $4
echo "[OK]"
}
@@ -463,6 +465,8 @@ function encrypt_recover_detached_online() { # $1 sector size, $2 resilience, $3
$CRYPTSETUP close $DEV_NAME || fail
[ -f $4 ] && rm -f $4
echo "[OK]"
}
@@ -487,6 +491,8 @@ function decrypt_recover_detached() { # $1 sector size, $2 resilience, $3 digest
check_hash_dev $DEV $3
[ -f $4 ] && rm -f $4
echo "[OK]"
}
@@ -517,6 +523,8 @@ function decrypt_recover_detached_online() { # $1 sector size, $2 resilience, $3
$CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 && fail
check_hash_dev $DEV $3
[ -f $4 ] && rm -f $4
echo "[OK]"
}
@@ -565,6 +573,7 @@ function encrypt_offline_fixed_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
[ -f $7 ] && rm -f $7
# try to reencrypt device size + 1 encryption sector size
wipe_dev $DEV
@@ -574,12 +583,15 @@ function encrypt_offline_fixed_size() {
# misaligned reencryption size
if [ $_esz -gt 1 ]; then
[ -f $7 ] && rm -f $7
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
[ -f $7 ] && rm -f $7
}
# sector size (bytes)
@@ -905,14 +917,18 @@ 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
rm -f $IMG_HDR
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
rm -f $IMG_HDR
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
rm -f $IMG_HDR
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
rm -f $IMG_HDR
# Device activation after encryption initialization
wipe_dev $DEV
@@ -924,12 +940,14 @@ 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
rm -f $IMG_HDR
# Device encryption with data offset set in detached header
wipe_dev $DEV
dd if=/dev/urandom of=$DEV bs=512 count=32768 >/dev/null 2>&1
echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --header $IMG_HDR --offset 32768 -q $FAST_PBKDF_ARGON $DEV || fail
check_hash $PWD1 $HASH9 $IMG_HDR
rm -f $IMG_HDR
# Device activation using key file
wipe_dev $DEV
@@ -1616,11 +1634,12 @@ echo $PWD1 | $CRYPTSETUP -q luksFormat -S5 --header $IMG_HDR --type luks2 $FAST_
echo -e "$PWD1\n$PWD1" | $CRYPTSETUP luksAddKey --unbound -s80 -S0 $FAST_PBKDF_ARGON $IMG_HDR || fail
echo $PWD1 | $CRYPTSETUP reencrypt --decrypt --init-only --header $IMG_HDR $DEV || fail
echo $PWD1 | $CRYPTSETUP open --test-passphrase $IMG_HDR || fail
rm -f $IMG_HDR
wipe_dev_head $DEV 1
echo $PWD1 | $CRYPTSETUP reencrypt -q --encrypt --init-only --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
echo $PWD1 | $CRYPTSETUP open --test-passphrase $IMG_HDR || fail
wipe_dev_head $DEV 1
echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --init-only --reduce-device-size 8M $FAST_PBKDF_ARGON $DEV || fail
echo $PWD1 | $CRYPTSETUP open --test-passphrase $DEV || fail