mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
Add strict compare volume key comparison for non-LUKS2 devices.
[Modified by Ondrej Kozina]
This commit is contained in:
113
lib/setup.c
113
lib/setup.c
@@ -3173,6 +3173,38 @@ int crypt_repair(struct crypt_device *cd,
|
||||
|
||||
/* compare volume keys */
|
||||
static int _compare_volume_keys(struct volume_key *svk, struct volume_key *tvk)
|
||||
{
|
||||
if (svk == tvk)
|
||||
return 0;
|
||||
|
||||
if (!svk || !tvk)
|
||||
return 1;
|
||||
|
||||
if (crypt_volume_key_length(svk) != crypt_volume_key_length(tvk))
|
||||
return 1;
|
||||
|
||||
/* No switch between keyring and direct key specification */
|
||||
if ((!crypt_volume_key_description(svk) && crypt_volume_key_description(tvk)) ||
|
||||
(crypt_volume_key_description(svk) && !crypt_volume_key_description(tvk)) ||
|
||||
(!crypt_volume_key_is_set(svk) && crypt_volume_key_is_set(tvk)) ||
|
||||
(crypt_volume_key_is_set(svk) && !crypt_volume_key_is_set(tvk)))
|
||||
return 1;
|
||||
|
||||
if (crypt_volume_key_description(svk) &&
|
||||
(crypt_volume_key_kernel_key_type(svk) != crypt_volume_key_kernel_key_type(tvk) ||
|
||||
strcmp(crypt_volume_key_description(svk), crypt_volume_key_description(tvk))))
|
||||
return 1;
|
||||
|
||||
if (crypt_volume_key_is_set(svk) &&
|
||||
crypt_backend_memeq(crypt_volume_key_get_key(svk),
|
||||
crypt_volume_key_get_key(tvk),
|
||||
crypt_volume_key_length(svk)))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _compare_volume_keys_luks2(struct volume_key *svk, struct volume_key *tvk)
|
||||
{
|
||||
if (svk == tvk)
|
||||
return 0;
|
||||
@@ -3258,7 +3290,12 @@ static int _compare_crypt_devices(struct crypt_device *cd,
|
||||
|
||||
if (crypt_volume_key_length(tgt->u.crypt.vk) == 0 && crypt_is_cipher_null(tgt->u.crypt.cipher))
|
||||
log_dbg(cd, "Existing device uses cipher null. Skipping key comparison.");
|
||||
else if (_compare_volume_keys(src->u.crypt.vk, tgt->u.crypt.vk)) {
|
||||
else if (cd && isLUKS2(cd->type)) {
|
||||
if (_compare_volume_keys_luks2(src->u.crypt.vk, tgt->u.crypt.vk)) {
|
||||
log_dbg(cd, "Keys in LUKS2 context and target device do not match.");
|
||||
goto out;
|
||||
}
|
||||
} else if (_compare_volume_keys(src->u.crypt.vk, tgt->u.crypt.vk)) {
|
||||
log_dbg(cd, "Keys in context and target device do not match.");
|
||||
goto out;
|
||||
}
|
||||
@@ -3392,9 +3429,14 @@ static int _reload_device(struct crypt_device *cd, const char *name,
|
||||
struct crypt_dm_active_device tdmd;
|
||||
struct dm_target *src, *tgt = &tdmd.segment;
|
||||
|
||||
if (!cd || !cd->type || !name || !(sdmd->flags & CRYPT_ACTIVATE_REFRESH))
|
||||
assert(cd);
|
||||
assert(sdmd);
|
||||
|
||||
if (!cd->type || !name || !(sdmd->flags & CRYPT_ACTIVATE_REFRESH))
|
||||
return -EINVAL;
|
||||
|
||||
src = &sdmd->segment;
|
||||
|
||||
r = dm_query_device(cd, name, DM_ACTIVE_DEVICE | DM_ACTIVE_CRYPT_CIPHER |
|
||||
DM_ACTIVE_UUID | DM_ACTIVE_CRYPT_KEYSIZE |
|
||||
DM_ACTIVE_CRYPT_KEY | DM_ACTIVE_INTEGRITY_PARAMS |
|
||||
@@ -3418,28 +3460,24 @@ static int _reload_device(struct crypt_device *cd, const char *name,
|
||||
goto out;
|
||||
}
|
||||
|
||||
src = &sdmd->segment;
|
||||
|
||||
/* Changing read only flag for active device makes no sense */
|
||||
if (tdmd.flags & CRYPT_ACTIVATE_READONLY)
|
||||
sdmd->flags |= CRYPT_ACTIVATE_READONLY;
|
||||
else
|
||||
sdmd->flags &= ~CRYPT_ACTIVATE_READONLY;
|
||||
|
||||
if (tgt->type == DM_CRYPT && sdmd->flags & CRYPT_ACTIVATE_KEYRING_KEY) {
|
||||
r = crypt_volume_key_set_description(tgt->u.crypt.vk,
|
||||
crypt_volume_key_description(src->u.crypt.vk),
|
||||
crypt_volume_key_kernel_key_type(src->u.crypt.vk));
|
||||
if (r)
|
||||
goto out;
|
||||
} else if (tgt->type == DM_CRYPT) {
|
||||
/*
|
||||
* Only LUKS2 allows altering between volume key
|
||||
* passed by hexbyte representation and reference
|
||||
* to kernel keyring service.
|
||||
*
|
||||
* To make it easier pass src key directly after
|
||||
* it was properly verified in crypt_compare_dm_devices
|
||||
* call above.
|
||||
*/
|
||||
if (isLUKS2(cd->type) && tgt->type == DM_CRYPT && src->u.crypt.vk) {
|
||||
crypt_free_volume_key(tgt->u.crypt.vk);
|
||||
tgt->u.crypt.vk = crypt_alloc_volume_key(crypt_volume_key_length(src->u.crypt.vk),
|
||||
crypt_volume_key_get_key(src->u.crypt.vk));
|
||||
if (!tgt->u.crypt.vk) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
tgt->u.crypt.vk = src->u.crypt.vk;
|
||||
}
|
||||
|
||||
if (tgt->type == DM_CRYPT)
|
||||
@@ -3459,6 +3497,10 @@ static int _reload_device(struct crypt_device *cd, const char *name,
|
||||
|
||||
r = dm_reload_device(cd, name, &tdmd, dmflags, 1);
|
||||
out:
|
||||
/* otherwise dm_targets_free would free src key */
|
||||
if (src->u.crypt.vk == tgt->u.crypt.vk)
|
||||
tgt->u.crypt.vk = NULL;
|
||||
|
||||
dm_targets_free(cd, &tdmd);
|
||||
free(CONST_CAST(void*)tdmd.uuid);
|
||||
|
||||
@@ -3478,9 +3520,16 @@ static int _reload_device_with_integrity(struct crypt_device *cd,
|
||||
struct device *data_device = NULL;
|
||||
bool clear = false;
|
||||
|
||||
if (!cd || !cd->type || !name || !iname || !(sdmd->flags & CRYPT_ACTIVATE_REFRESH))
|
||||
assert(cd);
|
||||
assert(sdmd);
|
||||
assert(sdmdi);
|
||||
|
||||
if (!cd->type || !name || !iname || !(sdmd->flags & CRYPT_ACTIVATE_REFRESH))
|
||||
return -EINVAL;
|
||||
|
||||
src = &sdmd->segment;
|
||||
srci = &sdmdi->segment;
|
||||
|
||||
r = dm_query_device(cd, name, DM_ACTIVE_DEVICE | DM_ACTIVE_CRYPT_CIPHER |
|
||||
DM_ACTIVE_UUID | DM_ACTIVE_CRYPT_KEYSIZE |
|
||||
DM_ACTIVE_CRYPT_KEY, &tdmd);
|
||||
@@ -3520,9 +3569,6 @@ static int _reload_device_with_integrity(struct crypt_device *cd,
|
||||
goto out;
|
||||
}
|
||||
|
||||
src = &sdmd->segment;
|
||||
srci = &sdmdi->segment;
|
||||
|
||||
r = device_alloc(cd, &data_device, ipath);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
@@ -3551,21 +3597,13 @@ static int _reload_device_with_integrity(struct crypt_device *cd,
|
||||
else
|
||||
sdmdi->flags &= ~CRYPT_ACTIVATE_READONLY;
|
||||
|
||||
if (sdmd->flags & CRYPT_ACTIVATE_KEYRING_KEY) {
|
||||
r = crypt_volume_key_set_description(tgt->u.crypt.vk,
|
||||
crypt_volume_key_description(src->u.crypt.vk),
|
||||
crypt_volume_key_kernel_key_type(src->u.crypt.vk));
|
||||
if (r)
|
||||
goto out;
|
||||
} else {
|
||||
crypt_free_volume_key(tgt->u.crypt.vk);
|
||||
tgt->u.crypt.vk = crypt_alloc_volume_key(crypt_volume_key_length(src->u.crypt.vk),
|
||||
crypt_volume_key_get_key(src->u.crypt.vk));
|
||||
if (!tgt->u.crypt.vk) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* To make it easier pass src key directly after
|
||||
* it was properly verified in crypt_compare_dm_devices
|
||||
* call above.
|
||||
*/
|
||||
crypt_free_volume_key(tgt->u.crypt.vk);
|
||||
tgt->u.crypt.vk = src->u.crypt.vk;
|
||||
|
||||
r = device_block_adjust(cd, src->data_device, DEV_OK,
|
||||
src->u.crypt.offset, &sdmd->size, NULL);
|
||||
@@ -3631,6 +3669,9 @@ out:
|
||||
dm_resume_device(cd, iname, 0);
|
||||
}
|
||||
|
||||
/* otherwise dm_targets_free would free src key */
|
||||
if (tgt->u.crypt.vk == src->u.crypt.vk)
|
||||
tgt->u.crypt.vk = NULL;
|
||||
dm_targets_free(cd, &tdmd);
|
||||
dm_targets_free(cd, &tdmdi);
|
||||
free(CONST_CAST(void*)tdmdi.uuid);
|
||||
|
||||
Reference in New Issue
Block a user