Support init_by_name for verity.

This commit is contained in:
Milan Broz
2012-06-08 16:38:26 +02:00
parent cdae1b4c60
commit ce2218ed65
9 changed files with 344 additions and 121 deletions

View File

@@ -256,12 +256,31 @@ static void hex_key(char *hexkey, size_t key_size, const char *key)
sprintf(&hexkey[i * 2], "%02x", (unsigned char)key[i]);
}
static int hex_to_bytes(const char *hex, char *result)
{
char buf[3] = "xx\0", *endp;
int i, len;
len = strlen(hex) / 2;
for (i = 0; i < len; i++) {
memcpy(buf, &hex[i * 2], 2);
result[i] = strtoul(buf, &endp, 16);
if (endp != &buf[2])
return -EINVAL;
}
return i;
}
/* http://code.google.com/p/cryptsetup/wiki/DMCrypt */
static char *get_dm_crypt_params(struct crypt_dm_active_device *dmd)
{
int r, max_size, null_cipher = 0;
char *params, *hexkey;
const char *features = "";
if (!dmd)
return NULL;
if (dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) {
if (dm_flags() & DM_DISCARDS_SUPPORTED) {
features = " 1 allow_discards";
@@ -283,14 +302,14 @@ static char *get_dm_crypt_params(struct crypt_dm_active_device *dmd)
hex_key(hexkey, dmd->u.crypt.vk->keylength, dmd->u.crypt.vk->key);
max_size = strlen(hexkey) + strlen(dmd->u.crypt.cipher) +
strlen(dmd->u.crypt.device) + strlen(features) + 64;
strlen(dmd->data_device) + strlen(features) + 64;
params = crypt_safe_alloc(max_size);
if (!params)
goto out;
r = snprintf(params, max_size, "%s %s %" PRIu64 " %s %" PRIu64 "%s",
dmd->u.crypt.cipher, hexkey, dmd->u.crypt.iv_offset,
dmd->u.crypt.device, dmd->u.crypt.offset, features);
dmd->data_device, dmd->u.crypt.offset, features);
if (r < 0 || r >= max_size) {
crypt_safe_free(params);
params = NULL;
@@ -299,12 +318,17 @@ out:
crypt_safe_free(hexkey);
return params;
}
/* http://code.google.com/p/cryptsetup/wiki/DMVerity */
static char *get_dm_verity_params(struct crypt_params_verity *vp,
struct crypt_dm_active_device *dmd)
{
int max_size, r;
char *params = NULL, *hexroot = NULL, *hexsalt = NULL;
if (!vp || !dmd)
return NULL;
hexroot = crypt_safe_alloc(dmd->u.verity.root_hash_size * 2 + 1);
if (!hexroot)
goto out;
@@ -316,7 +340,7 @@ 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->u.verity.data_device) +
strlen(dmd->data_device) +
strlen(dmd->u.verity.hash_device) +
strlen(vp->hash_name) + 128;
@@ -326,7 +350,7 @@ 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->u.verity.data_device,
vp->version, dmd->data_device,
dmd->u.verity.hash_device,
vp->data_block_size, vp->hash_block_size,
vp->data_size, dmd->u.verity.hash_offset,
@@ -581,7 +605,6 @@ 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;
@@ -589,12 +612,12 @@ int dm_create_device(const char *name,
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);
table_params = get_dm_verity_params(dmd->u.verity.vp, dmd);
if (!table_params)
return -EINVAL;
return _dm_create_device(name, type, dmd->u.crypt.device, dmd->flags,
return _dm_create_device(name, type, dmd->data_device, dmd->flags,
dmd->uuid, dmd->size, table_params, reload);
}
@@ -626,11 +649,18 @@ static int dm_status_dmi(const char *name, struct dm_info *dmi,
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
if (!target_type || strcmp(target_type, target) != 0 ||
start != 0 || next)
r = -EINVAL;
else
r = 0;
if (!target_type || start != 0 || next)
goto out;
if (target && strcmp(target_type, target))
goto out;
/* for target == NULL check all supported */
if (!target && (strcmp(target_type, DM_CRYPT_TARGET) &&
strcmp(target_type, DM_VERITY_TARGET)))
goto out;
r = 0;
out:
if (!r && status_line && !(*status_line = strdup(params)))
r = -ENOMEM;
@@ -646,7 +676,7 @@ int dm_status_device(const char *name)
int r;
struct dm_info dmi;
r = dm_status_dmi(name, &dmi, DM_CRYPT_TARGET, NULL);
r = dm_status_dmi(name, &dmi, NULL, NULL);
if (r < 0)
return r;
@@ -684,6 +714,7 @@ int dm_status_verity_ok(const char *name)
return r;
}
/* FIXME use hex wrapper, user val wrappers for line parsing */
static int _dm_query_crypt(uint32_t get_flags,
struct dm_info *dmi,
char *params,
@@ -693,11 +724,12 @@ static int _dm_query_crypt(uint32_t get_flags,
char *rcipher, *key_, *rdevice, *endp, buffer[3], *arg;
unsigned int i;
memset(dmd, 0, sizeof(*dmd));
dmd->target = DM_CRYPT;
rcipher = strsep(&params, " ");
/* cipher */
if (get_flags & DM_ACTIVE_CIPHER)
if (get_flags & DM_ACTIVE_CRYPT_CIPHER)
dmd->u.crypt.cipher = strdup(rcipher);
/* skip */
@@ -714,7 +746,7 @@ static int _dm_query_crypt(uint32_t get_flags,
/* device */
rdevice = strsep(&params, " ");
if (get_flags & DM_ACTIVE_DEVICE)
dmd->u.crypt.device = crypt_lookup_dev(rdevice);
dmd->data_device = crypt_lookup_dev(rdevice);
/*offset */
if (!params)
@@ -750,17 +782,17 @@ static int _dm_query_crypt(uint32_t get_flags,
}
/* Never allow to return empty key */
if ((get_flags & DM_ACTIVE_KEY) && dmi->suspended) {
if ((get_flags & DM_ACTIVE_CRYPT_KEY) && dmi->suspended) {
log_dbg("Cannot read volume key while suspended.");
return -EINVAL;
}
if (get_flags & DM_ACTIVE_KEYSIZE) {
if (get_flags & DM_ACTIVE_CRYPT_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) {
if (get_flags & DM_ACTIVE_CRYPT_KEY) {
buffer[2] = '\0';
for(i = 0; i < dmd->u.crypt.vk->keylength; i++) {
memcpy(buffer, &key_[i * 2], 2);
@@ -783,8 +815,109 @@ static int _dm_query_verity(uint32_t get_flags,
char *params,
struct crypt_dm_active_device *dmd)
{
struct crypt_params_verity *vp = NULL;
uint32_t val32;
uint64_t val64;
size_t len;
char *str, *str2;
if (get_flags & DM_ACTIVE_VERITY_PARAMS)
vp = dmd->u.verity.vp;
memset(dmd, 0, sizeof(*dmd));
dmd->target = DM_VERITY;
return -EINVAL;
dmd->u.verity.vp = vp;
/* version */
val32 = strtoul(params, &params, 10);
if (*params != ' ')
return -EINVAL;
if (vp)
vp->version = val32;
params++;
/* data device */
str = strsep(&params, " ");
if (!params)
return -EINVAL;
if (get_flags & DM_ACTIVE_DEVICE)
dmd->data_device = crypt_lookup_dev(str);
/* hash device */
str = strsep(&params, " ");
if (!params)
return -EINVAL;
if (get_flags & DM_ACTIVE_VERITY_HASH_DEVICE)
dmd->u.verity.hash_device = crypt_lookup_dev(str);
/* data block size*/
val32 = strtoul(params, &params, 10);
if (*params != ' ')
return -EINVAL;
if (vp)
vp->data_block_size = val32;
params++;
/* hash block size */
val32 = strtoul(params, &params, 10);
if (*params != ' ')
return -EINVAL;
if (vp)
vp->hash_block_size = val32;
params++;
/* data blocks */
val64 = strtoull(params, &params, 10);
if (*params != ' ')
return -EINVAL;
if (vp)
vp->data_size = val64;
params++;
/* hash start */
val64 = strtoull(params, &params, 10);
if (*params != ' ')
return -EINVAL;
dmd->u.verity.hash_offset = val64;
params++;
/* hash algorithm */
str = strsep(&params, " ");
if (!params)
return -EINVAL;
if (vp)
vp->hash_name = strdup(str);
/* root digest */
str = strsep(&params, " ");
if (!params)
return -EINVAL;
len = strlen(str) / 2;
dmd->u.verity.root_hash_size = len;
if (get_flags & DM_ACTIVE_VERITY_ROOT_HASH) {
if (!(str2 = malloc(len)))
return -ENOMEM;
if (hex_to_bytes(str, str2) != len)
return -EINVAL;
dmd->u.verity.root_hash = str2;
}
/* salt */
str = strsep(&params, " ");
if (params)
return -EINVAL;
if (vp) {
len = strlen(str) / 2;
vp->salt_size = len;
if (!(str2 = malloc(len)))
return -ENOMEM;
if (hex_to_bytes(str, str2) != len)
return -EINVAL;
vp->salt = str2;
}
return 0;
}
int dm_query_device(const char *name, uint32_t get_flags,
@@ -798,8 +931,6 @@ int dm_query_device(const char *name, uint32_t get_flags,
void *next = NULL;
int r = -EINVAL;
memset(dmd, 0, sizeof(*dmd));
if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
goto out;
if ((dm_flags() & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt))

View File

@@ -196,8 +196,8 @@ int LOOPAES_activate(struct crypt_device *cd,
.uuid = crypt_get_uuid(cd),
.size = 0,
.flags = flags,
.data_device = crypt_get_device_name(cd),
.u.crypt = {
.device = crypt_get_device_name(cd),
.cipher = NULL,
.vk = vk,
.offset = crypt_get_data_offset(cd),
@@ -206,7 +206,7 @@ int LOOPAES_activate(struct crypt_device *cd,
};
r = device_check_and_adjust(cd, dmd.u.crypt.device, DEV_EXCL,
r = device_check_and_adjust(cd, dmd.data_device, DEV_EXCL,
&dmd.size, &dmd.u.crypt.offset, &flags);
if (r)
return r;
@@ -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, NULL, 0);
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"));

View File

@@ -62,8 +62,8 @@ static int setup_mapping(const char *cipher, const char *name,
.uuid = NULL,
.size = 0,
.flags = 0,
.data_device = device,
.u.crypt = {
.device = device,
.cipher = cipher,
.vk = vk,
.offset = sector,
@@ -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, NULL, 0);
return dm_create_device(name, "TEMP", &dmd, 0);
}
static void sigint_handler(int sig __attribute__((unused)))

View File

@@ -1037,8 +1037,8 @@ int LUKS1_activate(struct crypt_device *cd,
.uuid = crypt_get_uuid(cd),
.flags = flags,
.size = 0,
.data_device = crypt_get_device_name(cd),
.u.crypt = {
.device = crypt_get_device_name(cd),
.cipher = NULL,
.vk = vk,
.offset = crypt_get_data_offset(cd),
@@ -1051,7 +1051,7 @@ int LUKS1_activate(struct crypt_device *cd,
else
device_check = DEV_EXCL;
r = device_check_and_adjust(cd, dmd.u.crypt.device, device_check,
r = device_check_and_adjust(cd, dmd.data_device, device_check,
&dmd.size, &dmd.u.crypt.offset,
&dmd.flags);
if (r)
@@ -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, NULL, 0);
r = dm_create_device(name, CRYPT_LUKS1, &dmd, 0);
free(dm_cipher);
return r;

View File

@@ -305,8 +305,8 @@ int PLAIN_activate(struct crypt_device *cd,
.uuid = crypt_get_uuid(cd),
.size = size,
.flags = flags,
.data_device = crypt_get_device_name(cd),
.u.crypt = {
.device = crypt_get_device_name(cd),
.cipher = NULL,
.vk = vk,
.offset = crypt_get_data_offset(cd),
@@ -319,7 +319,7 @@ int PLAIN_activate(struct crypt_device *cd,
else
device_check = DEV_EXCL;
r = device_check_and_adjust(cd, dmd.u.crypt.device, device_check,
r = device_check_and_adjust(cd, dmd.data_device, device_check,
&dmd.size, &dmd.u.crypt.offset, &dmd.flags);
if (r)
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, NULL, 0);
r = dm_create_device(name, CRYPT_PLAIN, &dmd, 0);
// FIXME
if (!cd->plain_uuid && dm_query_device(name, DM_ACTIVE_UUID, &dmd) >= 0)
@@ -677,15 +677,121 @@ static int _crypt_load_verity(struct crypt_device *cd, struct crypt_params_verit
return r;
}
static int _init_by_name_crypt(struct crypt_device *cd, const char *name)
{
struct crypt_dm_active_device dmd = {};
char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
int key_nums, r;
r = dm_query_device(name, DM_ACTIVE_DEVICE |
DM_ACTIVE_UUID |
DM_ACTIVE_CRYPT_CIPHER |
DM_ACTIVE_CRYPT_KEYSIZE, &dmd);
if (r < 0)
goto out;
if (isPLAIN(cd->type)) {
cd->plain_uuid = dmd.uuid ? strdup(dmd.uuid) : NULL;
cd->plain_hdr.hash = NULL; /* no way to get this */
cd->plain_hdr.offset = dmd.u.crypt.offset;
cd->plain_hdr.skip = dmd.u.crypt.iv_offset;
cd->plain_key_size = dmd.u.crypt.vk->keylength;
r = crypt_parse_name_and_mode(dmd.u.crypt.cipher, cipher, NULL, cipher_mode);
if (!r) {
cd->plain_cipher = strdup(cipher);
cd->plain_cipher_mode = strdup(cipher_mode);
}
} else if (isLOOPAES(cd->type)) {
cd->loopaes_uuid = dmd.uuid ? strdup(dmd.uuid) : NULL;
cd->loopaes_hdr.offset = dmd.u.crypt.offset;
r = crypt_parse_name_and_mode(dmd.u.crypt.cipher, cipher,
&key_nums, cipher_mode);
if (!r) {
cd->loopaes_cipher = strdup(cipher);
cd->loopaes_cipher_mode = strdup(cipher_mode);
/* version 3 uses last key for IV */
if (dmd.u.crypt.vk->keylength % key_nums)
key_nums++;
cd->loopaes_key_size = dmd.u.crypt.vk->keylength / key_nums;
}
} else if (isLUKS(cd->type)) {
if (mdata_device(cd)) {
r = _crypt_load_luks1(cd, 0, 0);
if (r < 0) {
log_dbg("LUKS device header does not match active device.");
free(cd->type);
cd->type = NULL;
r = 0;
goto out;
}
/* check whether UUIDs match each other */
r = crypt_uuid_cmp(dmd.uuid, cd->hdr.uuid);
if (r < 0) {
log_dbg("LUKS device header uuid: %s mismatches DM returned uuid %s",
cd->hdr.uuid, dmd.uuid);
free(cd->type);
cd->type = NULL;
r = 0;
goto out;
}
}
}
out:
crypt_free_volume_key(dmd.u.crypt.vk);
free(CONST_CAST(void*)dmd.u.crypt.cipher);
free(CONST_CAST(void*)dmd.data_device);
free(CONST_CAST(void*)dmd.uuid);
return r;
}
static int _init_by_name_verity(struct crypt_device *cd, const char *name)
{
struct crypt_params_verity params = {};
struct crypt_dm_active_device dmd = {
.target = DM_VERITY,
.u.verity.vp = &params,
};
int r;
r = dm_query_device(name, DM_ACTIVE_DEVICE |
DM_ACTIVE_UUID |
DM_ACTIVE_VERITY_HASH_DEVICE |
DM_ACTIVE_VERITY_PARAMS, &dmd);
if (r < 0)
goto out;
if (isVERITY(cd->type)) {
cd->verity_flags = CRYPT_VERITY_NO_HEADER; //FIXME
//cd->verity_uuid = dmd.uuid ? strdup(dmd.uuid) : NULL;
cd->verity_hdr.data_size = params.data_size;
cd->verity_root_hash_size = dmd.u.verity.root_hash_size;
cd->verity_root_hash = NULL;
cd->verity_hdr.hash_name = params.hash_name;
cd->verity_hdr.data_device = NULL;
cd->verity_hdr.data_block_size = params.data_block_size;
cd->verity_hdr.hash_block_size = params.hash_block_size;
cd->verity_hdr.hash_area_offset = params.hash_area_offset;
cd->verity_hdr.version = params.version;
cd->verity_hdr.flags = params.flags;
cd->verity_hdr.salt_size = params.salt_size;
cd->verity_hdr.salt = params.salt;
}
out:
free(CONST_CAST(void*)dmd.u.verity.hash_device);
free(CONST_CAST(void*)dmd.data_device);
free(CONST_CAST(void*)dmd.uuid);
return r;
}
int crypt_init_by_name_and_header(struct crypt_device **cd,
const char *name,
const char *header_device)
{
crypt_status_info ci;
struct crypt_dm_active_device dmd;
char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
int key_nums, r;
int r;
log_dbg("Allocating crypt device context by device %s.", name);
@@ -698,8 +804,7 @@ int crypt_init_by_name_and_header(struct crypt_device **cd,
return -ENODEV;
}
r = dm_query_device(name, DM_ACTIVE_DEVICE | DM_ACTIVE_CIPHER |
DM_ACTIVE_UUID | DM_ACTIVE_KEYSIZE, &dmd);
r = dm_query_device(name, DM_ACTIVE_DEVICE | DM_ACTIVE_UUID, &dmd);
if (r < 0)
goto out;
@@ -708,17 +813,17 @@ int crypt_init_by_name_and_header(struct crypt_device **cd,
if (header_device) {
r = crypt_init(cd, header_device);
} else {
r = crypt_init(cd, dmd.u.crypt.device);
r = crypt_init(cd, dmd.data_device);
/* Underlying device disappeared but mapping still active */
if (!dmd.u.crypt.device || r == -ENOTBLK)
if (!dmd.data_device || r == -ENOTBLK)
log_verbose(NULL, _("Underlying device for crypt device %s disappeared.\n"),
name);
/* Underlying device is not readable but crypt mapping exists */
if (r == -ENOTBLK) {
free(CONST_CAST(void*)dmd.u.crypt.device);
dmd.u.crypt.device = NULL;
free(CONST_CAST(void*)dmd.data_device);
dmd.data_device = NULL;
r = crypt_init(cd, NULL);
}
}
@@ -733,83 +838,38 @@ int crypt_init_by_name_and_header(struct crypt_device **cd,
(*cd)->type = strdup(CRYPT_LOOPAES);
else if (!strncmp(CRYPT_LUKS1, dmd.uuid, sizeof(CRYPT_LUKS1)-1))
(*cd)->type = strdup(CRYPT_LUKS1);
else if (!strncmp(CRYPT_VERITY, dmd.uuid, sizeof(CRYPT_VERITY)-1))
(*cd)->type = strdup(CRYPT_VERITY);
else
log_dbg("Unknown UUID set, some parameters are not set.");
} else
log_dbg("Active device has no UUID set, some parameters are not set.");
if (header_device) {
r = crypt_set_data_device(*cd, dmd.u.crypt.device);
r = crypt_set_data_device(*cd, dmd.data_device);
if (r < 0)
goto out;
}
/* Try to initialise basic parameters from active device */
if (!(*cd)->backing_file && dmd.u.crypt.device &&
crypt_loop_device(dmd.u.crypt.device) &&
!((*cd)->backing_file = crypt_loop_backing_file(dmd.u.crypt.device))) {
if (!(*cd)->backing_file && dmd.data_device &&
crypt_loop_device(dmd.data_device) &&
!((*cd)->backing_file = crypt_loop_backing_file(dmd.data_device))) {
r = -ENOMEM;
goto out;
}
if (isPLAIN((*cd)->type)) {
(*cd)->plain_uuid = dmd.uuid ? strdup(dmd.uuid) : NULL;
(*cd)->plain_hdr.hash = NULL; /* no way to get this */
(*cd)->plain_hdr.offset = dmd.u.crypt.offset;
(*cd)->plain_hdr.skip = dmd.u.crypt.iv_offset;
(*cd)->plain_key_size = dmd.u.crypt.vk->keylength;
r = crypt_parse_name_and_mode(dmd.u.crypt.cipher, cipher, NULL, cipher_mode);
if (!r) {
(*cd)->plain_cipher = strdup(cipher);
(*cd)->plain_cipher_mode = strdup(cipher_mode);
}
} else if (isLOOPAES((*cd)->type)) {
(*cd)->loopaes_uuid = dmd.uuid ? strdup(dmd.uuid) : NULL;
(*cd)->loopaes_hdr.offset = dmd.u.crypt.offset;
r = crypt_parse_name_and_mode(dmd.u.crypt.cipher, cipher,
&key_nums, cipher_mode);
if (!r) {
(*cd)->loopaes_cipher = strdup(cipher);
(*cd)->loopaes_cipher_mode = strdup(cipher_mode);
/* version 3 uses last key for IV */
if (dmd.u.crypt.vk->keylength % key_nums)
key_nums++;
(*cd)->loopaes_key_size = dmd.u.crypt.vk->keylength / key_nums;
}
} else if (isLUKS((*cd)->type)) {
if (mdata_device(*cd)) {
r = _crypt_load_luks1(*cd, 0, 0);
if (r < 0) {
log_dbg("LUKS device header does not match active device.");
free((*cd)->type);
(*cd)->type = NULL;
r = 0;
goto out;
}
/* checks whether UUIDs match each other */
r = crypt_uuid_cmp(dmd.uuid, (*cd)->hdr.uuid);
if (r < 0) {
log_dbg("LUKS device header uuid: %s mismatches DM returned uuid %s",
(*cd)->hdr.uuid, dmd.uuid);
free((*cd)->type);
(*cd)->type = NULL;
r = 0;
goto out;
}
}
}
if (dmd.target == DM_CRYPT)
r = _init_by_name_crypt(*cd, name);
else if (dmd.target == DM_VERITY)
r = _init_by_name_verity(*cd, name);
out:
if (r < 0) {
crypt_free(*cd);
*cd = NULL;
}
crypt_free_volume_key(dmd.u.crypt.vk);
free(CONST_CAST(void*)dmd.u.crypt.device);
free(CONST_CAST(void*)dmd.u.crypt.cipher);
free(CONST_CAST(void*)dmd.data_device);
free(CONST_CAST(void*)dmd.uuid);
return r;
}
@@ -1171,20 +1231,20 @@ int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size)
log_dbg("Resizing device %s to %" PRIu64 " sectors.", name, new_size);
r = dm_query_device(name, DM_ACTIVE_DEVICE | DM_ACTIVE_CIPHER |
DM_ACTIVE_UUID | DM_ACTIVE_KEYSIZE |
DM_ACTIVE_KEY, &dmd);
r = dm_query_device(name, DM_ACTIVE_DEVICE | DM_ACTIVE_CRYPT_CIPHER |
DM_ACTIVE_UUID | DM_ACTIVE_CRYPT_KEYSIZE |
DM_ACTIVE_CRYPT_KEY, &dmd);
if (r < 0) {
log_err(NULL, _("Device %s is not active.\n"), name);
goto out;
return -EINVAL;
}
if (!dmd.uuid) {
if (!dmd.uuid || dmd.target != DM_CRYPT) {
r = -EINVAL;
goto out;
}
r = device_check_and_adjust(cd, dmd.u.crypt.device, DEV_OK, &new_size,
r = device_check_and_adjust(cd, dmd.data_device, DEV_OK, &new_size,
&dmd.u.crypt.offset, &dmd.flags);
if (r)
goto out;
@@ -1195,12 +1255,14 @@ 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, NULL, 1);
r = dm_create_device(name, cd->type, &dmd, 1);
}
out:
crypt_free_volume_key(dmd.u.crypt.vk);
free(CONST_CAST(void*)dmd.u.crypt.cipher);
free(CONST_CAST(void*)dmd.u.crypt.device);
if (dmd.target == DM_CRYPT) {
crypt_free_volume_key(dmd.u.crypt.vk);
free(CONST_CAST(void*)dmd.u.crypt.cipher);
}
free(CONST_CAST(void*)dmd.data_device);
free(CONST_CAST(void*)dmd.uuid);
return r;
@@ -2342,6 +2404,9 @@ int crypt_get_active_device(struct crypt_device *cd __attribute__((unused)),
if (r < 0)
return r;
if (dmd.target != DM_CRYPT)
return -ENOTSUP;
cad->offset = dmd.u.crypt.offset;
cad->iv_offset = dmd.u.crypt.iv_offset;
cad->size = dmd.size;

View File

@@ -39,19 +39,24 @@ struct crypt_params_verity;
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_KEYSIZE (1 << 3)
#define DM_ACTIVE_KEY (1 << 4)
#define DM_ACTIVE_UUID (1 << 1)
#define DM_ACTIVE_CRYPT_CIPHER (1 << 2)
#define DM_ACTIVE_CRYPT_KEYSIZE (1 << 3)
#define DM_ACTIVE_CRYPT_KEY (1 << 4)
#define DM_ACTIVE_VERITY_ROOT_HASH (1 << 5)
#define DM_ACTIVE_VERITY_HASH_DEVICE (1 << 6)
#define DM_ACTIVE_VERITY_PARAMS (1 << 7)
struct crypt_dm_active_device {
enum { DM_CRYPT = 0, DM_VERITY } target;
uint64_t size; /* active device size */
uint32_t flags; /* activation flags */
const char *uuid;
const char *data_device;
union {
struct {
const char *device;
const char *cipher;
/* Active key for device */
@@ -62,13 +67,13 @@ struct crypt_dm_active_device {
uint64_t iv_offset; /* IV initilisation sector */
} crypt;
struct {
const char *data_device;
const char *hash_device;
const char *root_hash;
size_t root_hash_size;
uint32_t root_hash_size;
uint64_t hash_offset; /* hash offset (not header) */
struct crypt_params_verity *vp;
} verity;
} u;
};
@@ -85,7 +90,6 @@ int dm_query_device(const char *name, uint32_t get_flags,
int dm_create_device(const char *name,
const char *type,
struct crypt_dm_active_device *dmd,
void *params,
int reload);
int dm_suspend_and_wipe_key(const char *name);
int dm_resume_and_reinstate_key(const char *name,

View File

@@ -190,7 +190,7 @@ int VERITY_activate(struct crypt_device *cd,
return 0;
dmd.target = DM_VERITY;
dmd.u.verity.data_device = crypt_get_device_name(cd);
dmd.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;
@@ -198,13 +198,14 @@ int VERITY_activate(struct crypt_device *cd,
dmd.flags = CRYPT_ACTIVATE_READONLY;
dmd.size = verity_hdr->data_size * verity_hdr->data_block_size / 512;
dmd.uuid = NULL;
dmd.u.verity.vp = verity_hdr;
r = device_check_and_adjust(cd, dmd.u.verity.data_device, DEV_EXCL,
r = device_check_and_adjust(cd, dmd.data_device, DEV_EXCL,
&dmd.size, &offset, &dmd.flags);
if (r)
return r;
r = dm_create_device(name, CRYPT_VERITY, &dmd, verity_hdr, 0);
r = dm_create_device(name, CRYPT_VERITY, &dmd, 0);
if (!r && !(dm_flags() & DM_VERITY_SUPPORTED)) {
log_err(cd, _("Kernel doesn't support dm-verity mapping.\n"));
return -ENOTSUP;

View File

@@ -489,6 +489,8 @@ static int action_status(int arg __attribute__((unused)))
}
out:
crypt_free(cd);
if (r == -ENOTSUP)
r = 0;
return r;
}

View File

@@ -18,11 +18,11 @@
*/
/* TODO:
* - init_by_name()
* - support device without superblock
* - audit alloc errors / error path
* - change command names (cryptsetup style)
* - extend superblock (UUID)
* - add api tests
*/
#include <stdio.h>
@@ -40,6 +40,7 @@
#define MODE_CREATE 1
#define MODE_ACTIVATE 2
#define MODE_DUMP 3
#define MODE_STATUS 4
static int mode = -1;
static int use_superblock = 1; /* FIXME: no superblock not supported */
@@ -145,6 +146,18 @@ static int action_dump(void)
return r;
}
static int action_status(void)
{
struct crypt_device *cd = NULL;
int r;
r = crypt_init_by_name_and_header(&cd, dm_device, NULL);
if (!r)
r = crypt_dump(cd);
crypt_free(cd);
return r;
}
static int action_activate(int verify)
{
struct crypt_device *cd = NULL;
@@ -292,6 +305,7 @@ int main(int argc, const char **argv)
{ "verify", 'v', POPT_ARG_VAL, &mode, MODE_VERIFY, "Verify integrity", NULL },
{ "activate", 'a', POPT_ARG_VAL, &mode, MODE_ACTIVATE, "Activate the device", NULL },
{ "dump", 'd', POPT_ARG_VAL, &mode, MODE_DUMP, "Dump the device", NULL },
{ "status", 's', POPT_ARG_VAL, &mode, MODE_STATUS, "Status active device", NULL },
{ "no-superblock", 0, POPT_ARG_VAL, &use_superblock, 0, "Do not create/use superblock" },
{ "format", 0, POPT_ARG_INT, &version, 0, "Format version (1 - normal format, 0 - original Chromium OS format)", "number" },
{ "data-block-size", 0, POPT_ARG_INT, &data_block_size, 0, "Block size on the data device", "bytes" },
@@ -335,7 +349,7 @@ int main(int argc, const char **argv)
usage(popt_context, EXIT_FAILURE, _("Unknown action."),
poptGetInvocationName(popt_context));
if (mode == MODE_ACTIVATE) {
if (mode == MODE_ACTIVATE || mode == MODE_STATUS) {
dm_device = poptGetArg(popt_context);
if (!dm_device || !*dm_device)
usage(popt_context, EXIT_FAILURE,
@@ -343,6 +357,9 @@ int main(int argc, const char **argv)
poptGetInvocationName(popt_context));
}
if (mode == MODE_STATUS)
goto run; //FIXME
data_device = poptGetArg(popt_context);
if (!data_device)
usage(popt_context, EXIT_FAILURE, _("Missing data device name."),
@@ -383,7 +400,7 @@ int main(int argc, const char **argv)
salt_string = "";
salt_size = strlen(salt_string) / 2;
}
run:
if (opt_debug) {
opt_verbose = 1;
crypt_set_debug_level(-1);
@@ -403,6 +420,9 @@ int main(int argc, const char **argv)
case MODE_DUMP:
r = action_dump();
break;
case MODE_STATUS:
r = action_status();
break;
}
poptFreeContext(popt_context);