+2010-04-30 Milan Broz <mbroz@redhat.com>
+ * Try to use pkgconfig for device mapper library.
+ * Detect old dm-crypt module and disable LUKS suspend/resume.
+ * Fix apitest to work on older systems.
+
2010-04-12 Milan Broz <mbroz@redhat.com>
* Fix package config to use proper package version.
* Avoid class C++ keyword in library header.
#define DM_CRYPT_TARGET "crypt"
#define RETRY_COUNT 5
+static int _dm_crypt_wipe_key_supported = 0;
+
static int _dm_use_count = 0;
static struct crypt_device *_context = NULL;
static int _dm_simple(int task, const char *name, int udev_wait);
+static void _dm_set_crypt_compat(struct crypt_device *context,
+ int maj, int min, int patch)
+{
+ log_dbg("Detected dm-crypt target of version %i.%i.%i.", maj, min, patch);
+
+ if (maj >= 1 && min >=2)
+ _dm_crypt_wipe_key_supported = 1;
+ else
+ log_dbg("Suspend and resume disabled, no wipe key support.");
+}
+
+static int _dm_check_versions(struct crypt_device *context)
+{
+ int r = 0;
+ struct dm_task *dmt;
+ struct dm_versions *target, *last_target;
+
+ if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
+ goto fail_versions;
+
+ if (!dm_task_run(dmt)) {
+ dm_task_destroy(dmt);
+ goto fail_versions;
+ }
+
+ target = dm_task_get_versions(dmt);
+ do {
+ last_target = target;
+ if (!strcmp(DM_CRYPT_TARGET, target->name)) {
+ r = 1;
+ _dm_set_crypt_compat(context,
+ (int)target->version[0],
+ (int)target->version[1],
+ (int)target->version[2]);
+ }
+ target = (void *) target + target->next;
+ } while (last_target != target);
+
+ if (!r)
+ log_err(context, _("Cannot find compatible device-mapper kernel modules.\n"));
+
+ dm_task_destroy(dmt);
+ return r;
+
+fail_versions:
+ log_err(context, _("Cannot initialize device-mapper. Is dm_mod kernel module loaded?\n"));
+ return 0;
+}
+
int dm_init(struct crypt_device *context, int check_kernel)
{
if (!_dm_use_count++) {
log_dbg("Initialising device-mapper backend%s, UDEV is %sabled.",
check_kernel ? "" : " (NO kernel check requested)",
_dm_use_udev() ? "en" : "dis");
- if (check_kernel && !_dm_simple(DM_DEVICE_LIST_VERSIONS, NULL, 0)) {
- log_err(context, _("Cannot initialize device-mapper. Is dm_mod kernel module loaded?\n"));
+ if (check_kernel && !_dm_check_versions(context))
return -1;
- }
if (getuid() || geteuid())
log_dbg(("WARNING: Running as a non-root user. Functionality may be unavailable."));
dm_log_init(set_dm_error);
int dm_suspend_and_wipe_key(const char *name)
{
+ if (!_dm_crypt_wipe_key_supported)
+ return -ENOTSUP;
+
if (!_dm_simple(DM_DEVICE_SUSPEND, name, 0))
return -EINVAL;
char *msg;
int r = 0;
+ if (!_dm_crypt_wipe_key_supported)
+ return -ENOTSUP;
+
msg = safe_alloc(msg_size);
if (!msg)
return -ENOMEM;
}
r = dm_suspend_and_wipe_key(name);
- if (r)
+ if (r == -ENOTSUP)
+ log_err(cd, "Suspend is not supported for device %s.\n", name);
+ else if (r)
log_err(cd, "Error during suspending device %s.\n", name);
out:
if (!cd)
if (r >= 0) {
keyslot = r;
r = dm_resume_and_reinstate_key(name, mk->keyLength, mk->key);
- if (r)
+ if (r == -ENOTSUP)
+ log_err(cd, "Resume is not supported for device %s.\n", name);
+ else if (r)
log_err(cd, "Error during resuming device %s.\n", name);
} else
r = keyslot;
static char global_log[4096];
static int global_lines = 0;
+static int gcrypt_compatible = 0;
+
// Helpers
static int _prepare_keyfile(const char *name, const char *passphrase)
{
static void SuspendDevice(void)
{
+ int suspend_status;
struct crypt_device *cd;
OK_(crypt_init(&cd, DEVICE_1));
OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0));
- OK_(crypt_suspend(cd, CDEVICE_1));
+ suspend_status = crypt_suspend(cd, CDEVICE_1);
+ if (suspend_status == -ENOTSUP) {
+ printf("WARNING: Suspend/Resume not supported, skipping test.\n");
+ goto out;
+ }
+ OK_(suspend_status);
FAIL_(crypt_suspend(cd, CDEVICE_1), "already suspended");
FAIL_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)-1), "wrong key");
OK_(crypt_resume_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0));
FAIL_(crypt_resume_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0), "not suspended");
_remove_keyfiles();
-
+out:
OK_(crypt_deactivate(cd, CDEVICE_1));
crypt_free(cd);
}
char *cipher = "aes";
char *cipher_mode = "cbc-essiv:sha256";
+ if (!gcrypt_compatible) {
+ printf("WARNING: old libgcrypt, skipping test.\n");
+ return;
+ }
OK_(crypt_init(&cd, DEVICE_2));
OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, ¶ms));
crypt_free(cd);
}
+
+static void _gcrypt_compatible()
+{
+ int maj, min, patch;
+ FILE *f;
+
+ if (!(f = popen("libgcrypt-config --version", "r")))
+ return;
+
+ if (fscanf(f, "%d.%d.%d", &maj, &min, &patch) == 2 &&
+ maj >= 1 && min >= 4)
+ gcrypt_compatible = 1;
+ if (_debug)
+ printf("libgcrypt version %d.%d.%d detected.\n", maj, min, patch);
+
+ (void)fclose(f);
+ return;
+}
+
int main (int argc, char *argv[])
{
int i;
_cleanup();
_setup();
+ _gcrypt_compatible();
crypt_set_debug_level(_debug ? CRYPT_DEBUG_ALL : CRYPT_DEBUG_NONE);
RUN_(UseLuksDevice, "Use pre-formated LUKS device");
RUN_(SuspendDevice, "Suspend/Resume test");
-
_cleanup();
return 0;
}