mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
Support init_by_name for verity.
This commit is contained in:
@@ -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, ¶ms);
|
||||
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(¶ms, " ");
|
||||
/* 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(¶ms, " ");
|
||||
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, ¶ms, 10);
|
||||
if (*params != ' ')
|
||||
return -EINVAL;
|
||||
if (vp)
|
||||
vp->version = val32;
|
||||
params++;
|
||||
|
||||
/* data device */
|
||||
str = strsep(¶ms, " ");
|
||||
if (!params)
|
||||
return -EINVAL;
|
||||
if (get_flags & DM_ACTIVE_DEVICE)
|
||||
dmd->data_device = crypt_lookup_dev(str);
|
||||
|
||||
/* hash device */
|
||||
str = strsep(¶ms, " ");
|
||||
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, ¶ms, 10);
|
||||
if (*params != ' ')
|
||||
return -EINVAL;
|
||||
if (vp)
|
||||
vp->data_block_size = val32;
|
||||
params++;
|
||||
|
||||
/* hash block size */
|
||||
val32 = strtoul(params, ¶ms, 10);
|
||||
if (*params != ' ')
|
||||
return -EINVAL;
|
||||
if (vp)
|
||||
vp->hash_block_size = val32;
|
||||
params++;
|
||||
|
||||
/* data blocks */
|
||||
val64 = strtoull(params, ¶ms, 10);
|
||||
if (*params != ' ')
|
||||
return -EINVAL;
|
||||
if (vp)
|
||||
vp->data_size = val64;
|
||||
params++;
|
||||
|
||||
/* hash start */
|
||||
val64 = strtoull(params, ¶ms, 10);
|
||||
if (*params != ' ')
|
||||
return -EINVAL;
|
||||
dmd->u.verity.hash_offset = val64;
|
||||
params++;
|
||||
|
||||
/* hash algorithm */
|
||||
str = strsep(¶ms, " ");
|
||||
if (!params)
|
||||
return -EINVAL;
|
||||
if (vp)
|
||||
vp->hash_name = strdup(str);
|
||||
|
||||
/* root digest */
|
||||
str = strsep(¶ms, " ");
|
||||
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(¶ms, " ");
|
||||
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))
|
||||
|
||||
@@ -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"));
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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;
|
||||
|
||||
221
lib/setup.c
221
lib/setup.c
@@ -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 = ¶ms,
|
||||
};
|
||||
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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -489,6 +489,8 @@ static int action_status(int arg __attribute__((unused)))
|
||||
}
|
||||
out:
|
||||
crypt_free(cd);
|
||||
if (r == -ENOTSUP)
|
||||
r = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user