* Revert default initialisation of volume key in crypt_init_by_name().

* Do not allow key retrieval while suspended (key could be wiped).
* Do not allow suspend for non-LUKS devices.
* Support retries and timeout parameters for luksSuspend.

Add luksSuspend/Resume test.

git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@574 36d66b0a-2a48-0410-832c-cd162a569da5
This commit is contained in:
Milan Broz
2011-07-19 13:55:34 +00:00
parent 261d0d05a5
commit 1bf26b9a90
7 changed files with 60 additions and 32 deletions

View File

@@ -1,3 +1,9 @@
2011-07-19 Milan Broz <mbroz@redhat.com>
* Revert default initialisation of volume key in crypt_init_by_name().
* Do not allow key retrieval while suspended (key could be wiped).
* Do not allow suspend for non-LUKS devices.
* Support retries and timeout parameters for luksSuspend.
2011-07-07 Milan Broz <mbroz@redhat.com> 2011-07-07 Milan Broz <mbroz@redhat.com>
* Remove old API functions (all functions using crypt_options). * Remove old API functions (all functions using crypt_options).
* Add --enable-discards option to allow discards/TRIM requests. * Add --enable-discards option to allow discards/TRIM requests.

View File

@@ -681,22 +681,31 @@ int dm_query_device(const char *name, uint32_t get_flags,
goto out; goto out;
} }
if (get_flags & DM_ACTIVE_KEY) { /* Never allow to return empty key */
if ((get_flags & DM_ACTIVE_KEY) && dmi.suspended) {
log_dbg("Cannot read volume key while suspended.");
r = -EINVAL;
goto out;
}
if (get_flags & DM_ACTIVE_KEYSIZE) {
dmd->vk = crypt_alloc_volume_key(strlen(key_) / 2, NULL); dmd->vk = crypt_alloc_volume_key(strlen(key_) / 2, NULL);
if (!dmd->vk) { if (!dmd->vk) {
r = -ENOMEM; r = -ENOMEM;
goto out; goto out;
} }
buffer[2] = '\0'; if (get_flags & DM_ACTIVE_KEY) {
for(i = 0; i < dmd->vk->keylength; i++) { buffer[2] = '\0';
memcpy(buffer, &key_[i * 2], 2); for(i = 0; i < dmd->vk->keylength; i++) {
dmd->vk->key[i] = strtoul(buffer, &endp, 16); memcpy(buffer, &key_[i * 2], 2);
if (endp != &buffer[2]) { dmd->vk->key[i] = strtoul(buffer, &endp, 16);
crypt_free_volume_key(dmd->vk); if (endp != &buffer[2]) {
dmd->vk = NULL; crypt_free_volume_key(dmd->vk);
r = -EINVAL; dmd->vk = NULL;
goto out; r = -EINVAL;
goto out;
}
} }
} }
} }

View File

@@ -488,7 +488,8 @@ int crypt_init_by_name(struct crypt_device **cd, const char *name)
return -ENODEV; return -ENODEV;
} }
r = dm_query_device(name, DM_ACTIVE_ALL, &dmd); r = dm_query_device(name, DM_ACTIVE_DEVICE | DM_ACTIVE_CIPHER |
DM_ACTIVE_UUID | DM_ACTIVE_KEYSIZE, &dmd);
if (r < 0) if (r < 0)
goto out; goto out;
@@ -525,8 +526,6 @@ int crypt_init_by_name(struct crypt_device **cd, const char *name)
(*cd)->plain_hdr.hash = NULL; /* no way to get this */ (*cd)->plain_hdr.hash = NULL; /* no way to get this */
(*cd)->plain_hdr.offset = dmd.offset; (*cd)->plain_hdr.offset = dmd.offset;
(*cd)->plain_hdr.skip = dmd.iv_offset; (*cd)->plain_hdr.skip = dmd.iv_offset;
(*cd)->volume_key = dmd.vk;
dmd.vk = NULL;
r = crypt_parse_name_and_mode(dmd.cipher, cipher, NULL, cipher_mode); r = crypt_parse_name_and_mode(dmd.cipher, cipher, NULL, cipher_mode);
if (!r) { if (!r) {
@@ -550,14 +549,12 @@ int crypt_init_by_name(struct crypt_device **cd, const char *name)
} }
} else if (!strncmp(CRYPT_LUKS1, dmd.uuid, sizeof(CRYPT_LUKS1)-1)) { } else if (!strncmp(CRYPT_LUKS1, dmd.uuid, sizeof(CRYPT_LUKS1)-1)) {
if (dmd.device) { if (dmd.device) {
if (crypt_load(*cd, CRYPT_LUKS1, NULL) < 0 || r = crypt_load(*cd, CRYPT_LUKS1, NULL);
crypt_volume_key_verify(*cd, dmd.vk->key, dmd.vk->keylength) < 0) { if (r < 0) {
log_dbg("LUKS device header does not match active device."); log_dbg("LUKS device header does not match active device.");
goto out; /* initialise empty context */
r = 0;
} }
(*cd)->volume_key = dmd.vk;
dmd.vk = NULL;
} }
} }
} else } else
@@ -794,7 +791,9 @@ int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size)
log_dbg("Resizing device %s to %" PRIu64 " sectors.", name, new_size); log_dbg("Resizing device %s to %" PRIu64 " sectors.", name, new_size);
r = dm_query_device(name, DM_ACTIVE_ALL, &dmd); r = dm_query_device(name, DM_ACTIVE_DEVICE | DM_ACTIVE_CIPHER |
DM_ACTIVE_UUID | DM_ACTIVE_KEYSIZE |
DM_ACTIVE_KEY, &dmd);
if (r < 0) { if (r < 0) {
log_err(NULL, _("Device %s is not active.\n"), name); log_err(NULL, _("Device %s is not active.\n"), name);
goto out; goto out;
@@ -927,6 +926,12 @@ int crypt_suspend(struct crypt_device *cd,
log_dbg("Suspending volume %s.", name); log_dbg("Suspending volume %s.", name);
if (!isLUKS(cd->type)) {
log_err(cd, _("This operation is supported only for LUKS device.\n"));
r = -EINVAL;
goto out;
}
ci = crypt_status(NULL, name); ci = crypt_status(NULL, name);
if (ci < CRYPT_ACTIVE) { if (ci < CRYPT_ACTIVE) {
log_err(cd, _("Volume %s is not active.\n"), name); log_err(cd, _("Volume %s is not active.\n"), name);

View File

@@ -18,13 +18,8 @@ uint32_t dm_flags(void);
#define DM_ACTIVE_DEVICE (1 << 0) #define DM_ACTIVE_DEVICE (1 << 0)
#define DM_ACTIVE_CIPHER (1 << 1) #define DM_ACTIVE_CIPHER (1 << 1)
#define DM_ACTIVE_UUID (1 << 2) #define DM_ACTIVE_UUID (1 << 2)
#define DM_ACTIVE_KEY (1 << 3) #define DM_ACTIVE_KEYSIZE (1 << 3)
#define DM_ACTIVE_KEY (1 << 4)
#define DM_ACTIVE_ALL ( \
DM_ACTIVE_DEVICE | \
DM_ACTIVE_CIPHER | \
DM_ACTIVE_UUID | \
DM_ACTIVE_KEY)
struct crypt_dm_active_device { struct crypt_dm_active_device {
const char *device; const char *device;

View File

@@ -958,8 +958,8 @@ static int action_luksResume(int arg __attribute__((unused)))
if ((r = crypt_init_by_name(&cd, action_argv[0]))) if ((r = crypt_init_by_name(&cd, action_argv[0])))
goto out; goto out;
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL))) crypt_set_timeout(cd, opt_timeout);
goto out; crypt_set_password_retry(cd, opt_tries);
if (opt_key_file) if (opt_key_file)
r = crypt_resume_by_keyfile(cd, action_argv[0], CRYPT_ANY_SLOT, r = crypt_resume_by_keyfile(cd, action_argv[0], CRYPT_ANY_SLOT,

View File

@@ -895,11 +895,8 @@ static void UseTempVolumes(void)
EQ_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE); EQ_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE);
crypt_free(cd); crypt_free(cd);
// Volume key is properly initialised from active device
OK_(crypt_init_by_name(&cd, CDEVICE_2)); OK_(crypt_init_by_name(&cd, CDEVICE_2));
OK_(crypt_deactivate(cd, CDEVICE_2)); OK_(crypt_deactivate(cd, CDEVICE_2));
OK_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0));
OK_(crypt_deactivate(cd, CDEVICE_2));
crypt_free(cd); crypt_free(cd);
// Dirty checks: device without UUID // Dirty checks: device without UUID

View File

@@ -369,5 +369,21 @@ $CRYPTSETUP -q remove $DEV_NAME3 || fail
$CRYPTSETUP -q remove $DEV_NAME2 || fail $CRYPTSETUP -q remove $DEV_NAME2 || fail
$CRYPTSETUP -q remove $DEV_NAME || fail $CRYPTSETUP -q remove $DEV_NAME || fail
prepare "[26] Suspend/Resume" wipe
# only LUKS is supported
echo "key0" | $CRYPTSETUP create $DEV_NAME $LOOPDEV || fail
$CRYPTSETUP luksSuspend $DEV_NAME 2>/dev/null && fail
$CRYPTSETUP luksResume $DEV_NAME 2>/dev/null && fail
$CRYPTSETUP -q remove $DEV_NAME || fail
$CRYPTSETUP luksSuspend $DEV_NAME 2>/dev/null && fail
# LUKS
echo "key0" | $CRYPTSETUP -q luksFormat $LOOPDEV || fail
echo "key0" | $CRYPTSETUP -q luksOpen $LOOPDEV $DEV_NAME || fail
$CRYPTSETUP luksSuspend $DEV_NAME || fail
$CRYPTSETUP -q resize $DEV_NAME 2>/dev/null && fail
echo "xxx" | $CRYPTSETUP luksResume $DEV_NAME -T 1 2>/dev/null && fail
echo "key0" | $CRYPTSETUP luksResume $DEV_NAME || fail
$CRYPTSETUP -q luksClose $DEV_NAME || fail
remove_mapping remove_mapping
exit 0 exit 0