Unify dm backend for crypt/verity.

This commit is contained in:
Milan Broz
2012-06-08 10:12:12 +02:00
parent b016e65daa
commit c4b16923bb
7 changed files with 148 additions and 150 deletions

View File

@@ -300,15 +300,15 @@ out:
return params;
}
static char *get_dm_verity_params(struct crypt_params_verity *vp,
struct crypt_dm_active_verity *dmd)
struct crypt_dm_active_device *dmd)
{
int max_size, r;
char *params = NULL, *hexroot = NULL, *hexsalt = NULL;
hexroot = crypt_safe_alloc(dmd->root_hash_size * 2 + 1);
hexroot = crypt_safe_alloc(dmd->u.verity.root_hash_size * 2 + 1);
if (!hexroot)
goto out;
hex_key(hexroot, dmd->root_hash_size, dmd->root_hash);
hex_key(hexroot, dmd->u.verity.root_hash_size, dmd->u.verity.root_hash);
hexsalt = crypt_safe_alloc(vp->salt_size * 2 + 1);
if (!hexsalt)
@@ -316,7 +316,8 @@ static char *get_dm_verity_params(struct crypt_params_verity *vp,
hex_key(hexsalt, vp->salt_size, vp->salt);
max_size = strlen(hexroot) + strlen(hexsalt) +
strlen(dmd->data_device) + strlen(dmd->hash_device) +
strlen(dmd->u.verity.data_device) +
strlen(dmd->u.verity.hash_device) +
strlen(vp->hash_name) + 128;
params = crypt_safe_alloc(max_size);
@@ -325,9 +326,10 @@ static char *get_dm_verity_params(struct crypt_params_verity *vp,
r = snprintf(params, max_size,
"%u %s %s %u %u %" PRIu64 " %" PRIu64 " %s %s %s",
vp->version, dmd->data_device, dmd->hash_device,
vp->version, dmd->u.verity.data_device,
dmd->u.verity.hash_device,
vp->data_block_size, vp->hash_block_size,
vp->data_size, dmd->hash_offset,
vp->data_size, dmd->u.verity.hash_offset,
vp->hash_name, hexroot, hexsalt);
if (r < 0 || r >= max_size) {
crypt_safe_free(params);
@@ -579,11 +581,16 @@ out_no_removal:
int dm_create_device(const char *name,
const char *type,
struct crypt_dm_active_device *dmd,
void *params,
int reload)
{
char *table_params = NULL;
table_params = get_dm_crypt_params(dmd);
if (dmd->target == DM_CRYPT)
table_params = get_dm_crypt_params(dmd);
else if (dmd->target == DM_VERITY)
table_params = get_dm_verity_params(params, dmd);
if (!table_params)
return -EINVAL;
@@ -591,20 +598,6 @@ int dm_create_device(const char *name,
dmd->uuid, dmd->size, table_params, reload);
}
int dm_create_verity(const char *name,
struct crypt_params_verity *params,
struct crypt_dm_active_verity *dmd)
{
char *table_params = NULL;
table_params = get_dm_verity_params(params, dmd);
if (!table_params)
return -EINVAL;
return _dm_create_device(name, CRYPT_VERITY, dmd->data_device, dmd->flags,
NULL, dmd->size, table_params, 0);
}
static int dm_status_dmi(const char *name, struct dm_info *dmi,
const char *target, char **status_line)
{
@@ -691,16 +684,118 @@ int dm_status_verity_ok(const char *name)
return r;
}
static int _dm_query_crypt(uint32_t get_flags,
struct dm_info *dmi,
char *params,
struct crypt_dm_active_device *dmd)
{
uint64_t val64;
char *rcipher, *key_, *rdevice, *endp, buffer[3], *arg;
unsigned int i;
dmd->target = DM_CRYPT;
rcipher = strsep(&params, " ");
/* cipher */
if (get_flags & DM_ACTIVE_CIPHER)
dmd->u.crypt.cipher = strdup(rcipher);
/* skip */
key_ = strsep(&params, " ");
if (!params)
return -EINVAL;
val64 = strtoull(params, &params, 10);
if (*params != ' ')
return -EINVAL;
params++;
dmd->u.crypt.iv_offset = val64;
/* device */
rdevice = strsep(&params, " ");
if (get_flags & DM_ACTIVE_DEVICE)
dmd->u.crypt.device = crypt_lookup_dev(rdevice);
/*offset */
if (!params)
return -EINVAL;
val64 = strtoull(params, &params, 10);
dmd->u.crypt.offset = val64;
/* Features section, available since crypt target version 1.11 */
if (*params) {
if (*params != ' ')
return -EINVAL;
params++;
/* Number of arguments */
val64 = strtoull(params, &params, 10);
if (*params != ' ')
return -EINVAL;
params++;
for (i = 0; i < val64; i++) {
if (!params)
return -EINVAL;
arg = strsep(&params, " ");
if (!strcasecmp(arg, "allow_discards"))
dmd->flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
else /* unknown option */
return -EINVAL;
}
/* All parameters shold be processed */
if (params)
return -EINVAL;
}
/* Never allow to return empty key */
if ((get_flags & DM_ACTIVE_KEY) && dmi->suspended) {
log_dbg("Cannot read volume key while suspended.");
return -EINVAL;
}
if (get_flags & DM_ACTIVE_KEYSIZE) {
dmd->u.crypt.vk = crypt_alloc_volume_key(strlen(key_) / 2, NULL);
if (!dmd->u.crypt.vk)
return -ENOMEM;
if (get_flags & DM_ACTIVE_KEY) {
buffer[2] = '\0';
for(i = 0; i < dmd->u.crypt.vk->keylength; i++) {
memcpy(buffer, &key_[i * 2], 2);
dmd->u.crypt.vk->key[i] = strtoul(buffer, &endp, 16);
if (endp != &buffer[2]) {
crypt_free_volume_key(dmd->u.crypt.vk);
dmd->u.crypt.vk = NULL;
return -EINVAL;
}
}
}
}
memset(key_, 0, strlen(key_));
return 0;
}
static int _dm_query_verity(uint32_t get_flags,
struct dm_info *dmi,
char *params,
struct crypt_dm_active_device *dmd)
{
dmd->target = DM_VERITY;
return -EINVAL;
}
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;
uint64_t start, length, val64;
char *target_type, *params, *rcipher, *key_, *rdevice, *endp, buffer[3], *arg;
uint64_t start, length;
char *target_type, *params;
const char *tmp_uuid;
void *next = NULL;
unsigned int i;
int r = -EINVAL;
memset(dmd, 0, sizeof(*dmd));
@@ -724,103 +819,28 @@ int dm_query_device(const char *name, uint32_t get_flags,
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)
if (!target_type || start != 0 || next)
goto out;
if (!strcmp(target_type, DM_CRYPT_TARGET))
r = _dm_query_crypt(get_flags, &dmi, params, dmd);
else if (!strcmp(target_type, DM_VERITY_TARGET))
r = _dm_query_verity(get_flags, &dmi, params, dmd);
else
r = -EINVAL;
if (r < 0)
goto out;
dmd->size = length;
rcipher = strsep(&params, " ");
/* cipher */
if (get_flags & DM_ACTIVE_CIPHER)
dmd->u.crypt.cipher = strdup(rcipher);
/* skip */
key_ = strsep(&params, " ");
if (!params)
goto out;
val64 = strtoull(params, &params, 10);
if (*params != ' ')
goto out;
params++;
dmd->u.crypt.iv_offset = val64;
/* device */
rdevice = strsep(&params, " ");
if (get_flags & DM_ACTIVE_DEVICE)
dmd->u.crypt.device = crypt_lookup_dev(rdevice);
/*offset */
if (!params)
goto out;
val64 = strtoull(params, &params, 10);
dmd->u.crypt.offset = val64;
/* Features section, available since crypt target version 1.11 */
if (*params) {
if (*params != ' ')
goto out;
params++;
/* Number of arguments */
val64 = strtoull(params, &params, 10);
if (*params != ' ')
goto out;
params++;
for (i = 0; i < val64; i++) {
if (!params)
goto out;
arg = strsep(&params, " ");
if (!strcasecmp(arg, "allow_discards"))
dmd->flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
else /* unknown option */
goto out;
}
/* All parameters shold be processed */
if (params)
goto out;
}
/* 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->u.crypt.vk = crypt_alloc_volume_key(strlen(key_) / 2, NULL);
if (!dmd->u.crypt.vk) {
r = -ENOMEM;
goto out;
}
if (get_flags & DM_ACTIVE_KEY) {
buffer[2] = '\0';
for(i = 0; i < dmd->u.crypt.vk->keylength; i++) {
memcpy(buffer, &key_[i * 2], 2);
dmd->u.crypt.vk->key[i] = strtoul(buffer, &endp, 16);
if (endp != &buffer[2]) {
crypt_free_volume_key(dmd->u.crypt.vk);
dmd->u.crypt.vk = NULL;
r = -EINVAL;
goto out;
}
}
}
}
memset(key_, 0, strlen(key_));
if (dmi.read_only)
dmd->flags |= CRYPT_ACTIVATE_READONLY;
tmp_uuid = dm_task_get_uuid(dmt);
if (!tmp_uuid)
dmd->flags |= CRYPT_ACTIVATE_NO_UUID;
else if (get_flags & DM_ACTIVE_UUID) {
@@ -836,14 +856,6 @@ out:
return r;
}
int dm_query_verity(const char *name,
struct crypt_dm_active_verity *dmd)
{
int r = -EINVAL;
return r;
}
static int _dm_message(const char *name, const char *msg)
{
int r = 0;

View File

@@ -225,7 +225,7 @@ int LOOPAES_activate(struct crypt_device *cd,
log_dbg("Trying to activate loop-AES device %s using cipher %s.",
name, dmd.u.crypt.cipher);
r = dm_create_device(name, CRYPT_LOOPAES, &dmd, 0);
r = dm_create_device(name, CRYPT_LOOPAES, &dmd, NULL, 0);
if (!r && !(dm_flags() & req_flags)) {
log_err(cd, _("Kernel doesn't support loop-AES compatible mapping.\n"));

View File

@@ -86,7 +86,7 @@ static int setup_mapping(const char *cipher, const char *name,
dmd.size = round_up_modulo(srcLength,device_sector_size)/SECTOR_SIZE;
cleaner_size = dmd.size;
return dm_create_device(name, "TEMP", &dmd, 0);
return dm_create_device(name, "TEMP", &dmd, NULL, 0);
}
static void sigint_handler(int sig __attribute__((unused)))

View File

@@ -1062,7 +1062,7 @@ int LUKS1_activate(struct crypt_device *cd,
return -ENOMEM;
dmd.u.crypt.cipher = dm_cipher;
r = dm_create_device(name, CRYPT_LUKS1, &dmd, 0);
r = dm_create_device(name, CRYPT_LUKS1, &dmd, NULL, 0);
free(dm_cipher);
return r;

View File

@@ -335,7 +335,7 @@ int PLAIN_activate(struct crypt_device *cd,
log_dbg("Trying to activate PLAIN device %s using cipher %s.",
name, dmd.u.crypt.cipher);
r = dm_create_device(name, CRYPT_PLAIN, &dmd, 0);
r = dm_create_device(name, CRYPT_PLAIN, &dmd, NULL, 0);
// FIXME
if (!cd->plain_uuid && dm_query_device(name, DM_ACTIVE_UUID, &dmd) >= 0)
@@ -1195,7 +1195,7 @@ int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size)
r = 0;
} else {
dmd.size = new_size;
r = dm_create_device(name, cd->type, &dmd, 1);
r = dm_create_device(name, cd->type, &dmd, NULL, 1);
}
out:
crypt_free_volume_key(dmd.u.crypt.vk);

View File

@@ -73,18 +73,6 @@ struct crypt_dm_active_device {
} u;
};
struct crypt_dm_active_verity {
const char *data_device;
const char *hash_device;
const char *root_hash;
size_t root_hash_size;
uint64_t hash_offset; /* hash offset (not header) */
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);
@@ -94,15 +82,11 @@ int dm_status_suspended(const char *name);
int dm_status_verity_ok(const char *name);
int dm_query_device(const char *name, uint32_t get_flags,
struct crypt_dm_active_device *dmd);
int dm_query_verity(const char *name,
struct crypt_dm_active_verity *dmd);
int dm_create_device(const char *name,
const char *type,
struct crypt_dm_active_device *dmd,
void *params,
int reload);
int dm_create_verity(const char *name,
struct crypt_params_verity *params,
struct crypt_dm_active_verity *dmd);
int dm_suspend_and_wipe_key(const char *name);
int dm_resume_and_reinstate_key(const char *name,
size_t key_size,

View File

@@ -155,7 +155,7 @@ int VERITY_activate(struct crypt_device *cd,
struct crypt_params_verity *verity_hdr,
uint32_t flags)
{
struct crypt_dm_active_verity dmd;
struct crypt_dm_active_device dmd;
uint64_t offset = 0;
int r;
@@ -173,20 +173,22 @@ int VERITY_activate(struct crypt_device *cd,
if (!name)
return 0;
dmd.data_device = crypt_get_device_name(cd);
dmd.hash_device = hash_device;
dmd.root_hash = root_hash;
dmd.root_hash_size = root_hash_size;
dmd.hash_offset = VERITY_hash_offset_block(verity_hdr),
dmd.target = DM_VERITY;
dmd.u.verity.data_device = crypt_get_device_name(cd);
dmd.u.verity.hash_device = hash_device;
dmd.u.verity.root_hash = root_hash;
dmd.u.verity.root_hash_size = root_hash_size;
dmd.u.verity.hash_offset = VERITY_hash_offset_block(verity_hdr),
dmd.flags = CRYPT_ACTIVATE_READONLY;
dmd.size = verity_hdr->data_size * verity_hdr->data_block_size / 512;
dmd.uuid = NULL;
r = device_check_and_adjust(cd, dmd.data_device, DEV_EXCL,
r = device_check_and_adjust(cd, dmd.u.verity.data_device, DEV_EXCL,
&dmd.size, &offset, &dmd.flags);
if (r)
return r;
r = dm_create_verity(name, verity_hdr, &dmd);
r = dm_create_device(name, CRYPT_VERITY, &dmd, verity_hdr, 0);
if (!r && !(dm_flags() & DM_VERITY_SUPPORTED)) {
log_err(cd, _("Kernel doesn't support dm-verity mapping.\n"));
return -ENOTSUP;