Add FEC offset parameter for verity.

This commit is contained in:
Milan Broz
2017-04-03 12:34:50 +02:00
parent e8eab081c5
commit fc0bef732b
9 changed files with 44 additions and 4 deletions

View File

@@ -312,6 +312,7 @@ struct crypt_params_verity {
uint32_t hash_block_size; /**< hash block size (in bytes) */
uint64_t data_size; /**< data area size (in data blocks) */
uint64_t hash_area_offset; /**< hash/header offset (in bytes) */
uint64_t fec_area_offset; /**< FEC/header offset (in bytes) */
uint32_t fec_roots; /**< Reed-Solomon FEC roots */
uint32_t flags; /**< CRYPT_VERITY* flags */
};

View File

@@ -390,8 +390,8 @@ static char *get_dm_verity_params(struct crypt_params_verity *vp,
if (dmd->u.verity.fec_device) {
num_options += 8;
snprintf(fec_features, sizeof(fec_features)-1,
" use_fec_from_device %s fec_start 0 fec_blocks %" PRIu64 " fec_roots %" PRIu32,
device_block_path(dmd->u.verity.fec_device),
" use_fec_from_device %s fec_start %" PRIu64 " fec_blocks %" PRIu64 " fec_roots %" PRIu32,
device_block_path(dmd->u.verity.fec_device), dmd->u.verity.fec_offset,
vp->data_size + dmd->u.verity.hash_blocks, vp->fec_roots);
} else
*fec_features = '\0';

View File

@@ -730,6 +730,7 @@ static int _init_by_name_verity(struct crypt_device *cd, const char *name)
cd->u.verity.hdr.data_block_size = params.data_block_size;
cd->u.verity.hdr.hash_block_size = params.hash_block_size;
cd->u.verity.hdr.hash_area_offset = dmd.u.verity.hash_offset;
cd->u.verity.hdr.fec_area_offset = dmd.u.verity.fec_offset;
cd->u.verity.hdr.hash_type = params.hash_type;
cd->u.verity.hdr.flags = params.flags;
cd->u.verity.hdr.salt_size = params.salt_size;
@@ -1023,6 +1024,11 @@ static int _crypt_format_verity(struct crypt_device *cd,
return -EINVAL;
}
if (params->fec_area_offset % 512) {
log_err(cd, _("Unsupported VERITY FEC offset.\n"));
return -EINVAL;
}
if (!(cd->type = strdup(CRYPT_VERITY)))
return -ENOMEM;
@@ -1069,6 +1075,7 @@ static int _crypt_format_verity(struct crypt_device *cd,
cd->u.verity.hdr.data_block_size = params->data_block_size;
cd->u.verity.hdr.hash_block_size = params->hash_block_size;
cd->u.verity.hdr.hash_area_offset = params->hash_area_offset;
cd->u.verity.hdr.fec_area_offset = params->fec_area_offset;
cd->u.verity.hdr.hash_type = params->hash_type;
cd->u.verity.hdr.flags = params->flags;
cd->u.verity.hdr.salt_size = params->salt_size;

View File

@@ -83,6 +83,7 @@ struct crypt_dm_active_device {
uint64_t hash_offset; /* hash offset in blocks (not header) */
uint64_t hash_blocks; /* size of hash device (in hash blocks) */
uint64_t fec_offset; /* FEC offset in blocks (not header) */
struct crypt_params_verity *vp;
} verity;
} u;

View File

@@ -67,6 +67,21 @@ struct fec_context {
size_t ninputs;
};
/* Calculate FEC offset in hash blocks */
uint64_t VERITY_FEC_offset_block(struct crypt_params_verity *params)
{
uint64_t fec_offset = params->fec_area_offset;
if (params->flags & CRYPT_VERITY_NO_HEADER)
return fec_offset / params->hash_block_size;
fec_offset += sizeof(struct fec_sb);
//hash_offset += params->hash_block_size - 1;
return fec_offset / params->hash_block_size;
}
/* computes ceil(x / y) */
static inline uint64_t FEC_div_round_up(uint64_t x, uint64_t y)
{
@@ -302,6 +317,12 @@ int VERITY_FEC_create(struct crypt_device *cd,
return -errno;
}
if (lseek(fd, params->fec_area_offset, SEEK_SET) != params->fec_area_offset) {
log_dbg("Cannot seek to requested position in FEC device.");
TEMP_FAILURE_RETRY(close(fd));
return -EIO;
}
/* input devices */
memset(inputs, 0, sizeof(inputs));

View File

@@ -261,6 +261,7 @@ int VERITY_activate(struct crypt_device *cd,
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.u.verity.fec_offset = VERITY_FEC_offset_block(verity_hdr);
dmd.u.verity.hash_blocks = VERITY_hash_blocks(cd, verity_hdr);
dmd.flags = activation_flags;
dmd.size = verity_hdr->data_size * verity_hdr->data_block_size / 512;

View File

@@ -60,6 +60,7 @@ int VERITY_create(struct crypt_device *cd,
size_t root_hash_size);
uint64_t VERITY_hash_offset_block(struct crypt_params_verity *params);
uint64_t VERITY_FEC_offset_block(struct crypt_params_verity *params);
uint64_t VERITY_hash_blocks(struct crypt_device *cd, struct crypt_params_verity *params);

View File

@@ -444,8 +444,8 @@ int VERITY_create(struct crypt_device *cd,
uint64_t VERITY_hash_blocks(struct crypt_device *cd, struct crypt_params_verity *params)
{
off_t hash_position = (off_t)params->hash_area_offset;
int levels;
off_t hash_position = 0;
int levels = 0;
if (hash_levels(params->hash_block_size, crypt_get_volume_key_size(cd),
params->data_size, &hash_position, &levels, NULL, NULL))

View File

@@ -34,6 +34,7 @@ static int hash_block_size = DEFAULT_VERITY_HASH_BLOCK;
static uint64_t data_blocks = 0;
static const char *salt_string = NULL;
static uint64_t hash_offset = 0;
static uint64_t fec_offset = 0;
static const char *opt_uuid = NULL;
static int opt_restart_on_corruption = 0;
static int opt_ignore_corruption = 0;
@@ -76,6 +77,7 @@ static int _prepare_format(struct crypt_params_verity *params,
params->hash_block_size = hash_block_size;
params->data_size = data_blocks;
params->hash_area_offset = hash_offset;
params->fec_area_offset = fec_offset;
params->hash_type = hash_type;
params->flags = flags;
@@ -155,6 +157,7 @@ static int _activate(const char *dm_device,
if (use_superblock) {
params.flags = flags;
params.hash_area_offset = hash_offset;
params.fec_area_offset = fec_offset;
params.fec_device = fec_device;
params.fec_roots = fec_roots;
r = crypt_load(cd, CRYPT_VERITY, &params);
@@ -326,6 +329,7 @@ static int action_dump(int arg)
return r;
params.hash_area_offset = hash_offset;
params.fec_area_offset = fec_offset;
r = crypt_load(cd, CRYPT_VERITY, &params);
if (!r)
crypt_dump(cd);
@@ -417,6 +421,7 @@ int main(int argc, const char **argv)
{ "data-blocks", 0, POPT_ARG_STRING, &popt_tmp, 1, N_("The number of blocks in the data file"), N_("blocks") },
{ "fec-device", 0, POPT_ARG_STRING, &fec_device, 0, N_("Path to device with error correction data"), N_("path") },
{ "hash-offset", 0, POPT_ARG_STRING, &popt_tmp, 2, N_("Starting offset on the hash device"), N_("bytes") },
{ "fec-offset", 0, POPT_ARG_STRING, &popt_tmp, 3, N_("Starting offset on the FEC device"), N_("bytes") },
{ "hash", 'h', POPT_ARG_STRING, &hash_algorithm, 0, N_("Hash algorithm"), N_("string") },
{ "salt", 's', POPT_ARG_STRING, &salt_string, 0, N_("Salt"), N_("hex string") },
{ "uuid", '\0', POPT_ARG_STRING, &opt_uuid, 0, N_("UUID for device to use."), NULL },
@@ -459,6 +464,9 @@ int main(int argc, const char **argv)
case 2:
hash_offset = ull_value;
break;
case 3:
fec_offset = ull_value;
break;
}
if (r < 0)