Commit 913ef7c0 authored by Milan Broz's avatar Milan Broz

Rewrite dm query/create function backend.

git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@570 36d66b0a-2a48-0410-832c-cd162a569da5
parent 69bd9005
......@@ -62,7 +62,7 @@ int device_check_and_adjust(struct crypt_device *cd,
enum devcheck device_check,
uint64_t *size,
uint64_t *offset,
int *read_only);
uint32_t *flags);
int wipe_device_header(const char *device, int sectors);
void logger(struct crypt_device *cd, int class, const char *file, int line, const char *format, ...);
......@@ -94,5 +94,11 @@ int crypt_plain_hash(struct crypt_device *ctx,
const char *hash_name,
char *key, size_t key_size,
const char *passphrase, size_t passphrase_size);
int PLAIN_activate(struct crypt_device *cd,
const char *name,
struct volume_key *vk,
uint64_t size,
uint64_t iv_offset,
uint32_t flags);
#endif /* INTERNAL_H */
......@@ -375,7 +375,7 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot);
* Activation flags
*/
#define CRYPT_ACTIVATE_READONLY (1 << 0)
#define CRYPT_ACTIVATE_NO_UUID (1 << 1)
#define CRYPT_ACTIVATE_NO_UUID (1 << 1) /* ignored */
#define CRYPT_ACTIVATE_SHARED (1 << 2)
/**
......
......@@ -396,16 +396,8 @@ static void dm_prepare_uuid(const char *name, const char *type, const char *uuid
}
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,
uint64_t offset,
size_t key_size,
const char *key,
int read_only,
struct crypt_dm_active_device *dmd,
int reload)
{
struct dm_task *dmt = NULL;
......@@ -418,7 +410,8 @@ int dm_create_device(const char *name,
uint32_t cookie = 0;
uint16_t udev_flags = 0;
params = get_params(device, skip, offset, cipher, key_size, key);
params = get_params(dmd->device, dmd->iv_offset, dmd->offset,
dmd->cipher, dmd->key_size, dmd->key);
if (!params)
goto out_no_removal;
......@@ -433,7 +426,7 @@ int dm_create_device(const char *name,
if (!dm_task_set_name(dmt, name))
goto out_no_removal;
} else {
dm_prepare_uuid(name, type, uuid, dev_uuid, sizeof(dev_uuid));
dm_prepare_uuid(name, type, dmd->uuid, dev_uuid, sizeof(dev_uuid));
if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
goto out_no_removal;
......@@ -450,13 +443,13 @@ int dm_create_device(const char *name,
if ((dm_flags() & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt))
goto out_no_removal;
if (read_only && !dm_task_set_ro(dmt))
if ((dmd->flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt))
goto out_no_removal;
if (!dm_task_add_target(dmt, 0, size, DM_CRYPT_TARGET, params))
if (!dm_task_add_target(dmt, 0, dmd->size, DM_CRYPT_TARGET, params))
goto out_no_removal;
#ifdef DM_READ_AHEAD_MINIMUM_FLAG
if (device_read_ahead(device, &read_ahead) &&
if (device_read_ahead(dmd->device, &read_ahead) &&
!dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG))
goto out_no_removal;
#endif
......@@ -470,7 +463,7 @@ int dm_create_device(const char *name,
goto out;
if (!dm_task_set_name(dmt, name))
goto out;
if (uuid && !dm_task_set_uuid(dmt, dev_uuid))
if (dmd->uuid && !dm_task_set_uuid(dmt, dev_uuid))
goto out;
if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
goto out;
......@@ -513,10 +506,9 @@ out_no_removal:
return r;
}
int dm_status_device(const char *name)
static int dm_status_dmi(const char *name, struct dm_info *dmi)
{
struct dm_task *dmt;
struct dm_info dmi;
uint64_t start, length;
char *target_type, *params;
void *next = NULL;
......@@ -531,10 +523,10 @@ int dm_status_device(const char *name)
if (!dm_task_run(dmt))
goto out;
if (!dm_task_get_info(dmt, &dmi))
if (!dm_task_get_info(dmt, dmi))
goto out;
if (!dmi.exists) {
if (!dmi->exists) {
r = -ENODEV;
goto out;
}
......@@ -545,7 +537,7 @@ int dm_status_device(const char *name)
start != 0 || next)
r = -EINVAL;
else
r = (dmi.open_count > 0);
r = 0;
out:
if (dmt)
dm_task_destroy(dmt);
......@@ -553,17 +545,32 @@ out:
return r;
}
int dm_query_device(const char *name,
char **device,
uint64_t *size,
uint64_t *skip,
uint64_t *offset,
char **cipher,
int *key_size,
char **key,
int *read_only,
int *suspended,
char **uuid)
int dm_status_device(const char *name)
{
int r;
struct dm_info dmi;
r = dm_status_dmi(name, &dmi);
if (r < 0)
return r;
return (dmi.open_count > 0);
}
int dm_status_suspended(const char *name)
{
int r;
struct dm_info dmi;
r = dm_status_dmi(name, &dmi);
if (r < 0)
return r;
return dmi.suspended ? 1 : 0;
}
int dm_query_device(const char *name, uint32_t get_flags,
struct crypt_dm_active_device *dmd)
{
struct dm_task *dmt;
struct dm_info dmi;
......@@ -571,7 +578,10 @@ int dm_query_device(const char *name,
char *target_type, *params, *rcipher, *key_, *rdevice, *endp, buffer[3];
const char *tmp_uuid;
void *next = NULL;
int i, r = -EINVAL;
unsigned int i;
int r = -EINVAL;
memset(dmd, 0, sizeof(*dmd));
if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
goto out;
......@@ -592,19 +602,20 @@ int dm_query_device(const char *name,
goto out;
}
tmp_uuid = dm_task_get_uuid(dmt);
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
if (!target_type || strcmp(target_type, DM_CRYPT_TARGET) != 0 ||
start != 0 || next)
goto out;
if (size)
*size = length;
dmd->size = length;
rcipher = strsep(&params, " ");
/* cipher */
if (cipher)
*cipher = strdup(rcipher);
if (get_flags & DM_ACTIVE_CIPHER)
dmd->cipher = strdup(rcipher);
/* skip */
key_ = strsep(&params, " ");
......@@ -614,13 +625,13 @@ int dm_query_device(const char *name,
if (*params != ' ')
goto out;
params++;
if (skip)
*skip = val64;
dmd->iv_offset = val64;
/* device */
rdevice = strsep(&params, " ");
if (device)
*device = crypt_lookup_dev(rdevice);
if (get_flags & DM_ACTIVE_DEVICE)
dmd->device = crypt_lookup_dev(rdevice);
/*offset */
if (!params)
......@@ -628,43 +639,41 @@ int dm_query_device(const char *name,
val64 = strtoull(params, &params, 10);
if (*params)
goto out;
if (offset)
*offset = val64;
dmd->offset = val64;
/* key_size */
if (key_size)
*key_size = strlen(key_) / 2;
dmd->key_size = strlen(key_) / 2;
/* key */
if (key_size && key) {
*key = crypt_safe_alloc(*key_size);
if (!*key) {
if (dmd->key_size && (get_flags & DM_ACTIVE_KEY)) {
dmd->key = crypt_safe_alloc(dmd->key_size);
if (!dmd->key) {
r = -ENOMEM;
goto out;
}
buffer[2] = '\0';
for(i = 0; i < *key_size; i++) {
for(i = 0; i < dmd->key_size; i++) {
memcpy(buffer, &key_[i * 2], 2);
(*key)[i] = strtoul(buffer, &endp, 16);
dmd->key[i] = strtoul(buffer, &endp, 16);
if (endp != &buffer[2]) {
crypt_safe_free(key);
*key = NULL;
crypt_safe_free(dmd->key);
dmd->key = NULL;
goto out;
}
}
}
memset(key_, 0, strlen(key_));
if (read_only)
*read_only = dmi.read_only;
if (suspended)
*suspended = dmi.suspended;
if (dmi.read_only)
dmd->flags |= CRYPT_ACTIVATE_READONLY;
if (uuid && (tmp_uuid = dm_task_get_uuid(dmt)) &&
!strncmp(tmp_uuid, DM_UUID_PREFIX, DM_UUID_PREFIX_LEN))
*uuid = strdup(tmp_uuid + DM_UUID_PREFIX_LEN);
if (!tmp_uuid)
dmd->flags |= CRYPT_ACTIVATE_NO_UUID;
else if (get_flags & DM_ACTIVE_UUID) {
if (!strncmp(tmp_uuid, DM_UUID_PREFIX, DM_UUID_PREFIX_LEN))
dmd->uuid = strdup(tmp_uuid + DM_UUID_PREFIX_LEN);
}
r = (dmi.open_count > 0);
out:
......@@ -767,23 +776,22 @@ int dm_is_dm_kernel_name(const char *name)
int dm_check_segment(const char *name, uint64_t offset, uint64_t size)
{
uint64_t seg_size, seg_offset;
struct crypt_dm_active_device dmd;
int r;
log_dbg("Checking segments for device %s.", name);
r = dm_query_device(name, NULL, &seg_size, NULL, &seg_offset,
NULL, NULL, NULL, NULL, NULL, NULL);
r = dm_query_device(name, 0, &dmd);
if (r < 0)
return r;
if (offset >= (seg_offset + seg_size) || (offset + size) <= seg_offset)
if (offset >= (dmd.offset + dmd.size) || (offset + size) <= dmd.offset)
r = 0;
else
r = -EBUSY;
log_dbg("seg: %" PRIu64 " - %" PRIu64 ", new %" PRIu64 " - %" PRIu64 "%s",
seg_offset, seg_offset + seg_size, offset, offset + size,
dmd.offset, dmd.offset + dmd.size, offset, offset + size,
r ? " (overlapping)" : " (ok)");
return r;
......
......@@ -185,22 +185,26 @@ int LOOPAES_activate(struct crypt_device *cd,
const char *base_cipher,
unsigned int keys_count,
struct volume_key *vk,
uint64_t offset,
uint64_t skip,
uint32_t flags)
{
uint64_t size;
char *cipher = NULL;
uint32_t req_flags;
char *cipher;
const char *device;
int read_only, r;
size = 0;
/* Initial IV (skip) is always the same as offset */
device = crypt_get_device_name(cd);
read_only = flags & CRYPT_ACTIVATE_READONLY;
r = device_check_and_adjust(cd, device, DEV_EXCL, &size, &offset, &read_only);
int r;
struct crypt_dm_active_device dmd = {
.device = crypt_get_device_name(cd),
.cipher = NULL,
.uuid = crypt_get_uuid(cd),
.key = vk->key,
.key_size = vk->keylength,
.offset = crypt_get_data_offset(cd),
.iv_offset = skip,
.size = 0,
.flags = flags
};
r = device_check_and_adjust(cd, dmd.device, DEV_EXCL, &dmd.size, &dmd.offset, &flags);
if (r)
return r;
......@@ -214,12 +218,10 @@ int LOOPAES_activate(struct crypt_device *cd,
if (r < 0)
return -ENOMEM;
log_dbg("Trying to activate loop-AES device %s using cipher %s.", name, cipher);
r = dm_create_device(name, device,
cipher, CRYPT_LOOPAES,
crypt_get_uuid(cd),
size, skip, offset, vk->keylength, vk->key,
read_only, 0);
dmd.cipher = cipher;
log_dbg("Trying to activate loop-AES device %s using cipher %s.", name, dmd.cipher);
r = dm_create_device(name, CRYPT_LOOPAES, &dmd, 0);
if (!r && !(dm_flags() & req_flags)) {
log_err(cd, _("Kernel doesn't support loop-AES compatible mapping.\n"));
......
......@@ -18,7 +18,6 @@ int LOOPAES_activate(struct crypt_device *cd,
const char *base_cipher,
unsigned int keys_count,
struct volume_key *vk,
uint64_t offset,
uint64_t skip,
uint32_t flags);
#endif
......@@ -56,7 +56,17 @@ static int setup_mapping(const char *cipher, const char *name,
int mode, struct crypt_device *ctx)
{
int device_sector_size = sector_size_for_device(device);
uint64_t size;
struct crypt_dm_active_device dmd = {
.device = device,
.cipher = cipher,
.uuid = NULL,
.key = (char*)key,
.key_size = keyLength,
.offset = sector,
.iv_offset = 0,
.size = 0,
.flags = (mode == O_RDONLY) ? CRYPT_ACTIVATE_READONLY : 0
};
/*
* we need to round this to nearest multiple of the underlying
......@@ -66,11 +76,11 @@ static int setup_mapping(const char *cipher, const char *name,
log_err(ctx, _("Unable to obtain sector size for %s"), device);
return -EINVAL;
}
size = round_up_modulo(srcLength,device_sector_size)/SECTOR_SIZE;
cleaner_size = size;
return dm_create_device(name, device, cipher, "TEMP", NULL, size, 0, sector,
keyLength, key, (mode == O_RDONLY), 0);
dmd.size = round_up_modulo(srcLength,device_sector_size)/SECTOR_SIZE;
cleaner_size = dmd.size;
return dm_create_device(name, "TEMP", &dmd, 0);
}
static void sigint_handler(int sig __attribute__((unused)))
......
......@@ -897,3 +897,38 @@ int LUKS_keyslot_set(struct luks_phdr *hdr, int keyslot, int enable)
log_dbg("Key slot %d was %s in LUKS header.", keyslot, enable ? "enabled" : "disabled");
return 0;
}
int LUKS1_activate(struct crypt_device *cd,
const char *name,
struct volume_key *vk,
uint32_t flags)
{
int r;
char *dm_cipher = NULL;
struct crypt_dm_active_device dmd = {
.device = crypt_get_device_name(cd),
.cipher = NULL,
.uuid = crypt_get_uuid(cd),
.key = vk->key,
.key_size = vk->keylength,
.offset = crypt_get_data_offset(cd),
.iv_offset = 0,
.size = 0,
.flags = flags
};
r = device_check_and_adjust(cd, dmd.device, DEV_EXCL,
&dmd.size, &dmd.offset, &flags);
if (r)
return r;
r = asprintf(&dm_cipher, "%s-%s", crypt_get_cipher(cd), crypt_get_cipher_mode(cd));
if (r < 0)
return -ENOMEM;
dmd.cipher = dm_cipher;
r = dm_create_device(name, CRYPT_LUKS1, &dmd, 0);
free(dm_cipher);
return r;
}
......@@ -173,4 +173,9 @@ int LUKS_decrypt_from_storage(
unsigned int sector,
struct crypt_device *ctx);
int LUKS1_activate(struct crypt_device *cd,
const char *name,
struct volume_key *vk,
uint32_t flags);
#endif
This diff is collapsed.
......@@ -397,7 +397,7 @@ int device_check_and_adjust(struct crypt_device *cd,
enum devcheck device_check,
uint64_t *size,
uint64_t *offset,
int *read_only)
uint32_t *flags)
{
int r, real_readonly;
uint64_t real_size;
......@@ -442,10 +442,10 @@ int device_check_and_adjust(struct crypt_device *cd,
}
if (real_readonly)
*read_only = 1;
*flags |= CRYPT_ACTIVATE_READONLY;
log_dbg("Calculated device size is %" PRIu64 " sectors (%s), offset %" PRIu64 ".",
*size, *read_only ? "RO" : "RW", *offset);
*size, real_readonly ? "RO" : "RW", *offset);
return 0;
}
......
......@@ -13,27 +13,43 @@ struct crypt_device;
#define DM_PLAIN64_SUPPORTED (1 << 3) /* plain64 IV */
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)
struct crypt_dm_active_device {
const char *device;
const char *cipher;
const char *uuid;
char *key;
size_t key_size;
/* struct crypt_active_device */
uint64_t offset; /* offset in sectors */
uint64_t iv_offset; /* IV initilisation sector */
uint64_t size; /* active device size */
uint32_t flags; /* activation flags */
};
const char *dm_get_dir(void);
int dm_init(struct crypt_device *context, int check_kernel);
void dm_exit(void);
int dm_remove_device(const char *name, int force, uint64_t size);
int dm_status_device(const char *name);
int dm_query_device(const char *name,
char **device,
uint64_t *size,
uint64_t *skip,
uint64_t *offset,
char **cipher,
int *key_size,
char **key,
int *read_only,
int *suspended,
char **uuid);
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, uint64_t offset,
size_t key_size, const char *key,
int read_only, int reload);
int dm_status_suspended(const char *name);
int dm_query_device(const char *name, uint32_t get_flags,
struct crypt_dm_active_device *dmd);
int dm_create_device(const char *name,
const char *type,
struct crypt_dm_active_device *dmd,
int reload);
int dm_suspend_and_wipe_key(const char *name);
int dm_resume_and_reinstate_key(const char *name,
size_t key_size,
......
......@@ -33,6 +33,8 @@ struct volume_key *crypt_alloc_volume_key(unsigned keylength, const char *key)
vk->keylength = keylength;
if (key)
memcpy(&vk->key, key, keylength);
else
memset(&vk->key, 0, keylength);
return vk;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment