mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
Fix bug in reencryption parameters verification.
This commit is contained in:
committed by
Milan Broz
parent
8270b72bfc
commit
25b877a403
@@ -2640,26 +2640,32 @@ static int reencrypt_verify_datashift_params(struct crypt_device *cd,
|
||||
|
||||
static int reencrypt_verify_resilience_params(struct crypt_device *cd,
|
||||
const struct crypt_params_reencrypt *params,
|
||||
uint32_t sector_size)
|
||||
uint32_t sector_size, bool move_first_segment)
|
||||
{
|
||||
int r;
|
||||
|
||||
/* no change requested */
|
||||
if (!params || !params->resilience)
|
||||
return 0;
|
||||
|
||||
if (!strcmp(params->resilience, "journal"))
|
||||
return 0;
|
||||
return (params->data_shift || move_first_segment) ? -EINVAL : 0;
|
||||
else if (!strcmp(params->resilience, "none"))
|
||||
return 0;
|
||||
return (params->data_shift || move_first_segment) ? -EINVAL : 0;
|
||||
else if (!strcmp(params->resilience, "datashift"))
|
||||
return reencrypt_verify_datashift_params(cd, params, sector_size);
|
||||
else if (!strcmp(params->resilience, "checksum"))
|
||||
else if (!strcmp(params->resilience, "checksum")) {
|
||||
if (params->data_shift || move_first_segment)
|
||||
return -EINVAL;
|
||||
return reencrypt_verify_checksum_params(cd, params);
|
||||
else if (!strcmp(params->resilience, "datashift-checksum")) {
|
||||
r = reencrypt_verify_datashift_params(cd, params, sector_size);
|
||||
return r ?: reencrypt_verify_checksum_params(cd, params);
|
||||
} else if (!strcmp(params->resilience, "datashift-journal"))
|
||||
} else if (!strcmp(params->resilience, "datashift-checksum")) {
|
||||
if (!move_first_segment ||
|
||||
reencrypt_verify_datashift_params(cd, params, sector_size))
|
||||
return -EINVAL;
|
||||
return reencrypt_verify_checksum_params(cd, params);
|
||||
} else if (!strcmp(params->resilience, "datashift-journal")) {
|
||||
if (!move_first_segment)
|
||||
return -EINVAL;
|
||||
return reencrypt_verify_datashift_params(cd, params, sector_size);
|
||||
}
|
||||
|
||||
log_err(cd, _("Unsupported resilience mode %s"), params->resilience);
|
||||
return -EINVAL;
|
||||
@@ -2742,6 +2748,8 @@ static int reencrypt_decrypt_with_datashift_init(struct crypt_device *cd,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
log_dbg(cd, "Initializing decryption with datashift.");
|
||||
|
||||
data_shift = params->data_shift << SECTOR_SHIFT;
|
||||
|
||||
/*
|
||||
@@ -2774,9 +2782,11 @@ static int reencrypt_decrypt_with_datashift_init(struct crypt_device *cd,
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = reencrypt_verify_resilience_params(cd, params, sector_size);
|
||||
if (r < 0)
|
||||
r = reencrypt_verify_resilience_params(cd, params, sector_size, true);
|
||||
if (r < 0) {
|
||||
log_err(cd, _("Invalid reencryption resilience parameters."));
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = LUKS2_keyslot_reencrypt_allocate(cd, hdr, reencrypt_keyslot,
|
||||
params, reencrypt_get_alignment(cd, hdr));
|
||||
@@ -3039,7 +3049,7 @@ static int reencrypt_init(struct crypt_device *cd,
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = reencrypt_verify_resilience_params(cd, params, check_sector_size);
|
||||
r = reencrypt_verify_resilience_params(cd, params, check_sector_size, move_first_segment);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
@@ -3371,12 +3381,12 @@ static int reencrypt_load_by_passphrase(struct crypt_device *cd,
|
||||
|
||||
log_dbg(cd, "Loading LUKS2 reencryption context.");
|
||||
|
||||
|
||||
old_sector_size = reencrypt_get_sector_size_old(hdr);
|
||||
new_sector_size = reencrypt_get_sector_size_new(hdr);
|
||||
sector_size = new_sector_size > old_sector_size ? new_sector_size : old_sector_size;
|
||||
|
||||
r = reencrypt_verify_resilience_params(cd, params, sector_size);
|
||||
r = reencrypt_verify_resilience_params(cd, params, sector_size,
|
||||
LUKS2_get_segment_id_by_flag(hdr, "backup-moved-segment") >= 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -4641,7 +4641,86 @@ static void Luks2Reencryption(void)
|
||||
OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
|
||||
EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
|
||||
CRYPT_FREE(cd);
|
||||
remove(BACKUP_FILE);
|
||||
|
||||
/* remove error mapping */
|
||||
OK_(dmdevice_error_io(L_DEVICE_OK, DMDIR L_DEVICE_OK, DEVICE_ERROR, 0, 0, 8, ERR_REMOVE));
|
||||
|
||||
/* test various bogus reencryption resilience parameters */
|
||||
rparams = (struct crypt_params_reencrypt) {
|
||||
.mode = CRYPT_REENCRYPT_DECRYPT,
|
||||
.direction = CRYPT_REENCRYPT_FORWARD,
|
||||
.resilience = "checksum", /* should have been datashift-checksum */
|
||||
.hash = "sha256",
|
||||
.data_shift = r_header_size,
|
||||
.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY | CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT
|
||||
};
|
||||
|
||||
OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
|
||||
OK_(set_fast_pbkdf(cd));
|
||||
OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "xts-plain64", NULL, NULL, 64, NULL));
|
||||
EQ_(0, crypt_keyslot_add_by_volume_key(cd, 0, NULL, 64, PASSPHRASE, strlen(PASSPHRASE)));
|
||||
OK_(crypt_header_backup(cd, CRYPT_LUKS2, BACKUP_FILE));
|
||||
CRYPT_FREE(cd);
|
||||
|
||||
OK_(chmod(BACKUP_FILE, S_IRUSR|S_IWUSR));
|
||||
OK_(crypt_init_data_device(&cd, BACKUP_FILE, DMDIR L_DEVICE_OK));
|
||||
OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
|
||||
|
||||
/* decryption on device with data offset and no datashift subvariant mode */
|
||||
FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
|
||||
EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
|
||||
|
||||
rparams.resilience = "journal"; /* should have been datashift-journal */
|
||||
FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
|
||||
EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
|
||||
|
||||
rparams = (struct crypt_params_reencrypt) {
|
||||
.mode = CRYPT_REENCRYPT_DECRYPT,
|
||||
.direction = CRYPT_REENCRYPT_FORWARD,
|
||||
.resilience = "datashift-checksum",
|
||||
.hash = "sha256",
|
||||
.data_shift = 0, /* must be non zero */
|
||||
.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY | CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT
|
||||
};
|
||||
|
||||
/* datashift = 0 */
|
||||
FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
|
||||
EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
|
||||
|
||||
rparams.resilience = "datashift-journal";
|
||||
FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
|
||||
EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
|
||||
|
||||
rparams.resilience = "datashift"; /* datashift only is not supported in decryption mode with moved segment */
|
||||
FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
|
||||
EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
|
||||
|
||||
CRYPT_FREE(cd);
|
||||
|
||||
OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
|
||||
OK_(set_fast_pbkdf(cd));
|
||||
OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, ¶ms2));
|
||||
EQ_(crypt_keyslot_add_by_volume_key(cd, 21, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 21);
|
||||
|
||||
rparams = (struct crypt_params_reencrypt) {
|
||||
.mode = CRYPT_REENCRYPT_REENCRYPT,
|
||||
.direction = CRYPT_REENCRYPT_FORWARD,
|
||||
.resilience = "datashift-checksum",
|
||||
.hash = "sha256",
|
||||
.data_shift = r_header_size,
|
||||
.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY
|
||||
};
|
||||
|
||||
/* regular reencryption must not accept datashift subvariants */
|
||||
FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
|
||||
EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
|
||||
|
||||
rparams.resilience = "datashift-journal";
|
||||
FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
|
||||
EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
|
||||
|
||||
CRYPT_FREE(cd);
|
||||
_cleanup_dmdevices();
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user