diff --git a/ChangeLog b/ChangeLog index 68ead079..1d8241a5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-07-19 Milan Broz + * 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 * Remove old API functions (all functions using crypt_options). * Add --enable-discards option to allow discards/TRIM requests. diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c index 08160f13..c239f87e 100644 --- a/lib/libdevmapper.c +++ b/lib/libdevmapper.c @@ -681,22 +681,31 @@ int dm_query_device(const char *name, uint32_t get_flags, 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); if (!dmd->vk) { r = -ENOMEM; goto out; } - buffer[2] = '\0'; - for(i = 0; i < dmd->vk->keylength; i++) { - memcpy(buffer, &key_[i * 2], 2); - dmd->vk->key[i] = strtoul(buffer, &endp, 16); - if (endp != &buffer[2]) { - crypt_free_volume_key(dmd->vk); - dmd->vk = NULL; - r = -EINVAL; - goto out; + if (get_flags & DM_ACTIVE_KEY) { + buffer[2] = '\0'; + for(i = 0; i < dmd->vk->keylength; i++) { + memcpy(buffer, &key_[i * 2], 2); + dmd->vk->key[i] = strtoul(buffer, &endp, 16); + if (endp != &buffer[2]) { + crypt_free_volume_key(dmd->vk); + dmd->vk = NULL; + r = -EINVAL; + goto out; + } } } } diff --git a/lib/setup.c b/lib/setup.c index 916e388a..08eaf6f6 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -488,7 +488,8 @@ int crypt_init_by_name(struct crypt_device **cd, const char *name) 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) 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.offset = dmd.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); 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)) { if (dmd.device) { - if (crypt_load(*cd, CRYPT_LUKS1, NULL) < 0 || - crypt_volume_key_verify(*cd, dmd.vk->key, dmd.vk->keylength) < 0) { + r = crypt_load(*cd, CRYPT_LUKS1, NULL); + if (r < 0) { 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 @@ -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); - 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) { log_err(NULL, _("Device %s is not active.\n"), name); goto out; @@ -927,6 +926,12 @@ int crypt_suspend(struct crypt_device *cd, 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); if (ci < CRYPT_ACTIVE) { log_err(cd, _("Volume %s is not active.\n"), name); diff --git a/lib/utils_dm.h b/lib/utils_dm.h index c954ff09..b63d1aa2 100644 --- a/lib/utils_dm.h +++ b/lib/utils_dm.h @@ -18,13 +18,8 @@ uint32_t dm_flags(void); #define DM_ACTIVE_DEVICE (1 << 0) #define DM_ACTIVE_CIPHER (1 << 1) #define DM_ACTIVE_UUID (1 << 2) -#define DM_ACTIVE_KEY (1 << 3) - -#define DM_ACTIVE_ALL ( \ - DM_ACTIVE_DEVICE | \ - DM_ACTIVE_CIPHER | \ - DM_ACTIVE_UUID | \ - DM_ACTIVE_KEY) +#define DM_ACTIVE_KEYSIZE (1 << 3) +#define DM_ACTIVE_KEY (1 << 4) struct crypt_dm_active_device { const char *device; diff --git a/src/cryptsetup.c b/src/cryptsetup.c index a78e6961..b7e27ca0 100644 --- a/src/cryptsetup.c +++ b/src/cryptsetup.c @@ -958,8 +958,8 @@ static int action_luksResume(int arg __attribute__((unused))) if ((r = crypt_init_by_name(&cd, action_argv[0]))) goto out; - if ((r = crypt_load(cd, CRYPT_LUKS1, NULL))) - goto out; + crypt_set_timeout(cd, opt_timeout); + crypt_set_password_retry(cd, opt_tries); if (opt_key_file) r = crypt_resume_by_keyfile(cd, action_argv[0], CRYPT_ANY_SLOT, diff --git a/tests/api-test.c b/tests/api-test.c index ec4e3d9f..38526827 100644 --- a/tests/api-test.c +++ b/tests/api-test.c @@ -895,11 +895,8 @@ static void UseTempVolumes(void) EQ_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE); crypt_free(cd); - // Volume key is properly initialised from active device OK_(crypt_init_by_name(&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); // Dirty checks: device without UUID diff --git a/tests/compat-test b/tests/compat-test index 291c1bf2..91a84f56 100755 --- a/tests/compat-test +++ b/tests/compat-test @@ -369,5 +369,21 @@ $CRYPTSETUP -q remove $DEV_NAME3 || fail $CRYPTSETUP -q remove $DEV_NAME2 || 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 exit 0