mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
Add disable-luks2 reencryption configure option.
The option --disable-luks2-reencryption completely disable LUKS2 reencryption code. When used, the libcryptsetup library can read metadata with reencryption code, but all reencryption API calls and cryptsetup reencrypt commands are disabled. Devices with online reencryption in progress cannot be activated. This option can cause some incompatibilities. Please use with care.
This commit is contained in:
@@ -138,6 +138,14 @@ AC_DEFUN([NO_FIPS], [
|
||||
fi
|
||||
])
|
||||
|
||||
dnl LUKS2 online reencryption
|
||||
AC_ARG_ENABLE([luks2-reencryption],
|
||||
AS_HELP_STRING([--disable-luks2-reencryption], [disable LUKS2 online reencryption extension]),
|
||||
[], [enable_luks2_reencryption=yes])
|
||||
if test "x$enable_luks2_reencryption" = "xyes"; then
|
||||
AC_DEFINE(USE_LUKS2_REENCRYPTION, 1, [Use LUKS2 online reencryption extension])
|
||||
fi
|
||||
|
||||
dnl ==========================================================================
|
||||
dnl pwquality library (cryptsetup CLI only)
|
||||
AC_ARG_ENABLE([pwquality],
|
||||
|
||||
@@ -27,7 +27,9 @@ extern const keyslot_handler reenc_keyslot;
|
||||
|
||||
static const keyslot_handler *keyslot_handlers[LUKS2_KEYSLOTS_MAX] = {
|
||||
&luks2_keyslot,
|
||||
#if USE_LUKS2_REENCRYPTION
|
||||
&reenc_keyslot,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "luks2_internal.h"
|
||||
#include "utils_device_locking.h"
|
||||
|
||||
#if USE_LUKS2_REENCRYPTION
|
||||
static json_object *reencrypt_segment(struct luks2_hdr *hdr, unsigned new)
|
||||
{
|
||||
return LUKS2_get_segment_by_flag(hdr, new ? "backup-final" : "backup-previous");
|
||||
@@ -85,7 +86,7 @@ static uint64_t reencrypt_get_data_offset_old(struct luks2_hdr *hdr)
|
||||
{
|
||||
return reencrypt_data_offset(hdr, 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
static int reencrypt_digest(struct luks2_hdr *hdr, unsigned new)
|
||||
{
|
||||
int segment = LUKS2_get_segment_id_by_flag(hdr, new ? "backup-final" : "backup-previous");
|
||||
@@ -144,7 +145,7 @@ static const char *reencrypt_resilience_hash(struct luks2_hdr *hdr)
|
||||
|
||||
return json_object_get_string(jobj_hash);
|
||||
}
|
||||
|
||||
#if USE_LUKS2_REENCRYPTION
|
||||
static uint32_t reencrypt_alignment(struct luks2_hdr *hdr)
|
||||
{
|
||||
json_object *jobj_keyslot, *jobj_area, *jobj_type, *jobj_hash, *jobj_sector_size;
|
||||
@@ -560,7 +561,7 @@ static int reencrypt_make_post_segments(struct crypt_device *cd,
|
||||
|
||||
return rh->jobj_segs_post ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
#endif
|
||||
static uint64_t reencrypt_data_shift(struct luks2_hdr *hdr)
|
||||
{
|
||||
json_object *jobj_keyslot, *jobj_area, *jobj_data_shift;
|
||||
@@ -666,7 +667,7 @@ void LUKS2_reenc_context_free(struct crypt_device *cd, struct luks2_reenc_contex
|
||||
crypt_unlock_internal(cd, rh->reenc_lock);
|
||||
free(rh);
|
||||
}
|
||||
|
||||
#if USE_LUKS2_REENCRYPTION
|
||||
static size_t reencrypt_get_alignment(struct crypt_device *cd,
|
||||
struct luks2_hdr *hdr)
|
||||
{
|
||||
@@ -2545,7 +2546,7 @@ static int reencrypt_load(struct crypt_device *cd, struct luks2_hdr *hdr,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
/* internal only */
|
||||
int crypt_reencrypt_lock(struct crypt_device *cd, const char *uuid, struct crypt_lock_handle **reencrypt_lock)
|
||||
{
|
||||
@@ -2587,7 +2588,7 @@ void crypt_reencrypt_unlock(struct crypt_device *cd, struct crypt_lock_handle *r
|
||||
{
|
||||
crypt_unlock_internal(cd, reencrypt_lock);
|
||||
}
|
||||
|
||||
#if USE_LUKS2_REENCRYPTION
|
||||
static int reencrypt_lock_and_verify(struct crypt_device *cd, struct luks2_hdr *hdr,
|
||||
struct crypt_lock_handle **reencrypt_lock)
|
||||
{
|
||||
@@ -2842,7 +2843,7 @@ static int reencrypt_recovery_by_passphrase(struct crypt_device *cd,
|
||||
crypt_reencrypt_unlock(cd, reencrypt_lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif
|
||||
static int reencrypt_init_by_passphrase(struct crypt_device *cd,
|
||||
const char *name,
|
||||
const char *passphrase,
|
||||
@@ -2853,6 +2854,7 @@ static int reencrypt_init_by_passphrase(struct crypt_device *cd,
|
||||
const char *cipher_mode,
|
||||
const struct crypt_params_reencrypt *params)
|
||||
{
|
||||
#if USE_LUKS2_REENCRYPTION
|
||||
int r;
|
||||
crypt_reencrypt_info ri;
|
||||
struct volume_key *vks = NULL;
|
||||
@@ -2908,6 +2910,10 @@ out:
|
||||
crypt_drop_keyring_key(cd, vks);
|
||||
crypt_free_volume_key(vks);
|
||||
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,
|
||||
@@ -2960,6 +2966,7 @@ int crypt_reencrypt_init_by_passphrase(struct crypt_device *cd,
|
||||
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,
|
||||
struct luks2_hdr *hdr,
|
||||
struct luks2_reenc_context *rh,
|
||||
@@ -3200,10 +3207,11 @@ static int reencrypt_teardown(struct crypt_device *cd, struct luks2_hdr *hdr,
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif
|
||||
int crypt_reencrypt(struct crypt_device *cd,
|
||||
int (*progress)(uint64_t size, uint64_t offset, void *usrptr))
|
||||
{
|
||||
#if USE_LUKS2_REENCRYPTION
|
||||
int r;
|
||||
crypt_reencrypt_info ri;
|
||||
struct luks2_hdr *hdr;
|
||||
@@ -3261,8 +3269,12 @@ int crypt_reencrypt(struct crypt_device *cd,
|
||||
|
||||
r = reencrypt_teardown(cd, hdr, rh, rs, quit, progress);
|
||||
return r;
|
||||
#else
|
||||
log_err(cd, _("This operation is not supported for this device type."));
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if USE_LUKS2_REENCRYPTION
|
||||
static int reencrypt_recovery(struct crypt_device *cd,
|
||||
struct luks2_hdr *hdr,
|
||||
uint64_t device_size,
|
||||
@@ -3298,7 +3310,7 @@ err:
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
* use only for calculation of minimal data device size.
|
||||
* The real data offset is taken directly from segments!
|
||||
@@ -3313,7 +3325,7 @@ int LUKS2_reencrypt_data_offset(struct luks2_hdr *hdr, bool blockwise)
|
||||
|
||||
return blockwise ? data_offset : data_offset << SECTOR_SHIFT;
|
||||
}
|
||||
|
||||
#if USE_LUKS2_REENCRYPTION
|
||||
/* internal only */
|
||||
int luks2_check_device_size(struct crypt_device *cd, struct luks2_hdr *hdr, uint64_t check_size, uint64_t *dev_size, bool activation, bool dynamic)
|
||||
{
|
||||
@@ -3403,7 +3415,7 @@ err:
|
||||
|
||||
return r < 0 ? r : keyslot;
|
||||
}
|
||||
|
||||
#endif
|
||||
crypt_reencrypt_info LUKS2_reencrypt_status(struct crypt_device *cd, struct crypt_params_reencrypt *params)
|
||||
{
|
||||
crypt_reencrypt_info ri;
|
||||
|
||||
53
lib/setup.c
53
lib/setup.c
@@ -3708,21 +3708,6 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int load_all_keys(struct crypt_device *cd, struct luks2_hdr *hdr, struct volume_key *vks)
|
||||
{
|
||||
int r;
|
||||
struct volume_key *vk = vks;
|
||||
|
||||
while (vk) {
|
||||
r = LUKS2_volume_key_load_in_keyring_by_digest(cd, hdr, vk, crypt_volume_key_get_id(vk));
|
||||
if (r < 0)
|
||||
return r;
|
||||
vk = vk->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See fixmes in _open_and_activate_luks2 */
|
||||
int update_reencryption_flag(struct crypt_device *cd, int enable, bool commit);
|
||||
|
||||
@@ -3764,6 +3749,22 @@ out:
|
||||
return r < 0 ? r : keyslot;
|
||||
}
|
||||
|
||||
#if USE_LUKS2_REENCRYPTION
|
||||
static int load_all_keys(struct crypt_device *cd, struct luks2_hdr *hdr, struct volume_key *vks)
|
||||
{
|
||||
int r;
|
||||
struct volume_key *vk = vks;
|
||||
|
||||
while (vk) {
|
||||
r = LUKS2_volume_key_load_in_keyring_by_digest(cd, hdr, vk, crypt_volume_key_get_id(vk));
|
||||
if (r < 0)
|
||||
return r;
|
||||
vk = vk->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _open_all_keys(struct crypt_device *cd,
|
||||
struct luks2_hdr *hdr,
|
||||
int keyslot,
|
||||
@@ -3925,6 +3926,28 @@ static int _open_and_activate_luks2(struct crypt_device *cd,
|
||||
|
||||
return r;
|
||||
}
|
||||
#else
|
||||
static int _open_and_activate_luks2(struct crypt_device *cd,
|
||||
int keyslot,
|
||||
const char *name,
|
||||
const char *passphrase,
|
||||
size_t passphrase_size,
|
||||
uint32_t flags)
|
||||
{
|
||||
crypt_reencrypt_info ri;
|
||||
|
||||
ri = LUKS2_reenc_status(&cd->u.luks2.hdr);
|
||||
if (ri == CRYPT_REENCRYPT_INVALID)
|
||||
return -EINVAL;
|
||||
|
||||
if (ri > CRYPT_REENCRYPT_NONE) {
|
||||
log_err(cd, _("This operation is not supported for this device type."));
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return _open_and_activate(cd, keyslot, name, passphrase, passphrase_size, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _activate_by_passphrase(struct crypt_device *cd,
|
||||
const char *name,
|
||||
|
||||
@@ -3622,7 +3622,7 @@ static void Luks2Flags(void)
|
||||
|
||||
CRYPT_FREE(cd);
|
||||
}
|
||||
|
||||
#if KERNEL_KEYRING && USE_LUKS2_REENCRYPTION
|
||||
static int test_progress(uint64_t size, uint64_t offset, void *usrptr)
|
||||
{
|
||||
while (--test_progress_steps)
|
||||
@@ -3633,7 +3633,6 @@ static int test_progress(uint64_t size, uint64_t offset, void *usrptr)
|
||||
static void Luks2Reencryption(void)
|
||||
{
|
||||
/* reencryption currently depends on kernel keyring support */
|
||||
#if KERNEL_KEYRING
|
||||
/* NOTES:
|
||||
* - reencryption requires luks2 parameters. can we avoid it?
|
||||
*/
|
||||
@@ -4302,8 +4301,8 @@ static void Luks2Reencryption(void)
|
||||
CRYPT_FREE(cd);
|
||||
|
||||
_cleanup_dmdevices();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void Luks2Repair(void)
|
||||
{
|
||||
@@ -4419,7 +4418,9 @@ int main(int argc, char *argv[])
|
||||
RUN_(Luks2Integrity, "LUKS2 with data integrity");
|
||||
RUN_(Luks2Refresh, "Active device table refresh");
|
||||
RUN_(Luks2Flags, "LUKS2 persistent flags");
|
||||
#if KERNEL_KEYRING && USE_LUKS2_REENCRYPTION
|
||||
RUN_(Luks2Reencryption, "LUKS2 reencryption");
|
||||
#endif
|
||||
RUN_(Luks2Repair, "LUKS2 repair"); // test disables metadata locking. Run always last!
|
||||
|
||||
_cleanup();
|
||||
|
||||
@@ -114,6 +114,7 @@ function fail()
|
||||
function skip()
|
||||
{
|
||||
[ -n "$1" ] && echo "$1"
|
||||
remove_mapping
|
||||
exit 77
|
||||
}
|
||||
|
||||
@@ -745,6 +746,7 @@ prepare sector_size=512 physblk_exp=3 dev_size_mb=32
|
||||
echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 -c aes-cbc-essiv:sha256 --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
|
||||
wipe $PWD1
|
||||
check_hash $PWD1 $HASH1
|
||||
echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON 2>&1 | tail -1 | grep -q "not supported" && skip " No reenryption support, test skipped."
|
||||
echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON || fail
|
||||
check_hash $PWD1 $HASH1
|
||||
echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 256 -c twofish-cbc-essiv:sha256 --resilience journal $FAST_PBKDF_ARGON || fail
|
||||
|
||||
Reference in New Issue
Block a user