#include <dirent.h>
#include <errno.h>
#include <libdevmapper.h>
+#include <linux/dm-ioctl.h>
#include <fcntl.h>
#include <linux/fs.h>
+#include <uuid/uuid.h>
#include "internal.h"
#include "luks.h"
#define DEVICE_DIR "/dev"
#define DM_UUID_PREFIX "CRYPT-"
#define DM_UUID_PREFIX_LEN 6
-#define DM_UUID_LEN UUID_STRING_L
#define DM_CRYPT_TARGET "crypt"
#define RETRY_COUNT 5
return r;
}
+#define UUID_LEN 37 /* 36 + \0, libuuid ... */
+/*
+ * UUID has format: CRYPT-<devicetype>-[<uuid>-]<device name>
+ * CRYPT-PLAIN-name
+ * CRYPT-LUKS1-00000000000000000000000000000000-name
+ * CRYPT-TEMP-name
+ */
+static void dm_prepare_uuid(const char *name, const char *type, const char *uuid, char *buf, size_t buflen)
+{
+ char *ptr, uuid2[UUID_LEN] = {0};
+ uuid_t uu;
+ int i = 0;
+
+ /* Remove '-' chars */
+ if (uuid && !uuid_parse(uuid, uu)) {
+ for (ptr = uuid2, i = 0; i < UUID_LEN; i++)
+ if (uuid[i] != '-') {
+ *ptr = uuid[i];
+ ptr++;
+ }
+ }
+
+ i = snprintf(buf, buflen, DM_UUID_PREFIX "%s%s%s%s%s",
+ type ?: "", type ? "-" : "",
+ uuid2[0] ? uuid2 : "", uuid2[0] ? "-" : "",
+ name);
+
+ log_dbg("DM-UUID is %s", buf);
+ if (i >= buflen)
+ log_err(NULL, _("DM-UUID for device %s was truncated.\n"), name);
+}
+
int dm_create_device(const char *name,
const char *device,
const char *cipher,
+ const char *type,
const char *uuid,
uint64_t size,
uint64_t skip,
struct dm_info dmi;
char *params = NULL;
char *error = NULL;
- char dev_uuid[DM_UUID_PREFIX_LEN + DM_UUID_LEN + 1] = {0};
+ char dev_uuid[DM_UUID_LEN] = {0};
int r = -EINVAL;
uint32_t read_ahead = 0;
params = get_params(device, skip, offset, cipher, key_size, key);
if (!params)
goto out_no_removal;
-
- if (uuid) {
- strncpy(dev_uuid, DM_UUID_PREFIX, DM_UUID_PREFIX_LEN);
- strncpy(dev_uuid + DM_UUID_PREFIX_LEN, uuid, DM_UUID_LEN);
- dev_uuid[DM_UUID_PREFIX_LEN + DM_UUID_LEN] = '\0';
+
+ /* All devices must have DM_UUID, only resize on old device is exception */
+ if (reload) {
+ if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
+ goto out_no_removal;
+
+ if (!dm_task_set_name(dmt, name))
+ goto out_no_removal;
+ } else {
+ dm_prepare_uuid(name, type, uuid, dev_uuid, sizeof(dev_uuid));
+
+ if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
+ goto out_no_removal;
+
+ if (!dm_task_set_name(dmt, name))
+ goto out_no_removal;
+
+ if (!dm_task_set_uuid(dmt, dev_uuid))
+ goto out_no_removal;
}
- if (!(dmt = dm_task_create(reload ? DM_DEVICE_RELOAD
- : DM_DEVICE_CREATE)))
- goto out_no_removal;
- if (!dm_task_set_name(dmt, name))
- goto out_no_removal;
+
if (read_only && !dm_task_set_ro(dmt))
goto out_no_removal;
if (!dm_task_add_target(dmt, 0, size, DM_CRYPT_TARGET, params))
goto out_no_removal;
#endif
- if (uuid && !dm_task_set_uuid(dmt, dev_uuid))
- goto out_no_removal;
-
if (!dm_task_run(dmt))
goto out_no_removal;
int *key_size,
char **key,
int *read_only,
- int *suspended)
+ int *suspended,
+ char **uuid)
{
struct dm_task *dmt;
struct dm_info dmi;
uint64_t start, length, val64;
- char *target_type, *params, *rcipher, *key_, *rdevice, *endp, buffer[3];
+ char *target_type, *params, *rcipher, *key_, *rdevice, *endp, buffer[3], *tmp_uuid;
void *next = NULL;
int i, r = -EINVAL;
if (suspended)
*suspended = dmi.suspended;
+ if (uuid && (tmp_uuid = (char*)dm_task_get_uuid(dmt)) &&
+ !strncmp(tmp_uuid, DM_UUID_PREFIX, DM_UUID_PREFIX_LEN))
+ *uuid = strdup(tmp_uuid + DM_UUID_PREFIX_LEN);
+
r = (dmi.open_count > 0);
out:
if (dmt)
if (!processed_key)
return -ENOENT;
- r = dm_create_device(name, cd->device, dm_cipher ?: cipher, uuid, size, skip, offset,
+ r = dm_create_device(name, cd->device, dm_cipher ?: cipher, cd->type, uuid, size, skip, offset,
key_size, processed_key, read_only, reload);
free(dm_cipher);
crypt_get_cipher_mode(cd)) < 0)
r = -ENOMEM;
else
- r = dm_create_device(name, cd->device, cipher, no_uuid ? NULL : crypt_get_uuid(cd),
- size, 0, offset, mk->keyLength, mk->key,
- read_only, 0);
+ r = dm_create_device(name, cd->device, cipher, cd->type,
+ no_uuid ? NULL : crypt_get_uuid(cd),
+ size, 0, offset, mk->keyLength, mk->key,
+ read_only, 0);
free(cipher);
return r;
}
}
static int _crypt_init(struct crypt_device **cd,
+ const char *type,
struct crypt_options *options,
int load, int need_dm)
{
- int r;
+ int init_by_name, r;
+
+ /* if it is plain device and mapping table is being reloaded
+ initialize it by name*/
+ init_by_name = (type && !strcmp(type, CRYPT_PLAIN) && load);
/* Some of old API calls do not require DM in kernel,
fake initialisation by initialise it with kernel_check disabled */
if (!need_dm)
(void)dm_init(NULL, 0);
- r = crypt_init(cd, options->device);
+ if (init_by_name)
+ r = crypt_init_by_name(cd, options->name);
+ else
+ r = crypt_init(cd, options->device);
if (!need_dm)
dm_exit();
crypt_set_timeout(*cd, options->timeout);
crypt_set_password_retry(*cd, options->tries);
- crypt_set_iterarion_time(*cd, options->iteration_time);
+ crypt_set_iterarion_time(*cd, options->iteration_time ?: 1000);
crypt_set_password_verify(*cd, options->flags & CRYPT_FLAG_VERIFY);
- if (load)
- r = crypt_load(*cd, CRYPT_LUKS1, NULL);
+ if (load && !init_by_name)
+ r = crypt_load(*cd, type, NULL);
+
+ if (type && !(*cd)->type) {
+ (*cd)->type = strdup(type);
+ if (!(*cd)->type)
+ r = -ENOMEM;
+ }
+
+ if (r)
+ crypt_free(*cd);
return r;
}
unsigned int keyLen;
int r;
- r = _crypt_init(&cd, options, 0, 1);
+ r = _crypt_init(&cd, CRYPT_PLAIN, options, 0, 1);
if (r)
return r;
unsigned int keyLen;
int r;
- r = _crypt_init(&cd, options, 0, 1);
+ r = _crypt_init(&cd, CRYPT_PLAIN, options, 1, 1);
if (r)
return r;
int crypt_resize_device(struct crypt_options *options)
{
struct crypt_device *cd = NULL;
- char *device, *cipher, *key = NULL;
+ char *device = NULL, *cipher = NULL, *uuid = NULL, *key = NULL;
+ char *type = NULL;
uint64_t size, skip, offset;
int key_size, read_only, r;
r = dm_query_device(options->name, &device, &size, &skip, &offset,
- &cipher, &key_size, &key, &read_only, NULL);
+ &cipher, &key_size, &key, &read_only, NULL, &uuid);
if (r < 0)
- return r;
+ goto out;
- r = _crypt_init(&cd, options, 0, 1);
+ /* Try to determine type of device from UUID */
+ if (uuid) {
+ if (!strncmp(uuid, CRYPT_PLAIN, strlen(CRYPT_PLAIN))) {
+ type = CRYPT_PLAIN;
+ free (uuid);
+ uuid = NULL;
+ } else if (!strncmp(uuid, CRYPT_LUKS1, strlen(CRYPT_LUKS1)))
+ type = CRYPT_LUKS1;
+ }
+
+ r = _crypt_init(&cd, type, options, 1, 1);
if (r)
- return r;
+ goto out;
size = options->size;
r = device_check_and_adjust(cd, device, &size, &offset, &read_only);
if (r)
- return r;
+ goto out;
- r = dm_create_device(options->name, device, cipher, NULL, size, skip, offset,
+ r = dm_create_device(options->name, device, cipher, type,
+ crypt_get_uuid(cd), size, skip, offset,
key_size, key, read_only, 1);
-
+out:
safe_free(key);
free(cipher);
free(device);
+ free(uuid);
crypt_free(cd);
return r;
}
r = dm_query_device(options->name, (char **)&options->device, &options->size,
&options->skip, &options->offset, (char **)&options->cipher,
- &options->key_size, NULL, &read_only, NULL);
+ &options->key_size, NULL, &read_only, NULL, NULL);
if (r < 0)
return r;
return r;
}
- if ((r = _crypt_init(&cd, options, 0, 1)))
+ if ((r = _crypt_init(&cd, CRYPT_LUKS1, options, 0, 1)))
return r;
if (options->key_slot >= LUKS_NUMKEYS && options->key_slot != CRYPT_ANY_SLOT) {
if (!options->name)
return -EINVAL;
- r = _crypt_init(&cd, options, 1, 1);
+ r = _crypt_init(&cd, CRYPT_LUKS1, options, 1, 1);
if (r)
return r;
struct crypt_device *cd = NULL;
int r;
- r = _crypt_init(&cd, options, 1, 1);
+ r = _crypt_init(&cd, CRYPT_LUKS1, options, 1, 1);
if (r)
return r;
struct crypt_device *cd = NULL;
int r;
- r = _crypt_init(&cd, options, 1, 1);
+ r = _crypt_init(&cd, CRYPT_LUKS1, options, 1, 1);
if (r)
return r;
struct crypt_device *cd = NULL;
int r = -EINVAL;
- r = _crypt_init(&cd, options, 1, 1);
+ r = _crypt_init(&cd, CRYPT_LUKS1, options, 1, 1);
if (r)
return r;
char *uuid;
int r;
- r = _crypt_init(&cd, options, 1, 0);
+ r = _crypt_init(&cd, CRYPT_LUKS1, options, 1, 0);
if (r)
return r;
struct crypt_device *cd = NULL;
int r;
- r = _crypt_init(&cd, options, 1, 0);
- crypt_free(cd);
+ r = _crypt_init(&cd, CRYPT_LUKS1, options, 1, 0);
+ if (!r)
+ crypt_free(cd);
return r;
}
struct crypt_device *cd = NULL;
int r;
- r = _crypt_init(&cd, options, 1, 0);
+ r = _crypt_init(&cd, CRYPT_LUKS1, options, 1, 0);
if(r < 0)
return r;
}
r = dm_query_device(name, &device, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, NULL, NULL);
if (!r)
r = crypt_init(cd, device);
}
r = dm_query_device(name, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, &suspended);
+ NULL, NULL, NULL, NULL, &suspended, NULL);
if (r < 0)
return r;
}
r = dm_query_device(name, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, &suspended);
+ NULL, NULL, NULL, NULL, &suspended, NULL);
if (r < 0)
return r;
}
r = dm_query_device(name, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, &suspended);
+ NULL, NULL, NULL, NULL, &suspended, NULL);
if (r < 0)
return r;