mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-13 11:50:10 +01:00
Unify dm backend for crypt/verity.
This commit is contained in:
@@ -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(¶ms, " ");
|
||||
/* cipher */
|
||||
if (get_flags & DM_ACTIVE_CIPHER)
|
||||
dmd->u.crypt.cipher = strdup(rcipher);
|
||||
|
||||
/* skip */
|
||||
key_ = strsep(¶ms, " ");
|
||||
if (!params)
|
||||
return -EINVAL;
|
||||
val64 = strtoull(params, ¶ms, 10);
|
||||
if (*params != ' ')
|
||||
return -EINVAL;
|
||||
params++;
|
||||
|
||||
dmd->u.crypt.iv_offset = val64;
|
||||
|
||||
/* device */
|
||||
rdevice = strsep(¶ms, " ");
|
||||
if (get_flags & DM_ACTIVE_DEVICE)
|
||||
dmd->u.crypt.device = crypt_lookup_dev(rdevice);
|
||||
|
||||
/*offset */
|
||||
if (!params)
|
||||
return -EINVAL;
|
||||
val64 = strtoull(params, ¶ms, 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, ¶ms, 10);
|
||||
if (*params != ' ')
|
||||
return -EINVAL;
|
||||
params++;
|
||||
|
||||
for (i = 0; i < val64; i++) {
|
||||
if (!params)
|
||||
return -EINVAL;
|
||||
arg = strsep(¶ms, " ");
|
||||
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, ¶ms);
|
||||
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(¶ms, " ");
|
||||
/* cipher */
|
||||
if (get_flags & DM_ACTIVE_CIPHER)
|
||||
dmd->u.crypt.cipher = strdup(rcipher);
|
||||
|
||||
/* skip */
|
||||
key_ = strsep(¶ms, " ");
|
||||
if (!params)
|
||||
goto out;
|
||||
val64 = strtoull(params, ¶ms, 10);
|
||||
if (*params != ' ')
|
||||
goto out;
|
||||
params++;
|
||||
|
||||
dmd->u.crypt.iv_offset = val64;
|
||||
|
||||
/* device */
|
||||
rdevice = strsep(¶ms, " ");
|
||||
if (get_flags & DM_ACTIVE_DEVICE)
|
||||
dmd->u.crypt.device = crypt_lookup_dev(rdevice);
|
||||
|
||||
/*offset */
|
||||
if (!params)
|
||||
goto out;
|
||||
val64 = strtoull(params, ¶ms, 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, ¶ms, 10);
|
||||
if (*params != ' ')
|
||||
goto out;
|
||||
params++;
|
||||
|
||||
for (i = 0; i < val64; i++) {
|
||||
if (!params)
|
||||
goto out;
|
||||
arg = strsep(¶ms, " ");
|
||||
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;
|
||||
|
||||
@@ -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"));
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user