mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
Add crypt_resume_by_volume_key() function.
If user has volume key available, LUKS device can be resumed directly using provided volume key. No keyslot derivation is needed, only key digest is checked. Fixes: #502.
This commit is contained in:
@@ -828,6 +828,20 @@ int crypt_resume_by_keyfile(struct crypt_device *cd,
|
||||
int keyslot,
|
||||
const char *keyfile,
|
||||
size_t keyfile_size);
|
||||
/**
|
||||
* Resume crypt device using provided volume key.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param name name of device to resume
|
||||
* @param volume_key provided volume key
|
||||
* @param volume_key_size size of volume_key
|
||||
*
|
||||
* @return @e 0 on success or negative errno value otherwise.
|
||||
*/
|
||||
int crypt_resume_by_volume_key(struct crypt_device *cd,
|
||||
const char *name,
|
||||
const char *volume_key,
|
||||
size_t volume_key_size);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,7 @@ CRYPTSETUP_2.0 {
|
||||
crypt_resume_by_keyfile;
|
||||
crypt_resume_by_keyfile_offset;
|
||||
crypt_resume_by_keyfile_device_offset;
|
||||
crypt_resume_by_volume_key;
|
||||
crypt_free;
|
||||
|
||||
crypt_keyslot_add_by_passphrase;
|
||||
|
||||
64
lib/setup.c
64
lib/setup.c
@@ -3144,7 +3144,7 @@ int crypt_resume_by_keyfile_device_offset(struct crypt_device *cd,
|
||||
}
|
||||
|
||||
r = dm_resume_and_reinstate_key(cd, name, vk);
|
||||
if (r)
|
||||
if (r < 0)
|
||||
log_err(cd, _("Error during resuming device %s."), name);
|
||||
out:
|
||||
crypt_safe_free(passphrase_read);
|
||||
@@ -3175,6 +3175,65 @@ int crypt_resume_by_keyfile_offset(struct crypt_device *cd,
|
||||
keyfile, keyfile_size, keyfile_offset);
|
||||
}
|
||||
|
||||
int crypt_resume_by_volume_key(struct crypt_device *cd,
|
||||
const char *name,
|
||||
const char *volume_key,
|
||||
size_t volume_key_size)
|
||||
{
|
||||
struct volume_key *vk = NULL;
|
||||
int r;
|
||||
|
||||
if (!name || !volume_key)
|
||||
return -EINVAL;
|
||||
|
||||
log_dbg(cd, "Resuming volume %s by volume key.", name);
|
||||
|
||||
if ((r = onlyLUKS(cd)))
|
||||
return r;
|
||||
|
||||
r = dm_status_suspended(cd, name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!r) {
|
||||
log_err(cd, _("Volume %s is not suspended."), name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vk = crypt_alloc_volume_key(volume_key_size, volume_key);
|
||||
if (!vk)
|
||||
return -ENOMEM;
|
||||
|
||||
if (isLUKS1(cd->type))
|
||||
r = LUKS_verify_volume_key(&cd->u.luks1.hdr, vk);
|
||||
else if (isLUKS2(cd->type))
|
||||
r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk);
|
||||
else
|
||||
r = -EINVAL;
|
||||
if (r == -EPERM || r == -ENOENT)
|
||||
log_err(cd, _("Volume key does not match the volume."));
|
||||
if (r < 0)
|
||||
goto out;
|
||||
r = 0;
|
||||
|
||||
if (crypt_use_keyring_for_vk(cd)) {
|
||||
r = LUKS2_key_description_by_segment(cd, &cd->u.luks2.hdr, vk, CRYPT_DEFAULT_SEGMENT);
|
||||
if (!r)
|
||||
r = crypt_volume_key_load_in_keyring(cd, vk);
|
||||
}
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
r = dm_resume_and_reinstate_key(cd, name, vk);
|
||||
if (r < 0)
|
||||
log_err(cd, _("Error during resuming device %s."), name);
|
||||
out:
|
||||
if (r < 0)
|
||||
crypt_drop_keyring_key(cd, vk);
|
||||
crypt_free_volume_key(vk);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Keyslot manipulation
|
||||
*/
|
||||
@@ -4472,6 +4531,9 @@ int crypt_volume_key_verify(struct crypt_device *cd,
|
||||
r = LUKS_verify_volume_key(&cd->u.luks1.hdr, vk);
|
||||
else if (isLUKS2(cd->type))
|
||||
r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk);
|
||||
else
|
||||
r = -EINVAL;
|
||||
|
||||
|
||||
if (r == -EPERM)
|
||||
log_err(cd, _("Volume key does not match the volume."));
|
||||
|
||||
@@ -538,6 +538,8 @@ static void UseLuks2Device(void)
|
||||
static void SuspendDevice(void)
|
||||
{
|
||||
struct crypt_active_device cad;
|
||||
char key[128];
|
||||
size_t key_size;
|
||||
int suspend_status;
|
||||
|
||||
OK_(crypt_init(&cd, DEVICE_1));
|
||||
@@ -593,6 +595,14 @@ static void SuspendDevice(void)
|
||||
OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, DEVICE_1));
|
||||
OK_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)));
|
||||
|
||||
/* Resume by volume key */
|
||||
OK_(crypt_suspend(cd, CDEVICE_1));
|
||||
key_size = sizeof(key);
|
||||
memset(key, 0, key_size);
|
||||
FAIL_(crypt_resume_by_volume_key(cd, CDEVICE_1, key, key_size), "wrong key");
|
||||
OK_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, KEY1, strlen(KEY1)));
|
||||
OK_(crypt_resume_by_volume_key(cd, CDEVICE_1, key, key_size));
|
||||
|
||||
OK_(crypt_deactivate(cd, CDEVICE_1));
|
||||
CRYPT_FREE(cd);
|
||||
|
||||
|
||||
@@ -679,6 +679,8 @@ static void UseLuksDevice(void)
|
||||
static void SuspendDevice(void)
|
||||
{
|
||||
struct crypt_active_device cad;
|
||||
char key[128];
|
||||
size_t key_size;
|
||||
int suspend_status;
|
||||
|
||||
OK_(crypt_init(&cd, DEVICE_1));
|
||||
@@ -733,6 +735,14 @@ static void SuspendDevice(void)
|
||||
OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, DEVICE_1));
|
||||
OK_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)));
|
||||
|
||||
/* Resume by volume key */
|
||||
OK_(crypt_suspend(cd, CDEVICE_1));
|
||||
key_size = sizeof(key);
|
||||
memset(key, 0, key_size);
|
||||
FAIL_(crypt_resume_by_volume_key(cd, CDEVICE_1, key, key_size), "wrong key");
|
||||
OK_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, KEY1, strlen(KEY1)));
|
||||
OK_(crypt_resume_by_volume_key(cd, CDEVICE_1, key, key_size));
|
||||
|
||||
OK_(crypt_deactivate(cd, CDEVICE_1));
|
||||
CRYPT_FREE(cd);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user