mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-07 08:50:05 +01:00
Enable userspace FEC decoding in veritysetup.
This commit is contained in:
committed by
Milan Broz
parent
5e0db46f17
commit
dc58985ac6
@@ -1812,7 +1812,7 @@ static int _crypt_format_verity(struct crypt_device *cd,
|
||||
r = VERITY_create(cd, &cd->u.verity.hdr,
|
||||
cd->u.verity.root_hash, cd->u.verity.root_hash_size);
|
||||
if (!r && params->fec_device)
|
||||
r = VERITY_FEC_create(cd, &cd->u.verity.hdr, cd->u.verity.fec_device);
|
||||
r = VERITY_FEC_process(cd, &cd->u.verity.hdr, cd->u.verity.fec_device, 0, NULL);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -242,6 +242,7 @@ int VERITY_activate(struct crypt_device *cd,
|
||||
{
|
||||
struct crypt_dm_active_device dmd;
|
||||
uint32_t dmv_flags;
|
||||
unsigned int fec_errors = 0;
|
||||
int r;
|
||||
|
||||
log_dbg("Trying to activate VERITY device %s using hash %s.",
|
||||
@@ -249,8 +250,18 @@ int VERITY_activate(struct crypt_device *cd,
|
||||
|
||||
if (verity_hdr->flags & CRYPT_VERITY_CHECK_HASH) {
|
||||
log_dbg("Verification of data in userspace required.");
|
||||
r = VERITY_verify(cd, verity_hdr,
|
||||
root_hash, root_hash_size);
|
||||
r = VERITY_verify(cd, verity_hdr, root_hash, root_hash_size);
|
||||
|
||||
if (r == -EPERM && fec_device) {
|
||||
log_dbg("Verification failed, trying to repair with FEC device.");
|
||||
r = VERITY_FEC_process(cd, verity_hdr, fec_device, 1, &fec_errors);
|
||||
if (r < 0)
|
||||
log_err(cd, _("Errors cannot be repaired with FEC device.\n"));
|
||||
else if (fec_errors)
|
||||
log_err(cd, _("Found %u repairable errors with FEC device.\n"),
|
||||
fec_errors);
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -59,9 +59,11 @@ int VERITY_create(struct crypt_device *cd,
|
||||
char *root_hash,
|
||||
size_t root_hash_size);
|
||||
|
||||
int VERITY_FEC_create(struct crypt_device *cd,
|
||||
int VERITY_FEC_process(struct crypt_device *cd,
|
||||
struct crypt_params_verity *params,
|
||||
struct device *fec_device);
|
||||
struct device *fec_device,
|
||||
int check_fec,
|
||||
unsigned int *errors);
|
||||
|
||||
uint64_t VERITY_hash_offset_block(struct crypt_params_verity *params);
|
||||
|
||||
|
||||
@@ -104,18 +104,18 @@ static int FEC_read_interleaved(struct fec_context *ctx, uint64_t i,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* encodes inputs to fd */
|
||||
static int FEC_encode_inputs(struct crypt_device *cd,
|
||||
struct crypt_params_verity *params,
|
||||
struct fec_input_device *inputs,
|
||||
size_t ninputs, int fd)
|
||||
/* encodes/decode inputs to/from fd */
|
||||
static int FEC_process_inputs(struct crypt_device *cd,
|
||||
struct crypt_params_verity *params,
|
||||
struct fec_input_device *inputs,
|
||||
size_t ninputs, int fd,
|
||||
int decode, unsigned int *errors)
|
||||
{
|
||||
int r = 0;
|
||||
unsigned int i;
|
||||
struct fec_context ctx;
|
||||
uint32_t b;
|
||||
uint64_t n;
|
||||
uint8_t parity[params->fec_roots];
|
||||
uint8_t rs_block[FEC_RSM];
|
||||
uint8_t *buf = NULL;
|
||||
void *rs;
|
||||
@@ -149,7 +149,7 @@ static int FEC_encode_inputs(struct crypt_device *cd,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* encode input */
|
||||
/* encode/decode input */
|
||||
for (n = 0; n < ctx.rounds; ++n) {
|
||||
for (i = 0; i < ctx.rsn; ++i) {
|
||||
if (FEC_read_interleaved(&ctx, n * ctx.rsn * ctx.block_size + i,
|
||||
@@ -164,24 +164,44 @@ static int FEC_encode_inputs(struct crypt_device *cd,
|
||||
for (i = 0; i < ctx.rsn; ++i)
|
||||
rs_block[i] = buf[i * ctx.block_size + b];
|
||||
|
||||
encode_rs_char(rs, rs_block, parity);
|
||||
if (write_buffer(fd, parity, sizeof(parity)) != (ssize_t)sizeof(parity)) {
|
||||
log_err(cd, _("Failed to write parity for RS block %" PRIu64 ".\n"), n);
|
||||
r = -EIO;
|
||||
goto out;
|
||||
/* decoding from parity device */
|
||||
if (decode) {
|
||||
if (read_buffer(fd, &rs_block[ctx.rsn], ctx.roots) != ctx.roots) {
|
||||
log_err(cd, _("Failed to read parity for RS block %" PRIu64 ".\n"), n);
|
||||
r = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = decode_rs_char(rs, rs_block);
|
||||
if (r < 0) {
|
||||
log_err(cd, _("Failed to repair parity for block %" PRIu64 ".\n"), n);
|
||||
goto out;
|
||||
}
|
||||
/* return number of detected errors */
|
||||
if (errors)
|
||||
*errors += r;
|
||||
r = 0;
|
||||
} else {
|
||||
/* encoding and writing parity data to fec device */
|
||||
encode_rs_char(rs, rs_block, &rs_block[ctx.rsn]);
|
||||
if (write_buffer(fd, &rs_block[ctx.rsn], ctx.roots) != ctx.roots) {
|
||||
log_err(cd, _("Failed to write parity for RS block %" PRIu64 ".\n"), n);
|
||||
r = -EIO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
free_rs_char(rs);
|
||||
free(buf);
|
||||
return r;
|
||||
}
|
||||
|
||||
int VERITY_FEC_create(struct crypt_device *cd,
|
||||
int VERITY_FEC_process(struct crypt_device *cd,
|
||||
struct crypt_params_verity *params,
|
||||
struct device *fec_device)
|
||||
struct device *fec_device, int check_fec,
|
||||
unsigned int *errors)
|
||||
{
|
||||
int r;
|
||||
int fd = -1;
|
||||
@@ -212,8 +232,11 @@ int VERITY_FEC_create(struct crypt_device *cd,
|
||||
|
||||
r = -EIO;
|
||||
|
||||
/* output device */
|
||||
fd = open(device_path(fec_device), O_RDWR);
|
||||
if (check_fec)
|
||||
fd = open(device_path(fec_device), O_RDONLY);
|
||||
else
|
||||
fd = open(device_path(fec_device), O_RDWR);
|
||||
|
||||
if (fd == -1) {
|
||||
log_err(cd, _("Cannot open device %s.\n"), device_path(fec_device));
|
||||
goto out;
|
||||
@@ -245,7 +268,7 @@ int VERITY_FEC_create(struct crypt_device *cd,
|
||||
}
|
||||
inputs[1].count -= inputs[1].start;
|
||||
|
||||
r = FEC_encode_inputs(cd, params, inputs, FEC_INPUT_DEVICES, fd);
|
||||
r = FEC_process_inputs(cd, params, inputs, FEC_INPUT_DEVICES, fd, check_fec, errors);
|
||||
out:
|
||||
if (inputs[0].fd != -1)
|
||||
close(inputs[0].fd);
|
||||
|
||||
Reference in New Issue
Block a user