"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "lib/luks2/luks2_reencrypt.c" between
cryptsetup-2.4.2.tar.xz and cryptsetup-2.4.3.tar.xz

About: cryptsetup is a utility used to conveniently setup disk encryption based on the dm-crypt kernel module. These include plain dm-crypt volumes, LUKS volumes, loop-AES and TrueCrypt compatible format.

luks2_reencrypt.c  (cryptsetup-2.4.2.tar.xz):luks2_reencrypt.c  (cryptsetup-2.4.3.tar.xz)
skipping to change at line 94 skipping to change at line 94
ssize_t read; ssize_t read;
struct crypt_storage_wrapper *cw1; struct crypt_storage_wrapper *cw1;
struct crypt_storage_wrapper *cw2; struct crypt_storage_wrapper *cw2;
uint32_t wflags1; uint32_t wflags1;
uint32_t wflags2; uint32_t wflags2;
struct crypt_lock_handle *reenc_lock; struct crypt_lock_handle *reenc_lock;
}; };
#if USE_LUKS2_REENCRYPTION
static int reencrypt_keyslot_update(struct crypt_device *cd, static int reencrypt_keyslot_update(struct crypt_device *cd,
const struct luks2_reencrypt *rh) const struct luks2_reencrypt *rh)
{ {
int r;
json_object *jobj_keyslot, *jobj_area, *jobj_area_type; json_object *jobj_keyslot, *jobj_area, *jobj_area_type;
struct luks2_hdr *hdr; struct luks2_hdr *hdr;
if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2))) if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
return -EINVAL; return -EINVAL;
jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, rh->reenc_keyslot); jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, rh->reenc_keyslot);
if (!jobj_keyslot) if (!jobj_keyslot)
return -EINVAL; return -EINVAL;
skipping to change at line 127 skipping to change at line 128
log_dbg(cd, "Updating reencrypt keyslot for none protection."); log_dbg(cd, "Updating reencrypt keyslot for none protection.");
json_object_object_add(jobj_area, "type", json_object_new_string( "none")); json_object_object_add(jobj_area, "type", json_object_new_string( "none"));
json_object_object_del(jobj_area, "hash"); json_object_object_del(jobj_area, "hash");
} else if (rh->rp.type == REENC_PROTECTION_JOURNAL) { } else if (rh->rp.type == REENC_PROTECTION_JOURNAL) {
log_dbg(cd, "Updating reencrypt keyslot for journal protection.") ; log_dbg(cd, "Updating reencrypt keyslot for journal protection.") ;
json_object_object_add(jobj_area, "type", json_object_new_string( "journal")); json_object_object_add(jobj_area, "type", json_object_new_string( "journal"));
json_object_object_del(jobj_area, "hash"); json_object_object_del(jobj_area, "hash");
} else } else
log_dbg(cd, "No update of reencrypt keyslot needed."); log_dbg(cd, "No update of reencrypt keyslot needed.");
return 0; r = LUKS2_keyslot_reencrypt_digest_create(cd, hdr, rh->vks);
if (r < 0)
log_err(cd, "Failed to refresh reencryption verification digest."
);
return r;
} }
static json_object *reencrypt_segment(struct luks2_hdr *hdr, unsigned new) static json_object *reencrypt_segment(struct luks2_hdr *hdr, unsigned new)
{ {
return LUKS2_get_segment_by_flag(hdr, new ? "backup-final" : "backup-prev ious"); return LUKS2_get_segment_by_flag(hdr, new ? "backup-final" : "backup-prev ious");
} }
static json_object *reencrypt_segment_new(struct luks2_hdr *hdr) static json_object *reencrypt_segment_new(struct luks2_hdr *hdr)
{ {
return reencrypt_segment(hdr, 1); return reencrypt_segment(hdr, 1);
skipping to change at line 193 skipping to change at line 198
static uint64_t reencrypt_get_data_offset_new(struct luks2_hdr *hdr) static uint64_t reencrypt_get_data_offset_new(struct luks2_hdr *hdr)
{ {
return reencrypt_data_offset(hdr, 1); return reencrypt_data_offset(hdr, 1);
} }
static uint64_t reencrypt_get_data_offset_old(struct luks2_hdr *hdr) static uint64_t reencrypt_get_data_offset_old(struct luks2_hdr *hdr)
{ {
return reencrypt_data_offset(hdr, 0); return reencrypt_data_offset(hdr, 0);
} }
#endif
static int reencrypt_digest(struct luks2_hdr *hdr, unsigned new) static int reencrypt_digest(struct luks2_hdr *hdr, unsigned new)
{ {
int segment = LUKS2_get_segment_id_by_flag(hdr, new ? "backup-final" : "b ackup-previous"); int segment = LUKS2_get_segment_id_by_flag(hdr, new ? "backup-final" : "b ackup-previous");
if (segment < 0) if (segment < 0)
return segment; return segment;
return LUKS2_digest_by_segment(hdr, segment); return LUKS2_digest_by_segment(hdr, segment);
} }
skipping to change at line 252 skipping to change at line 257
json_object_object_get_ex(jobj_keyslot, "area", &jobj_area); json_object_object_get_ex(jobj_keyslot, "area", &jobj_area);
if (!json_object_object_get_ex(jobj_area, "type", &jobj_type)) if (!json_object_object_get_ex(jobj_area, "type", &jobj_type))
return NULL; return NULL;
if (strcmp(json_object_get_string(jobj_type), "checksum")) if (strcmp(json_object_get_string(jobj_type), "checksum"))
return NULL; return NULL;
if (!json_object_object_get_ex(jobj_area, "hash", &jobj_hash)) if (!json_object_object_get_ex(jobj_area, "hash", &jobj_hash))
return NULL; return NULL;
return json_object_get_string(jobj_hash); return json_object_get_string(jobj_hash);
} }
#if USE_LUKS2_REENCRYPTION
static uint32_t reencrypt_alignment(struct luks2_hdr *hdr) static uint32_t reencrypt_alignment(struct luks2_hdr *hdr)
{ {
json_object *jobj_keyslot, *jobj_area, *jobj_type, *jobj_hash, *jobj_sect or_size; json_object *jobj_keyslot, *jobj_area, *jobj_type, *jobj_hash, *jobj_sect or_size;
int ks = LUKS2_find_keyslot(hdr, "reencrypt"); int ks = LUKS2_find_keyslot(hdr, "reencrypt");
if (ks < 0) if (ks < 0)
return 0; return 0;
jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, ks); jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, ks);
skipping to change at line 664 skipping to change at line 669
} else if (rh->direction == CRYPT_REENCRYPT_FORWARD) { } else if (rh->direction == CRYPT_REENCRYPT_FORWARD) {
log_dbg(cd, "Calculating post segments (forward direction)."); log_dbg(cd, "Calculating post segments (forward direction).");
rh->jobj_segs_post = reencrypt_make_post_segments_forward(cd, hdr , rh, data_offset); rh->jobj_segs_post = reencrypt_make_post_segments_forward(cd, hdr , rh, data_offset);
} else if (rh->direction == CRYPT_REENCRYPT_BACKWARD) { } else if (rh->direction == CRYPT_REENCRYPT_BACKWARD) {
log_dbg(cd, "Calculating segments (backward direction)."); log_dbg(cd, "Calculating segments (backward direction).");
rh->jobj_segs_post = reencrypt_make_post_segments_backward(cd, hd r, rh, data_offset); rh->jobj_segs_post = reencrypt_make_post_segments_backward(cd, hd r, rh, data_offset);
} }
return rh->jobj_segs_post ? 0 : -EINVAL; return rh->jobj_segs_post ? 0 : -EINVAL;
} }
#endif
static uint64_t reencrypt_data_shift(struct luks2_hdr *hdr) static uint64_t reencrypt_data_shift(struct luks2_hdr *hdr)
{ {
json_object *jobj_keyslot, *jobj_area, *jobj_data_shift; json_object *jobj_keyslot, *jobj_area, *jobj_data_shift;
int ks = LUKS2_find_keyslot(hdr, "reencrypt"); int ks = LUKS2_find_keyslot(hdr, "reencrypt");
if (ks < 0) if (ks < 0)
return 0; return 0;
jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, ks); jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, ks);
skipping to change at line 770 skipping to change at line 775
free(rh->device_name); free(rh->device_name);
free(rh->overlay_name); free(rh->overlay_name);
free(rh->hotzone_name); free(rh->hotzone_name);
crypt_drop_keyring_key(cd, rh->vks); crypt_drop_keyring_key(cd, rh->vks);
crypt_free_volume_key(rh->vks); crypt_free_volume_key(rh->vks);
device_release_excl(cd, crypt_data_device(cd)); device_release_excl(cd, crypt_data_device(cd));
crypt_unlock_internal(cd, rh->reenc_lock); crypt_unlock_internal(cd, rh->reenc_lock);
free(rh); free(rh);
} }
#if USE_LUKS2_REENCRYPTION
static size_t reencrypt_get_alignment(struct crypt_device *cd, static size_t reencrypt_get_alignment(struct crypt_device *cd,
struct luks2_hdr *hdr) struct luks2_hdr *hdr)
{ {
int ss; int ss;
size_t alignment = device_block_size(cd, crypt_data_device(cd)); size_t alignment = device_block_size(cd, crypt_data_device(cd));
ss = reencrypt_get_sector_size_old(hdr); ss = reencrypt_get_sector_size_old(hdr);
if (ss > 0 && (size_t)ss > alignment) if (ss > 0 && (size_t)ss > alignment)
alignment = ss; alignment = ss;
ss = reencrypt_get_sector_size_new(hdr); ss = reencrypt_get_sector_size_new(hdr);
skipping to change at line 828 skipping to change at line 833
{ {
uint64_t tmp, linear_length = 0; uint64_t tmp, linear_length = 0;
int sg, segs = json_segments_count(jobj_segments); int sg, segs = json_segments_count(jobj_segments);
/* find reencrypt offset with data shift */ /* find reencrypt offset with data shift */
for (sg = 0; sg < segs; sg++) for (sg = 0; sg < segs; sg++)
if (LUKS2_segment_is_type(hdr, sg, "linear")) if (LUKS2_segment_is_type(hdr, sg, "linear"))
linear_length += LUKS2_segment_size(hdr, sg, 0); linear_length += LUKS2_segment_size(hdr, sg, 0);
/* all active linear segments length */ /* all active linear segments length */
if (linear_length) { if (linear_length && segs > 1) {
if (linear_length < data_shift) if (linear_length < data_shift)
return -EINVAL; return -EINVAL;
tmp = linear_length - data_shift; tmp = linear_length - data_shift;
if (tmp && tmp < data_shift) { if (tmp && tmp < data_shift) {
*offset = data_shift; *offset = data_shift;
*reencrypt_length = tmp; *reencrypt_length = tmp;
} else } else
*offset = tmp; *offset = tmp;
return 0; return 0;
} }
skipping to change at line 1023 skipping to change at line 1028
rh->rp.type = REENC_PROTECTION_CHECKSUM; rh->rp.type = REENC_PROTECTION_CHECKSUM;
r = snprintf(rh->rp.p.csum.hash, r = snprintf(rh->rp.p.csum.hash,
sizeof(rh->rp.p.csum.hash), "%s", params->hash); sizeof(rh->rp.p.csum.hash), "%s", params->hash);
if (r < 0 || (size_t)r >= sizeof(rh->rp.p.csum.hash)) { if (r < 0 || (size_t)r >= sizeof(rh->rp.p.csum.hash)) {
log_dbg(cd, "Invalid hash parameter"); log_dbg(cd, "Invalid hash parameter");
return -EINVAL; return -EINVAL;
} }
if (crypt_hash_init(&rh->rp.p.csum.ch, params->hash)) { if (crypt_hash_init(&rh->rp.p.csum.ch, params->hash)) {
log_dbg(cd, "Failed to initialize checksum resilience has h %s", params->hash); log_err(cd, _("Hash algorithm %s not supported."), params ->hash);
return -EINVAL; return -EINVAL;
} }
r = crypt_hash_size(params->hash); r = crypt_hash_size(params->hash);
if (r < 1) { if (r < 1) {
log_dbg(cd, "Invalid hash size"); log_dbg(cd, "Invalid hash size");
return -EINVAL; return -EINVAL;
} }
rh->rp.p.csum.hash_size = r; rh->rp.p.csum.hash_size = r;
skipping to change at line 1748 skipping to change at line 1753
} }
return commit ? LUKS2_hdr_write(cd, hdr) : 0; return commit ? LUKS2_hdr_write(cd, hdr) : 0;
} }
static int reencrypt_set_encrypt_segments(struct crypt_device *cd, struct luks2_ hdr *hdr, uint64_t dev_size, uint64_t data_shift, bool move_first_segment, crypt _reencrypt_direction_info di) static int reencrypt_set_encrypt_segments(struct crypt_device *cd, struct luks2_ hdr *hdr, uint64_t dev_size, uint64_t data_shift, bool move_first_segment, crypt _reencrypt_direction_info di)
{ {
int r; int r;
uint64_t first_segment_offset, first_segment_length, uint64_t first_segment_offset, first_segment_length,
second_segment_offset, second_segment_length, second_segment_offset, second_segment_length,
data_offset = LUKS2_get_data_offset(hdr) << SECTOR_SHIFT; data_offset = LUKS2_get_data_offset(hdr) << SECTOR_SHIFT,
data_size = dev_size - data_shift;
json_object *jobj_segment_first = NULL, *jobj_segment_second = NULL, *job j_segments; json_object *jobj_segment_first = NULL, *jobj_segment_second = NULL, *job j_segments;
if (dev_size < data_shift) if (dev_size < data_shift)
return -EINVAL; return -EINVAL;
if (data_shift && (di == CRYPT_REENCRYPT_FORWARD)) if (data_shift && (di == CRYPT_REENCRYPT_FORWARD))
return -ENOTSUP; return -ENOTSUP;
if (move_first_segment) { if (move_first_segment) {
/* /*
* future data_device layout: * future data_device layout:
* [future LUKS2 header (data shift size)][second data segment][g ap (data shift size)][first data segment (data shift size)] * [future LUKS2 header (data shift size)][second data segment][g ap (data shift size)][first data segment (data shift size)]
*/ */
first_segment_offset = dev_size; first_segment_offset = dev_size;
first_segment_length = data_shift; if (data_size < data_shift) {
second_segment_offset = data_shift; first_segment_length = data_size;
second_segment_length = dev_size - 2 * data_shift; second_segment_length = second_segment_offset = 0;
} else {
first_segment_length = data_shift;
second_segment_offset = data_shift;
second_segment_length = data_size - data_shift;
}
} else if (data_shift) { } else if (data_shift) {
first_segment_offset = data_offset; first_segment_offset = data_offset;
first_segment_length = dev_size; first_segment_length = dev_size;
} else { } else {
/* future data_device layout with detached header: [first data se gment] */ /* future data_device layout with detached header: [first data se gment] */
first_segment_offset = data_offset; first_segment_offset = data_offset;
first_segment_length = 0; /* dynamic */ first_segment_length = 0; /* dynamic */
} }
jobj_segments = json_object_new_object(); jobj_segments = json_object_new_object();
skipping to change at line 2166 skipping to change at line 2177
static int reencrypt_move_data(struct crypt_device *cd, int devfd, uint64_t data _shift) static int reencrypt_move_data(struct crypt_device *cd, int devfd, uint64_t data _shift)
{ {
void *buffer; void *buffer;
int r; int r;
ssize_t ret; ssize_t ret;
uint64_t buffer_len, offset; uint64_t buffer_len, offset;
struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2); struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
log_dbg(cd, "Going to move data from head of data device."); log_dbg(cd, "Going to move data from head of data device.");
buffer_len = data_shift;
if (!buffer_len)
return -EINVAL;
offset = json_segment_get_offset(LUKS2_get_segment_jobj(hdr, 0), 0); offset = json_segment_get_offset(LUKS2_get_segment_jobj(hdr, 0), 0);
buffer_len = json_segment_get_size(LUKS2_get_segment_jobj(hdr, 0), 0);
/* this is nonsense anyway */ if (!buffer_len || buffer_len > data_shift)
if (buffer_len != json_segment_get_size(LUKS2_get_segment_jobj(hdr, 0), 0
)) {
log_dbg(cd, "buffer_len %" PRIu64", segment size %" PRIu64, buffe
r_len, json_segment_get_size(LUKS2_get_segment_jobj(hdr, 0), 0));
return -EINVAL; return -EINVAL;
}
if (posix_memalign(&buffer, device_alignment(crypt_data_device(cd)), buff er_len)) if (posix_memalign(&buffer, device_alignment(crypt_data_device(cd)), buff er_len))
return -ENOMEM; return -ENOMEM;
ret = read_lseek_blockwise(devfd, ret = read_lseek_blockwise(devfd,
device_block_size(cd, crypt_data_device(cd)), device_block_size(cd, crypt_data_device(cd)),
device_alignment(crypt_data_device(cd)), device_alignment(crypt_data_device(cd)),
buffer, buffer_len, 0); buffer, buffer_len, 0);
if (ret < 0 || (uint64_t)ret != buffer_len) { if (ret < 0 || (uint64_t)ret != buffer_len) {
r = -EIO; r = -EIO;
skipping to change at line 2450 skipping to change at line 2454
log_err(cd, _("All key slots full.")); log_err(cd, _("All key slots full."));
return -EINVAL; return -EINVAL;
} }
/* /*
* We must perform data move with exclusive open data device * We must perform data move with exclusive open data device
* to exclude another cryptsetup process to colide with * to exclude another cryptsetup process to colide with
* encryption initialization (or mount) * encryption initialization (or mount)
*/ */
if (move_first_segment) { if (move_first_segment) {
if (dev_size < 2 * (params->data_shift << SECTOR_SHIFT)) { if (dev_size < (params->data_shift << SECTOR_SHIFT)) {
log_err(cd, _("Device %s is too small."), device_path(cry pt_data_device(cd))); log_err(cd, _("Device %s is too small."), device_path(cry pt_data_device(cd)));
return -EINVAL; return -EINVAL;
} }
if (params->data_shift < LUKS2_get_data_offset(hdr)) { if (params->data_shift < LUKS2_get_data_offset(hdr)) {
log_err(cd, _("Data shift (%" PRIu64 " sectors) is less t han future data offset (%" PRIu64 " sectors)."), params->data_shift, LUKS2_get_d ata_offset(hdr)); log_err(cd, _("Data shift (%" PRIu64 " sectors) is less t han future data offset (%" PRIu64 " sectors)."), params->data_shift, LUKS2_get_d ata_offset(hdr));
return -EINVAL; return -EINVAL;
} }
devfd = device_open_excl(cd, crypt_data_device(cd), O_RDWR); devfd = device_open_excl(cd, crypt_data_device(cd), O_RDWR);
if (devfd < 0) { if (devfd < 0) {
if (devfd == -EBUSY) if (devfd == -EBUSY)
skipping to change at line 2473 skipping to change at line 2477
} }
} }
if (params->mode == CRYPT_REENCRYPT_ENCRYPT) { if (params->mode == CRYPT_REENCRYPT_ENCRYPT) {
/* in-memory only */ /* in-memory only */
r = reencrypt_set_encrypt_segments(cd, hdr, dev_size, params->dat a_shift << SECTOR_SHIFT, move_first_segment, params->direction); r = reencrypt_set_encrypt_segments(cd, hdr, dev_size, params->dat a_shift << SECTOR_SHIFT, move_first_segment, params->direction);
if (r) if (r)
goto out; goto out;
} }
r = LUKS2_keyslot_reencrypt_create(cd, hdr, reencrypt_keyslot, r = LUKS2_keyslot_reencrypt_allocate(cd, hdr, reencrypt_keyslot,
params); params);
if (r < 0) if (r < 0)
goto out; goto out;
r = reencrypt_make_backup_segments(cd, hdr, keyslot_new, _cipher, data_of fset, params); r = reencrypt_make_backup_segments(cd, hdr, keyslot_new, _cipher, data_of fset, params);
if (r) { if (r) {
log_dbg(cd, "Failed to create reencryption backup device segments ."); log_dbg(cd, "Failed to create reencryption backup device segments .");
goto out; goto out;
} }
r = LUKS2_keyslot_open_all_segments(cd, keyslot_old, keyslot_new, passphr ase, passphrase_size, vks); r = LUKS2_keyslot_open_all_segments(cd, keyslot_old, keyslot_new, passphr ase, passphrase_size, vks);
if (r < 0) if (r < 0)
goto out; goto out;
r = LUKS2_keyslot_reencrypt_digest_create(cd, hdr, *vks);
if (r < 0)
goto out;
if (name && params->mode != CRYPT_REENCRYPT_ENCRYPT) { if (name && params->mode != CRYPT_REENCRYPT_ENCRYPT) {
r = reencrypt_verify_and_upload_keys(cd, hdr, LUKS2_reencrypt_dig est_old(hdr), LUKS2_reencrypt_digest_new(hdr), *vks); r = reencrypt_verify_and_upload_keys(cd, hdr, LUKS2_reencrypt_dig est_old(hdr), LUKS2_reencrypt_digest_new(hdr), *vks);
if (r) if (r)
goto out; goto out;
r = dm_query_device(cd, name, DM_ACTIVE_UUID | DM_ACTIVE_DEVICE | r = dm_query_device(cd, name, DM_ACTIVE_UUID | DM_ACTIVE_DEVICE |
DM_ACTIVE_CRYPT_KEYSIZE | DM_ACTIVE_CRYPT_KEY | DM_ACTIVE_CRYPT_KEYSIZE | DM_ACTIVE_CRYPT_KEY |
DM_ACTIVE_CRYPT_CIPHER, &dmd_target); DM_ACTIVE_CRYPT_CIPHER, &dmd_target);
if (r < 0) if (r < 0)
goto out; goto out;
skipping to change at line 2618 skipping to change at line 2626
} }
rh->progress += (uint64_t)rh->read; rh->progress += (uint64_t)rh->read;
return 0; return 0;
} }
static int reencrypt_load(struct crypt_device *cd, struct luks2_hdr *hdr, static int reencrypt_load(struct crypt_device *cd, struct luks2_hdr *hdr,
uint64_t device_size, uint64_t device_size,
const struct crypt_params_reencrypt *params, const struct crypt_params_reencrypt *params,
struct volume_key *vks,
struct luks2_reencrypt **rh) struct luks2_reencrypt **rh)
{ {
int r; int r;
struct luks2_reencrypt *tmp = NULL; struct luks2_reencrypt *tmp = NULL;
crypt_reencrypt_info ri = LUKS2_reencrypt_status(hdr); crypt_reencrypt_info ri = LUKS2_reencrypt_status(hdr);
if (ri == CRYPT_REENCRYPT_NONE) {
log_err(cd, _("Device not marked for LUKS2 reencryption."));
return -EINVAL;
} else if (ri == CRYPT_REENCRYPT_INVALID)
return -EINVAL;
r = LUKS2_reencrypt_digest_verify(cd, hdr, vks);
if (r < 0)
return r;
if (ri == CRYPT_REENCRYPT_CLEAN) if (ri == CRYPT_REENCRYPT_CLEAN)
r = reencrypt_load_clean(cd, hdr, device_size, &tmp, params); r = reencrypt_load_clean(cd, hdr, device_size, &tmp, params);
else if (ri == CRYPT_REENCRYPT_CRASH) else if (ri == CRYPT_REENCRYPT_CRASH)
r = reencrypt_load_crashed(cd, hdr, device_size, &tmp); r = reencrypt_load_crashed(cd, hdr, device_size, &tmp);
else if (ri == CRYPT_REENCRYPT_NONE) { else
log_err(cd, _("Device not marked for LUKS2 reencryption."));
return -EINVAL;
} else
r = -EINVAL; r = -EINVAL;
if (r < 0 || !tmp) { if (r < 0 || !tmp) {
log_err(cd, _("Failed to load LUKS2 reencryption context.")); log_err(cd, _("Failed to load LUKS2 reencryption context."));
return r; return r;
} }
*rh = tmp; *rh = tmp;
return 0; return 0;
} }
#endif
static int reencrypt_lock_internal(struct crypt_device *cd, const char *uuid, st ruct crypt_lock_handle **reencrypt_lock) static int reencrypt_lock_internal(struct crypt_device *cd, const char *uuid, st ruct crypt_lock_handle **reencrypt_lock)
{ {
int r; int r;
char *lock_resource; char *lock_resource;
if (!crypt_metadata_locking_enabled()) { if (!crypt_metadata_locking_enabled()) {
*reencrypt_lock = NULL; *reencrypt_lock = NULL;
return 0; return 0;
} }
skipping to change at line 2705 skipping to change at line 2721
return -EINVAL; return -EINVAL;
return reencrypt_lock_internal(cd, crypt_get_uuid(cd), reencrypt_lock); return reencrypt_lock_internal(cd, crypt_get_uuid(cd), reencrypt_lock);
} }
/* internal only */ /* internal only */
void LUKS2_reencrypt_unlock(struct crypt_device *cd, struct crypt_lock_handle *r eencrypt_lock) void LUKS2_reencrypt_unlock(struct crypt_device *cd, struct crypt_lock_handle *r eencrypt_lock)
{ {
crypt_unlock_internal(cd, reencrypt_lock); crypt_unlock_internal(cd, reencrypt_lock);
} }
#if USE_LUKS2_REENCRYPTION
static int reencrypt_lock_and_verify(struct crypt_device *cd, struct luks2_hdr * hdr, static int reencrypt_lock_and_verify(struct crypt_device *cd, struct luks2_hdr * hdr,
struct crypt_lock_handle **reencrypt_lock) struct crypt_lock_handle **reencrypt_lock)
{ {
int r; int r;
crypt_reencrypt_info ri; crypt_reencrypt_info ri;
struct crypt_lock_handle *h; struct crypt_lock_handle *h;
ri = LUKS2_reencrypt_status(hdr); ri = LUKS2_reencrypt_status(hdr);
if (ri == CRYPT_REENCRYPT_INVALID) { if (ri == CRYPT_REENCRYPT_INVALID) {
log_err(cd, _("Failed to get reencryption state.")); log_err(cd, _("Failed to get reencryption state."));
skipping to change at line 2880 skipping to change at line 2896
(required_size > (device_size >> SECTOR_SHIFT)) || (required_size > (device_size >> SECTOR_SHIFT)) ||
(!dynamic && (required_size != minimal_size)) || (!dynamic && (required_size != minimal_size)) ||
(old_ss > 0 && MISALIGNED(required_size, old_ss >> SECTOR_SHI FT)) || (old_ss > 0 && MISALIGNED(required_size, old_ss >> SECTOR_SHI FT)) ||
(new_ss > 0 && MISALIGNED(required_size, new_ss >> SECTOR_SHI FT))) { (new_ss > 0 && MISALIGNED(required_size, new_ss >> SECTOR_SHI FT))) {
log_err(cd, _("Illegal device size requested in reencrypt ion parameters.")); log_err(cd, _("Illegal device size requested in reencrypt ion parameters."));
goto err; goto err;
} }
rparams.device_size = required_size; rparams.device_size = required_size;
} }
r = reencrypt_load(cd, hdr, device_size, &rparams, &rh); r = reencrypt_load(cd, hdr, device_size, &rparams, *vks, &rh);
if (r < 0 || !rh) if (r < 0 || !rh)
goto err; goto err;
if (name && (r = reencrypt_context_set_names(rh, name))) if (name && (r = reencrypt_context_set_names(rh, name)))
goto err; goto err;
/* Reassure device is not mounted and there's no dm mapping active */ /* Reassure device is not mounted and there's no dm mapping active */
if (!name && (device_open_excl(cd, crypt_data_device(cd), O_RDONLY) < 0)) { if (!name && (device_open_excl(cd, crypt_data_device(cd), O_RDONLY) < 0)) {
log_err(cd,_("Failed to open %s in exclusive mode (already mapped or mounted)."), device_path(crypt_data_device(cd))); log_err(cd,_("Failed to open %s in exclusive mode (already mapped or mounted)."), device_path(crypt_data_device(cd)));
r = -EBUSY; r = -EBUSY;
skipping to change at line 2975 skipping to change at line 2991
log_err(cd, _("LUKS2 reencryption recovery failed.")); log_err(cd, _("LUKS2 reencryption recovery failed."));
} else { } else {
log_dbg(cd, "No LUKS2 reencryption recovery needed."); log_dbg(cd, "No LUKS2 reencryption recovery needed.");
r = 0; r = 0;
} }
LUKS2_reencrypt_unlock(cd, reencrypt_lock); LUKS2_reencrypt_unlock(cd, reencrypt_lock);
return r; return r;
} }
static int reencrypt_repair_by_passphrase(
struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot_old,
int keyslot_new,
const char *passphrase,
size_t passphrase_size)
{
int r;
struct crypt_lock_handle *reencrypt_lock;
struct luks2_reencrypt *rh;
crypt_reencrypt_info ri;
struct volume_key *vks = NULL;
log_dbg(cd, "Loading LUKS2 reencryption context for metadata repair.");
rh = crypt_get_luks2_reencrypt(cd);
if (rh) {
LUKS2_reencrypt_free(cd, rh);
crypt_set_luks2_reencrypt(cd, NULL);
rh = NULL;
}
ri = LUKS2_reencrypt_status(hdr);
if (ri == CRYPT_REENCRYPT_INVALID)
return -EINVAL;
if (ri < CRYPT_REENCRYPT_CLEAN) {
log_err(cd, _("Device is not in reencryption."));
return -EINVAL;
}
r = LUKS2_reencrypt_lock(cd, &reencrypt_lock);
if (r < 0) {
if (r == -EBUSY)
log_err(cd, _("Reencryption process is already running.")
);
else
log_err(cd, _("Failed to acquire reencryption lock."));
return r;
}
/* With reencryption lock held, reload device context and verify metadata
state */
r = crypt_load(cd, CRYPT_LUKS2, NULL);
if (r)
goto out;
ri = LUKS2_reencrypt_status(hdr);
if (ri == CRYPT_REENCRYPT_INVALID) {
r = -EINVAL;
goto out;
}
if (ri == CRYPT_REENCRYPT_NONE) {
r = 0;
goto out;
}
r = LUKS2_keyslot_open_all_segments(cd, keyslot_old, keyslot_new, passphr
ase, passphrase_size, &vks);
if (r < 0)
goto out;
r = LUKS2_keyslot_reencrypt_digest_create(cd, hdr, vks);
crypt_free_volume_key(vks);
vks = NULL;
if (r < 0)
goto out;
/* removes online-reencrypt flag v1 */
if ((r = reencrypt_update_flag(cd, 0, false)))
goto out;
/* adds online-reencrypt flag v2 and commits metadata */
r = reencrypt_update_flag(cd, 1, true);
out:
LUKS2_reencrypt_unlock(cd, reencrypt_lock);
crypt_free_volume_key(vks);
return r;
}
#endif
static int reencrypt_init_by_passphrase(struct crypt_device *cd, static int reencrypt_init_by_passphrase(struct crypt_device *cd,
const char *name, const char *name,
const char *passphrase, const char *passphrase,
size_t passphrase_size, size_t passphrase_size,
int keyslot_old, int keyslot_old,
int keyslot_new, int keyslot_new,
const char *cipher, const char *cipher,
const char *cipher_mode, const char *cipher_mode,
const struct crypt_params_reencrypt *params) const struct crypt_params_reencrypt *params)
{ {
#if USE_LUKS2_REENCRYPTION
int r; int r;
crypt_reencrypt_info ri; crypt_reencrypt_info ri;
struct volume_key *vks = NULL; struct volume_key *vks = NULL;
uint32_t flags = params ? params->flags : 0; uint32_t flags = params ? params->flags : 0;
struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2); struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
/* short-circuit in reencryption metadata update and finish immediately.
*/
if (flags & CRYPT_REENCRYPT_REPAIR_NEEDED)
return reencrypt_repair_by_passphrase(cd, hdr, keyslot_old, keysl
ot_new, passphrase, passphrase_size);
/* short-circuit in recovery and finish immediately. */ /* short-circuit in recovery and finish immediately. */
if (flags & CRYPT_REENCRYPT_RECOVERY) if (flags & CRYPT_REENCRYPT_RECOVERY)
return reencrypt_recovery_by_passphrase(cd, hdr, keyslot_old, key slot_new, passphrase, passphrase_size); return reencrypt_recovery_by_passphrase(cd, hdr, keyslot_old, key slot_new, passphrase, passphrase_size);
if (cipher && !crypt_cipher_wrapped_key(cipher, cipher_mode)) { if (cipher && !crypt_cipher_wrapped_key(cipher, cipher_mode)) {
r = crypt_keyslot_get_key_size(cd, keyslot_new); r = crypt_keyslot_get_key_size(cd, keyslot_new);
if (r < 0) if (r < 0)
return r; return r;
r = LUKS2_check_cipher(cd, r, cipher, cipher_mode); r = LUKS2_check_cipher(cd, r, cipher, cipher_mode);
if (r < 0) if (r < 0)
skipping to change at line 3040 skipping to change at line 3140
if (r < 0 || (flags & CRYPT_REENCRYPT_INITIALIZE_ONLY)) if (r < 0 || (flags & CRYPT_REENCRYPT_INITIALIZE_ONLY))
goto out; goto out;
r = reencrypt_load_by_passphrase(cd, name, passphrase, passphrase_size, k eyslot_old, keyslot_new, &vks, params); r = reencrypt_load_by_passphrase(cd, name, passphrase, passphrase_size, k eyslot_old, keyslot_new, &vks, params);
out: out:
if (r < 0) if (r < 0)
crypt_drop_keyring_key(cd, vks); crypt_drop_keyring_key(cd, vks);
crypt_free_volume_key(vks); crypt_free_volume_key(vks);
return r < 0 ? r : LUKS2_find_keyslot(hdr, "reencrypt"); return r < 0 ? r : LUKS2_find_keyslot(hdr, "reencrypt");
#else
log_err(cd, _("This operation is not supported for this device type."));
return -ENOTSUP;
#endif
} }
int crypt_reencrypt_init_by_keyring(struct crypt_device *cd, int crypt_reencrypt_init_by_keyring(struct crypt_device *cd,
const char *name, const char *name,
const char *passphrase_description, const char *passphrase_description,
int keyslot_old, int keyslot_old,
int keyslot_new, int keyslot_new,
const char *cipher, const char *cipher,
const char *cipher_mode, const char *cipher_mode,
const struct crypt_params_reencrypt *params) const struct crypt_params_reencrypt *params)
skipping to change at line 3092 skipping to change at line 3196
const struct crypt_params_reencrypt *params) const struct crypt_params_reencrypt *params)
{ {
if (onlyLUKS2mask(cd, CRYPT_REQUIREMENT_ONLINE_REENCRYPT) || !passphrase) if (onlyLUKS2mask(cd, CRYPT_REQUIREMENT_ONLINE_REENCRYPT) || !passphrase)
return -EINVAL; return -EINVAL;
if (params && (params->flags & CRYPT_REENCRYPT_INITIALIZE_ONLY) && (param s->flags & CRYPT_REENCRYPT_RESUME_ONLY)) if (params && (params->flags & CRYPT_REENCRYPT_INITIALIZE_ONLY) && (param s->flags & CRYPT_REENCRYPT_RESUME_ONLY))
return -EINVAL; return -EINVAL;
return reencrypt_init_by_passphrase(cd, name, passphrase, passphrase_size , keyslot_old, keyslot_new, cipher, cipher_mode, params); return reencrypt_init_by_passphrase(cd, name, passphrase, passphrase_size , keyslot_old, keyslot_new, cipher, cipher_mode, params);
} }
#if USE_LUKS2_REENCRYPTION
static reenc_status_t reencrypt_step(struct crypt_device *cd, static reenc_status_t reencrypt_step(struct crypt_device *cd,
struct luks2_hdr *hdr, struct luks2_hdr *hdr,
struct luks2_reencrypt *rh, struct luks2_reencrypt *rh,
uint64_t device_size, uint64_t device_size,
bool online) bool online)
{ {
int r; int r;
/* update reencrypt keyslot protection parameters in memory only */
r = reencrypt_keyslot_update(cd, rh);
if (r < 0) {
log_dbg(cd, "Keyslot update failed.");
return REENC_ERR;
}
/* in memory only */ /* in memory only */
r = reencrypt_make_segments(cd, hdr, rh, device_size); r = reencrypt_make_segments(cd, hdr, rh, device_size);
if (r) if (r)
return REENC_ERR; return REENC_ERR;
r = reencrypt_assign_segments(cd, hdr, rh, 1, 0); r = reencrypt_assign_segments(cd, hdr, rh, 1, 0);
if (r) { if (r) {
log_err(cd, _("Failed to set device segments for next reencryptio n hotzone.")); log_err(cd, _("Failed to set device segments for next reencryptio n hotzone."));
return REENC_ERR; return REENC_ERR;
} }
skipping to change at line 3276 skipping to change at line 3374
dm_remove_device(cd, rh->device_name, CRYPT_DEACTIVATE_DEFERR ED); dm_remove_device(cd, rh->device_name, CRYPT_DEACTIVATE_DEFERR ED);
} }
if (finished) { if (finished) {
if (reencrypt_wipe_moved_segment(cd, rh)) if (reencrypt_wipe_moved_segment(cd, rh))
log_err(cd, _("Failed to wipe backup segment data.")); log_err(cd, _("Failed to wipe backup segment data."));
if (reencrypt_get_data_offset_new(hdr) && LUKS2_set_keyslots_size (cd, hdr, reencrypt_get_data_offset_new(hdr))) if (reencrypt_get_data_offset_new(hdr) && LUKS2_set_keyslots_size (cd, hdr, reencrypt_get_data_offset_new(hdr)))
log_dbg(cd, "Failed to set new keyslots area size."); log_dbg(cd, "Failed to set new keyslots area size.");
if (rh->digest_old >= 0 && rh->digest_new != rh->digest_old) if (rh->digest_old >= 0 && rh->digest_new != rh->digest_old)
for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++)
if (LUKS2_digest_by_keyslot(hdr, i) == rh->digest if (LUKS2_digest_by_keyslot(hdr, i) == rh->digest
_old) _old && crypt_keyslot_destroy(cd, i))
crypt_keyslot_destroy(cd, i); log_err(cd, _("Failed to remove unused (u
crypt_keyslot_destroy(cd, rh->reenc_keyslot); nbound) keyslot %d."), i);
if (reencrypt_erase_backup_segments(cd, hdr)) if (reencrypt_erase_backup_segments(cd, hdr))
log_dbg(cd, "Failed to erase backup segments"); log_dbg(cd, "Failed to erase backup segments");
/* do we need atomic erase? */ if (reencrypt_update_flag(cd, 0, false))
if (reencrypt_update_flag(cd, 0, true)) log_dbg(cd, "Failed to disable reencryption requirement f
log_err(cd, _("Failed to disable reencryption requirement lag.");
flag."));
/* metadata commit point also removing reencryption flag on-disk
*/
if (crypt_keyslot_destroy(cd, rh->reenc_keyslot)) {
log_err(cd, _("Failed to remove reencryption keyslot."));
return -EINVAL;
}
} }
return 0; return 0;
} }
static void reencrypt_teardown_fatal(struct crypt_device *cd, struct luks2_reenc rypt *rh) static void reencrypt_teardown_fatal(struct crypt_device *cd, struct luks2_reenc rypt *rh)
{ {
log_err(cd, _("Fatal error while reencrypting chunk starting at %" PRIu64 ", %" PRIu64 " sectors long."), log_err(cd, _("Fatal error while reencrypting chunk starting at %" PRIu64 ", %" PRIu64 " sectors long."),
(rh->offset >> SECTOR_SHIFT) + crypt_get_data_offset(cd), rh->len gth >> SECTOR_SHIFT); (rh->offset >> SECTOR_SHIFT) + crypt_get_data_offset(cd), rh->len gth >> SECTOR_SHIFT);
skipping to change at line 3333 skipping to change at line 3436
default: default:
r = -EIO; r = -EIO;
} }
/* this frees reencryption lock */ /* this frees reencryption lock */
LUKS2_reencrypt_free(cd, rh); LUKS2_reencrypt_free(cd, rh);
crypt_set_luks2_reencrypt(cd, NULL); crypt_set_luks2_reencrypt(cd, NULL);
return r; return r;
} }
#endif
int crypt_reencrypt_run( int crypt_reencrypt_run(
struct crypt_device *cd, struct crypt_device *cd,
int (*progress)(uint64_t size, uint64_t offset, void *usrptr), int (*progress)(uint64_t size, uint64_t offset, void *usrptr),
void *usrptr) void *usrptr)
{ {
#if USE_LUKS2_REENCRYPTION
int r; int r;
crypt_reencrypt_info ri; crypt_reencrypt_info ri;
struct luks2_hdr *hdr; struct luks2_hdr *hdr;
struct luks2_reencrypt *rh; struct luks2_reencrypt *rh;
reenc_status_t rs; reenc_status_t rs;
bool quit = false; bool quit = false;
if (onlyLUKS2mask(cd, CRYPT_REQUIREMENT_ONLINE_REENCRYPT)) if (onlyLUKS2mask(cd, CRYPT_REQUIREMENT_ONLINE_REENCRYPT))
return -EINVAL; return -EINVAL;
skipping to change at line 3374 skipping to change at line 3479
if (rh->online && reencrypt_init_device_stack(cd, rh)) { if (rh->online && reencrypt_init_device_stack(cd, rh)) {
log_err(cd, _("Failed to initialize reencryption device stack.")) ; log_err(cd, _("Failed to initialize reencryption device stack.")) ;
return -EINVAL; return -EINVAL;
} }
log_dbg(cd, "Progress %" PRIu64 ", device_size %" PRIu64, rh->progress, r h->device_size); log_dbg(cd, "Progress %" PRIu64 ", device_size %" PRIu64, rh->progress, r h->device_size);
rs = REENC_OK; rs = REENC_OK;
/* update reencrypt keyslot protection parameters in memory only */
if (!quit && (rh->device_size > rh->progress)) {
r = reencrypt_keyslot_update(cd, rh);
if (r < 0) {
log_dbg(cd, "Keyslot update failed.");
return reencrypt_teardown(cd, hdr, rh, REENC_ERR, quit, p
rogress, usrptr);
}
}
while (!quit && (rh->device_size > rh->progress)) { while (!quit && (rh->device_size > rh->progress)) {
rs = reencrypt_step(cd, hdr, rh, rh->device_size, rh->online); rs = reencrypt_step(cd, hdr, rh, rh->device_size, rh->online);
if (rs != REENC_OK) if (rs != REENC_OK)
break; break;
log_dbg(cd, "Progress %" PRIu64 ", device_size %" PRIu64, rh->pro gress, rh->device_size); log_dbg(cd, "Progress %" PRIu64 ", device_size %" PRIu64, rh->pro gress, rh->device_size);
if (progress && progress(rh->device_size, rh->progress, usrptr)) if (progress && progress(rh->device_size, rh->progress, usrptr))
quit = true; quit = true;
r = reencrypt_context_update(cd, rh); r = reencrypt_context_update(cd, rh);
skipping to change at line 3396 skipping to change at line 3510
rs = REENC_ERR; rs = REENC_ERR;
break; break;
} }
log_dbg(cd, "Next reencryption offset will be %" PRIu64 " sectors .", rh->offset); log_dbg(cd, "Next reencryption offset will be %" PRIu64 " sectors .", rh->offset);
log_dbg(cd, "Next reencryption chunk size will be %" PRIu64 " sec tors).", rh->length); log_dbg(cd, "Next reencryption chunk size will be %" PRIu64 " sec tors).", rh->length);
} }
r = reencrypt_teardown(cd, hdr, rh, rs, quit, progress, usrptr); r = reencrypt_teardown(cd, hdr, rh, rs, quit, progress, usrptr);
return r; return r;
#else
log_err(cd, _("This operation is not supported for this device type."));
return -ENOTSUP;
#endif
} }
int crypt_reencrypt( int crypt_reencrypt(
struct crypt_device *cd, struct crypt_device *cd,
int (*progress)(uint64_t size, uint64_t offset, void *usrptr)) int (*progress)(uint64_t size, uint64_t offset, void *usrptr))
{ {
return crypt_reencrypt_run(cd, progress, NULL); return crypt_reencrypt_run(cd, progress, NULL);
} }
#if USE_LUKS2_REENCRYPTION
static int reencrypt_recovery(struct crypt_device *cd, static int reencrypt_recovery(struct crypt_device *cd,
struct luks2_hdr *hdr, struct luks2_hdr *hdr,
uint64_t device_size, uint64_t device_size,
struct volume_key *vks) struct volume_key *vks)
{ {
int r; int r;
struct luks2_reencrypt *rh = NULL; struct luks2_reencrypt *rh = NULL;
r = reencrypt_load(cd, hdr, device_size, NULL, &rh); r = reencrypt_load(cd, hdr, device_size, NULL, vks, &rh);
if (r < 0) { if (r < 0) {
log_err(cd, _("Failed to load LUKS2 reencryption context.")); log_err(cd, _("Failed to load LUKS2 reencryption context."));
return r; return r;
} }
r = reencrypt_recover_segment(cd, hdr, rh, vks); r = reencrypt_recover_segment(cd, hdr, rh, vks);
if (r < 0) if (r < 0)
goto out; goto out;
if ((r = reencrypt_assign_segments(cd, hdr, rh, 0, 0))) if ((r = reencrypt_assign_segments(cd, hdr, rh, 0, 0)))
skipping to change at line 3440 skipping to change at line 3558
} }
r = reencrypt_teardown_ok(cd, hdr, rh); r = reencrypt_teardown_ok(cd, hdr, rh);
if (!r) if (!r)
r = LUKS2_hdr_write(cd, hdr); r = LUKS2_hdr_write(cd, hdr);
out: out:
LUKS2_reencrypt_free(cd, rh); LUKS2_reencrypt_free(cd, rh);
return r; return r;
} }
#endif
/* /*
* use only for calculation of minimal data device size. * use only for calculation of minimal data device size.
* The real data offset is taken directly from segments! * The real data offset is taken directly from segments!
*/ */
int LUKS2_reencrypt_data_offset(struct luks2_hdr *hdr, bool blockwise) int LUKS2_reencrypt_data_offset(struct luks2_hdr *hdr, bool blockwise)
{ {
crypt_reencrypt_info ri = LUKS2_reencrypt_status(hdr); crypt_reencrypt_info ri = LUKS2_reencrypt_status(hdr);
uint64_t data_offset = LUKS2_get_data_offset(hdr); uint64_t data_offset = LUKS2_get_data_offset(hdr);
if (ri == CRYPT_REENCRYPT_CLEAN && reencrypt_direction(hdr) == CRYPT_REEN CRYPT_FORWARD) if (ri == CRYPT_REENCRYPT_CLEAN && reencrypt_direction(hdr) == CRYPT_REEN CRYPT_FORWARD)
skipping to change at line 3482 skipping to change at line 3600
r = device_check_size(cd, crypt_data_device(cd), data_offset, 1); r = device_check_size(cd, crypt_data_device(cd), data_offset, 1);
if (r) if (r)
return r; return r;
r = device_size(crypt_data_device(cd), &real_size); r = device_size(crypt_data_device(cd), &real_size);
if (r) if (r)
return r; return r;
log_dbg(cd, "Required minimal device size: %" PRIu64 " (%" PRIu64 " secto rs)" log_dbg(cd, "Required minimal device size: %" PRIu64 " (%" PRIu64 " secto rs)"
", real device size: %" PRIu64 " (%" PRIu64 " sectors)\n" ", real device size: %" PRIu64 " (%" PRIu64 " sectors) "
"calculated device size: %" PRIu64 " (%" PRIu64 " sectors)", "calculated device size: %" PRIu64 " (%" PRIu64 " sectors)",
check_size, check_size >> SECTOR_SHIFT, real_size, real_size >> SECTOR_SHIFT, check_size, check_size >> SECTOR_SHIFT, real_size, real_size >> SECTOR_SHIFT,
real_size - data_offset, (real_size - data_offset) >> SECTOR_ SHIFT); real_size - data_offset, (real_size - data_offset) >> SECTOR_ SHIFT);
if (real_size < data_offset || (check_size && (real_size - data_offset) < check_size)) { if (real_size < data_offset || (check_size && real_size < check_size)) {
log_err(cd, _("Device %s is too small."), device_path(crypt_data_ device(cd))); log_err(cd, _("Device %s is too small."), device_path(crypt_data_ device(cd)));
return -EINVAL; return -EINVAL;
} }
*dev_size = real_size - data_offset; *dev_size = real_size - data_offset;
return 0; return 0;
} }
#if USE_LUKS2_REENCRYPTION
/* returns keyslot number on success (>= 0) or negative errnor otherwise */ /* returns keyslot number on success (>= 0) or negative errnor otherwise */
int LUKS2_reencrypt_locked_recovery_by_passphrase(struct crypt_device *cd, int LUKS2_reencrypt_locked_recovery_by_passphrase(struct crypt_device *cd,
int keyslot_old, int keyslot_old,
int keyslot_new, int keyslot_new,
const char *passphrase, const char *passphrase,
size_t passphrase_size, size_t passphrase_size,
uint32_t flags __attribute__((unused)), uint32_t flags __attribute__((unused)),
struct volume_key **vks) struct volume_key **vks)
{ {
uint64_t minimal_size, device_size; uint64_t minimal_size, device_size;
skipping to change at line 3546 skipping to change at line 3664
if (!r && vks) if (!r && vks)
MOVE_REF(*vks, _vks); MOVE_REF(*vks, _vks);
out: out:
if (r < 0) if (r < 0)
crypt_drop_keyring_key(cd, _vks); crypt_drop_keyring_key(cd, _vks);
crypt_free_volume_key(_vks); crypt_free_volume_key(_vks);
return r < 0 ? r : keyslot; return r < 0 ? r : keyslot;
} }
#endif
crypt_reencrypt_info LUKS2_reencrypt_get_params(struct luks2_hdr *hdr, crypt_reencrypt_info LUKS2_reencrypt_get_params(struct luks2_hdr *hdr,
struct crypt_params_reencrypt *params) struct crypt_params_reencrypt *params)
{ {
crypt_reencrypt_info ri; crypt_reencrypt_info ri;
int digest;
uint32_t version;
ri = LUKS2_reencrypt_status(hdr); ri = LUKS2_reencrypt_status(hdr);
if (ri == CRYPT_REENCRYPT_NONE || ri == CRYPT_REENCRYPT_INVALID || !param s) if (ri == CRYPT_REENCRYPT_NONE || ri == CRYPT_REENCRYPT_INVALID || !param s)
return ri; return ri;
digest = LUKS2_digest_by_keyslot(hdr, LUKS2_find_keyslot(hdr, "reencrypt"
));
if (digest < 0 && digest != -ENOENT)
return CRYPT_REENCRYPT_INVALID;
/*
* In case there's an old "online-reencrypt" requirement or reencryption
* keyslot digest is missing inform caller reencryption metadata requires
repair.
*/
if (!LUKS2_config_get_reencrypt_version(hdr, &version) &&
(version < 2 || digest == -ENOENT)) {
params->flags |= CRYPT_REENCRYPT_REPAIR_NEEDED;
return ri;
}
params->mode = reencrypt_mode(hdr); params->mode = reencrypt_mode(hdr);
params->direction = reencrypt_direction(hdr); params->direction = reencrypt_direction(hdr);
params->resilience = reencrypt_resilience_type(hdr); params->resilience = reencrypt_resilience_type(hdr);
params->hash = reencrypt_resilience_hash(hdr); params->hash = reencrypt_resilience_hash(hdr);
params->data_shift = reencrypt_data_shift(hdr) >> SECTOR_SHIFT; params->data_shift = reencrypt_data_shift(hdr) >> SECTOR_SHIFT;
params->max_hotzone_size = 0; params->max_hotzone_size = 0;
if (LUKS2_get_segment_id_by_flag(hdr, "backup-moved-segment") >= 0) if (LUKS2_get_segment_id_by_flag(hdr, "backup-moved-segment") >= 0)
params->flags |= CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT; params->flags |= CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT;
return ri; return ri;
 End of changes. 44 change blocks. 
54 lines changed or deleted 197 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)