Allow offline reencryption on files without root privileges.

If userspace block ciphers are not available try kcapi first.
This commit is contained in:
Ondrej Kozina
2019-06-24 17:02:25 +02:00
committed by Milan Broz
parent c25ce7c585
commit 292a5f50b2
3 changed files with 39 additions and 23 deletions

View File

@@ -617,6 +617,6 @@ void LUKS2_reenc_context_free(struct crypt_device *cd, struct luks2_reenc_contex
int crypt_reencrypt_lock(struct crypt_device *cd, const char *uuid, struct crypt_lock_handle **reencrypt_lock);
void crypt_reencrypt_unlock(struct crypt_device *cd, struct crypt_lock_handle *reencrypt_lock);
int luks2_check_device_size(struct crypt_device *cd, struct luks2_hdr *hdr, uint64_t check_size, uint64_t *device_size, bool activation);
int luks2_check_device_size(struct crypt_device *cd, struct luks2_hdr *hdr, uint64_t check_size, uint64_t *dev_size, bool activation);
#endif

View File

@@ -1144,7 +1144,7 @@ static int _init_storage_wrappers(struct crypt_device *cd,
{
int r;
struct volume_key *vk;
uint32_t wrapper_flags = DISABLE_KCAPI;
uint32_t wrapper_flags = (getuid() || geteuid()) ? 0 : DISABLE_KCAPI;
vk = crypt_volume_key_by_id(vks, rh->digest_old);
r = crypt_storage_wrapper_init(cd, &rh->cw1, crypt_data_device(cd),
@@ -2190,7 +2190,7 @@ static int _create_backup_segments(struct crypt_device *cd,
segment++;
if (digest_new >= 0) {
segment_offset = data_offset * SECTOR_SIZE;
segment_offset = data_offset;
if (strcmp(params->mode, "encrypt") && modify_offset(&segment_offset, data_shift, params->direction)) {
r = -EINVAL;
goto err;
@@ -2199,7 +2199,7 @@ static int _create_backup_segments(struct crypt_device *cd,
crypt_get_iv_offset(cd),
NULL, cipher, sector_size, 0);
} else if (!strcmp(params->mode, "decrypt")) {
segment_offset = data_offset * SECTOR_SIZE;
segment_offset = data_offset;
if (modify_offset(&segment_offset, data_shift, params->direction)) {
r = -EINVAL;
goto err;
@@ -2287,14 +2287,23 @@ static int _reencrypt_init(struct crypt_device *cd,
return -EINVAL;
}
data_offset = LUKS2_get_data_offset(hdr);
data_offset = LUKS2_get_data_offset(hdr) << SECTOR_SHIFT;
r = device_block_adjust(cd, crypt_data_device(cd), DEV_OK,
data_offset, &dev_size, NULL);
r = device_check_access(cd, crypt_data_device(cd), DEV_OK);
if (r)
return r;
if (MISALIGNED(dev_size, sector_size >> SECTOR_SHIFT)) {
r = device_check_size(cd, crypt_data_device(cd), data_offset, 1);
if (r)
return r;
r = device_size(crypt_data_device(cd), &dev_size);
if (r)
return r;
dev_size -= data_offset;
if (MISALIGNED(dev_size, sector_size)) {
log_err(cd, _("Data device is not aligned to requested encryption sector size (%" PRIu32 " bytes)."), sector_size);
return -EINVAL;
}
@@ -2328,7 +2337,7 @@ static int _reencrypt_init(struct crypt_device *cd,
if (!strcmp(params->mode, "encrypt")) {
/* in-memory only */
r = _encrypt_set_segments(cd, hdr, dev_size << SECTOR_SHIFT, params->data_shift << SECTOR_SHIFT, move_first_segment, params->direction);
r = _encrypt_set_segments(cd, hdr, dev_size, params->data_shift << SECTOR_SHIFT, move_first_segment, params->direction);
if (r)
goto err;
}
@@ -2654,7 +2663,8 @@ static int _reencrypt_load(struct crypt_device *cd,
return -EINVAL;
/* some configurations provides fixed device size */
if ((r = luks2_check_device_size(cd, hdr, minimal_size >> SECTOR_SHIFT, &device_size, false))) {
r = luks2_check_device_size(cd, hdr, minimal_size, &device_size, false);
if (r) {
r = -EINVAL;
goto err;
}
@@ -3248,28 +3258,36 @@ err:
}
/* internal only */
int luks2_check_device_size(struct crypt_device *cd, struct luks2_hdr *hdr, uint64_t check_size, uint64_t *device_size, bool activation)
int luks2_check_device_size(struct crypt_device *cd, struct luks2_hdr *hdr, uint64_t check_size, uint64_t *dev_size, bool activation)
{
int r;
crypt_reencrypt_direction_info di;
uint64_t real_size = 0;
uint64_t data_offset, real_size = 0;
if (!LUKS2_reencrypt_direction(hdr, &di) && (di == CRYPT_REENCRYPT_BACKWARD) &&
LUKS2_get_segment_by_flag(hdr, "backup-moved-segment"))
check_size += LUKS2_reencrypt_data_shift(hdr) >> SECTOR_SHIFT;
r = device_block_adjust(cd, crypt_data_device(cd), activation ? DEV_EXCL : DEV_OK,
crypt_get_data_offset(cd), &check_size, NULL);
check_size += LUKS2_reencrypt_data_shift(hdr);
r = device_check_access(cd, crypt_data_device(cd), activation ? DEV_EXCL : DEV_OK);
if (r)
return r;
r = device_block_adjust(cd, crypt_data_device(cd), DEV_OK,
crypt_get_data_offset(cd), &real_size, NULL);
data_offset = crypt_get_data_offset(cd) << SECTOR_SHIFT;
r = device_check_size(cd, crypt_data_device(cd), data_offset, 1);
if (r)
return r;
*device_size = real_size << SECTOR_SHIFT;
r = device_size(crypt_data_device(cd), &real_size);
if (r)
return r;
if (real_size < data_offset || (check_size && (real_size - data_offset) < check_size)) {
log_err(cd, _("Device %s is too small."), device_path(crypt_data_device(cd)));
return -EINVAL;
}
*dev_size = real_size - data_offset;
return 0;
}
@@ -3307,8 +3325,7 @@ int LUKS2_reencrypt_locked_recovery_by_passphrase(struct crypt_device *cd,
vk = vk->next;
}
if (luks2_check_device_size(cd, hdr, minimal_size >> SECTOR_SHIFT,
&device_size, true))
if (luks2_check_device_size(cd, hdr, minimal_size, &device_size, true))
goto err;
r = _reencrypt_recover(cd, hdr, device_size, _vks);

View File

@@ -3862,8 +3862,7 @@ static int _open_and_activate_reencrypt_device(struct crypt_device *cd,
log_dbg(cd, "Entering clean reencryption state mode.");
if (r >= 0)
r = luks2_check_device_size(cd, hdr, minimal_size >> SECTOR_SHIFT,
&device_size, true);
r = luks2_check_device_size(cd, hdr, minimal_size, &device_size, true);
if (r >= 0)
r = LUKS2_activate_multi(cd, name, vks, flags);