mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-13 11:50:10 +01:00
Refactor LUKS2 device activation (in reencryption).
This commit is contained in:
129
lib/setup.c
129
lib/setup.c
@@ -3696,7 +3696,56 @@ out:
|
|||||||
return r < 0 ? r : keyslot;
|
return r < 0 ? r : keyslot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _open_all_keys(struct crypt_device *cd,
|
||||||
|
struct luks2_hdr *hdr,
|
||||||
|
int keyslot,
|
||||||
|
const char *passphrase,
|
||||||
|
size_t passphrase_size,
|
||||||
|
uint32_t flags,
|
||||||
|
struct volume_key **vks)
|
||||||
|
{
|
||||||
|
int r, segment;
|
||||||
|
struct volume_key *_vks = NULL;
|
||||||
|
crypt_reencrypt_info ri = LUKS2_reenc_status(hdr);
|
||||||
|
|
||||||
|
segment = (flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) ? CRYPT_ANY_SEGMENT : CRYPT_DEFAULT_SEGMENT;
|
||||||
|
|
||||||
|
switch (ri) {
|
||||||
|
case CRYPT_REENCRYPT_NONE:
|
||||||
|
r = LUKS2_keyslot_open(cd, keyslot, segment, passphrase, passphrase_size, &_vks);
|
||||||
|
break;
|
||||||
|
case CRYPT_REENCRYPT_CLEAN:
|
||||||
|
case CRYPT_REENCRYPT_CRASH:
|
||||||
|
if (segment == CRYPT_ANY_SEGMENT)
|
||||||
|
r = LUKS2_keyslot_open(cd, keyslot, segment, passphrase,
|
||||||
|
passphrase_size, &_vks);
|
||||||
|
else
|
||||||
|
r = LUKS2_keyslot_open_all_segments(cd, keyslot,
|
||||||
|
keyslot, passphrase, passphrase_size,
|
||||||
|
&_vks);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
r = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyslot == CRYPT_ANY_SLOT)
|
||||||
|
keyslot = r;
|
||||||
|
|
||||||
|
if (r >= 0 && (flags & CRYPT_ACTIVATE_KEYRING_KEY))
|
||||||
|
r = load_all_keys(cd, hdr, _vks);
|
||||||
|
|
||||||
|
if (r >= 0 && vks)
|
||||||
|
MOVE_REF(*vks, _vks);
|
||||||
|
|
||||||
|
if (r < 0)
|
||||||
|
crypt_drop_keyring_key(cd, _vks);
|
||||||
|
crypt_free_volume_key(_vks);
|
||||||
|
|
||||||
|
return r < 0 ? r : keyslot;
|
||||||
|
}
|
||||||
|
|
||||||
static int _open_and_activate_reencrypt_device(struct crypt_device *cd,
|
static int _open_and_activate_reencrypt_device(struct crypt_device *cd,
|
||||||
|
struct luks2_hdr *hdr,
|
||||||
int keyslot,
|
int keyslot,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *passphrase,
|
const char *passphrase,
|
||||||
@@ -3705,15 +3754,12 @@ static int _open_and_activate_reencrypt_device(struct crypt_device *cd,
|
|||||||
{
|
{
|
||||||
crypt_reencrypt_info ri;
|
crypt_reencrypt_info ri;
|
||||||
uint64_t check_size, device_size;
|
uint64_t check_size, device_size;
|
||||||
bool use_keyring, keys_ready = false;
|
|
||||||
struct volume_key *vks = NULL;
|
struct volume_key *vks = NULL;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
struct crypt_lock_handle *reencrypt_lock = NULL;
|
struct crypt_lock_handle *reencrypt_lock = NULL;
|
||||||
struct luks2_reenc_context *rh = NULL;
|
struct luks2_reenc_context *rh = NULL;
|
||||||
struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
|
|
||||||
|
|
||||||
if (name)
|
r = crypt_reencrypt_lock(cd, NULL, &reencrypt_lock);
|
||||||
r = crypt_reencrypt_lock(cd, NULL, &reencrypt_lock);
|
|
||||||
if (r) {
|
if (r) {
|
||||||
if (r == -EBUSY)
|
if (r == -EBUSY)
|
||||||
log_err(cd, _("Reencryption in-progress. Cannot activate device."));
|
log_err(cd, _("Reencryption in-progress. Cannot activate device."));
|
||||||
@@ -3722,40 +3768,34 @@ static int _open_and_activate_reencrypt_device(struct crypt_device *cd,
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name && (r = crypt_load(cd, CRYPT_LUKS2, NULL)))
|
if ((r = crypt_load(cd, CRYPT_LUKS2, NULL)))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
ri = LUKS2_reenc_status(hdr);
|
ri = LUKS2_reenc_status(hdr);
|
||||||
|
|
||||||
if (name) {
|
r = -EINVAL;
|
||||||
r = -EINVAL;
|
if (LUKS2_get_data_size(hdr, &check_size, NULL))
|
||||||
if (LUKS2_get_data_size(hdr, &check_size, NULL))
|
goto err;
|
||||||
goto err;
|
if (luks2_check_device_size(cd, hdr, check_size >> SECTOR_SHIFT, &device_size, true))
|
||||||
if (luks2_check_device_size(cd, hdr, check_size >> SECTOR_SHIFT, &device_size, true))
|
goto err;
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name && ri == CRYPT_REENCRYPT_CRASH) {
|
if (crypt_use_keyring_for_vk(cd))
|
||||||
|
flags |= CRYPT_ACTIVATE_KEYRING_KEY;
|
||||||
|
|
||||||
|
if (ri == CRYPT_REENCRYPT_CRASH) {
|
||||||
log_dbg(cd, _("Entering reencryption crash recovery."));
|
log_dbg(cd, _("Entering reencryption crash recovery."));
|
||||||
|
|
||||||
|
r = _open_all_keys(cd, hdr, keyslot, passphrase, passphrase_size, flags, &vks);
|
||||||
|
if (r < 0)
|
||||||
|
goto err;
|
||||||
|
keyslot = r;
|
||||||
|
|
||||||
r = LUKS2_reenc_load(cd, hdr, device_size, NULL, &rh);
|
r = LUKS2_reenc_load(cd, hdr, device_size, NULL, &rh);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_err(cd, _("Failed to load reencryption context from LUKS2 header."));
|
log_err(cd, _("Failed to load reencryption context from LUKS2 header."));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = LUKS2_keyslot_open_all_segments(cd, keyslot, keyslot, passphrase, passphrase_size, &vks);
|
|
||||||
if (r < 0)
|
|
||||||
goto err;
|
|
||||||
keyslot = r;
|
|
||||||
|
|
||||||
r = LUKS2_verify_and_upload_keys(cd, hdr, rh->digest_old, rh->digest_new, vks);
|
|
||||||
if (r) {
|
|
||||||
log_err(cd, _("Failed to verify and upload keys for recovery."));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
keys_ready = true;
|
|
||||||
r = LUKS2_reenc_recover(cd, hdr, rh, vks);
|
r = LUKS2_reenc_recover(cd, hdr, rh, vks);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto err;
|
goto err;
|
||||||
@@ -3781,41 +3821,26 @@ static int _open_and_activate_reencrypt_device(struct crypt_device *cd,
|
|||||||
|
|
||||||
/* recovery finished reencryption or it's already finished */
|
/* recovery finished reencryption or it's already finished */
|
||||||
if (ri == CRYPT_REENCRYPT_NONE) {
|
if (ri == CRYPT_REENCRYPT_NONE) {
|
||||||
|
crypt_drop_keyring_key(cd, vks);
|
||||||
crypt_free_volume_key(vks);
|
crypt_free_volume_key(vks);
|
||||||
crypt_reencrypt_unlock(cd, reencrypt_lock);
|
crypt_reencrypt_unlock(cd, reencrypt_lock);
|
||||||
return _open_and_activate(cd, keyslot, name, passphrase, passphrase_size, flags);
|
return _open_and_activate(cd, keyslot, name, passphrase, passphrase_size, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ri > CRYPT_REENCRYPT_CLEAN && name) {
|
if (ri > CRYPT_REENCRYPT_CLEAN) {
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
use_keyring = (name || (flags & CRYPT_ACTIVATE_KEYRING_KEY)) &&
|
if (!vks) {
|
||||||
crypt_use_keyring_for_vk(cd);
|
r = _open_all_keys(cd, hdr, keyslot, passphrase, passphrase_size, flags, &vks);
|
||||||
if (use_keyring)
|
|
||||||
flags |= CRYPT_ACTIVATE_KEYRING_KEY;
|
|
||||||
|
|
||||||
if (!keys_ready) {
|
|
||||||
log_dbg(cd, "Entering clean reencryption state mode.");
|
|
||||||
/* we need all keys in this case */
|
|
||||||
if (use_keyring || name)
|
|
||||||
r = LUKS2_keyslot_open_all_segments(cd, keyslot, keyslot, passphrase, passphrase_size, &vks);
|
|
||||||
else
|
|
||||||
/* allow user to test passphrase only for whatever keyslot */
|
|
||||||
r = LUKS2_keyslot_open(cd, keyslot, CRYPT_ANY_SEGMENT, passphrase, passphrase_size, &vks);
|
|
||||||
if (r >= 0)
|
if (r >= 0)
|
||||||
keyslot = r;
|
keyslot = r;
|
||||||
if (r < 0)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
keys_ready = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_keyring && keys_ready)
|
log_dbg(cd, "Entering clean reencryption state mode.");
|
||||||
r = load_all_keys(cd, hdr, vks);
|
|
||||||
|
|
||||||
if (r >= 0 && name)
|
if (r >= 0)
|
||||||
r = LUKS2_activate_multi(cd, name, vks, flags);
|
r = LUKS2_activate_multi(cd, name, vks, flags);
|
||||||
err:
|
err:
|
||||||
crypt_reencrypt_unlock(cd, reencrypt_lock);
|
crypt_reencrypt_unlock(cd, reencrypt_lock);
|
||||||
@@ -3844,10 +3869,14 @@ static int _open_and_activate_luks2(struct crypt_device *cd,
|
|||||||
if (ri == CRYPT_REENCRYPT_INVALID)
|
if (ri == CRYPT_REENCRYPT_INVALID)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (ri > CRYPT_REENCRYPT_NONE)
|
if (ri > CRYPT_REENCRYPT_NONE) {
|
||||||
r = _open_and_activate_reencrypt_device(cd, keyslot, name, passphrase,
|
if (name)
|
||||||
passphrase_size, flags);
|
r = _open_and_activate_reencrypt_device(cd, hdr, keyslot, name, passphrase,
|
||||||
else
|
passphrase_size, flags);
|
||||||
|
else
|
||||||
|
r = _open_all_keys(cd, hdr, keyslot, passphrase,
|
||||||
|
passphrase_size, flags, NULL);
|
||||||
|
} else
|
||||||
r = _open_and_activate(cd, keyslot, name, passphrase,
|
r = _open_and_activate(cd, keyslot, name, passphrase,
|
||||||
passphrase_size, flags);
|
passphrase_size, flags);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user