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";
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;
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;
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;
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,
int dm_create_device(const char *name,
const char *type,
struct crypt_dm_active_device *dmd,
- void *params,
int reload)
{
char *table_params = NULL;
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);
}
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;
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;
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,
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 */
/* 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)
}
/* 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);
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,
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))
.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),
};
- 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;
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"));
.uuid = NULL,
.size = 0,
.flags = 0,
+ .data_device = device,
.u.crypt = {
- .device = device,
.cipher = cipher,
.vk = vk,
.offset = sector,
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)))
.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),
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 -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;
.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),
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;
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)
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);
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;
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);
}
}
(*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;
}
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;
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;
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;
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 */
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;
};
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,
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;
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;
}
out:
crypt_free(cd);
+ if (r == -ENOTSUP)
+ r = 0;
return r;
}
*/
/* 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>
#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 */
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;
{ "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" },
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,
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."),
salt_string = "";
salt_size = strlen(salt_string) / 2;
}
-
+run:
if (opt_debug) {
opt_verbose = 1;
crypt_set_debug_level(-1);
case MODE_DUMP:
r = action_dump();
break;
+ case MODE_STATUS:
+ r = action_status();
+ break;
}
poptFreeContext(popt_context);