aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilan Broz <gmazyland@gmail.com>2022-01-02 16:57:31 +0100
committerMilan Broz <gmazyland@gmail.com>2022-01-13 07:07:37 +0100
commitd45e6788e8f55f1b3cf92893ecc66435edd43426 (patch)
tree325633688d1667240b76495b105f0dd0b33b0f4e
parent18cb1eeeb9d320d9fb4f9bc3289a23f6694f9d60 (diff)
downloadcryptsetup-d45e6788e8f55f1b3cf92893ecc66435edd43426.tar.gz
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.
-rw-r--r--configure.ac8
-rw-r--r--lib/luks2/luks2_keyslot.c2
-rw-r--r--lib/luks2/luks2_reencrypt.c36
-rw-r--r--lib/setup.c53
-rw-r--r--tests/api-test-2.c6
-rwxr-xr-xtests/luks2-reencryption-test2
6 files changed, 78 insertions, 29 deletions
diff --git a/configure.ac b/configure.ac
index 142c4da0..f5d95e2f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -145,6 +145,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],
diff --git a/lib/luks2/luks2_keyslot.c b/lib/luks2/luks2_keyslot.c
index 99db9385..8409d531 100644
--- a/lib/luks2/luks2_keyslot.c
+++ b/lib/luks2/luks2_keyslot.c
@@ -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
};
diff --git a/lib/luks2/luks2_reencrypt.c b/lib/luks2/luks2_reencrypt.c
index 985d6d34..54ace512 100644
--- a/lib/luks2/luks2_reencrypt.c
+++ b/lib/luks2/luks2_reencrypt.c
@@ -91,7 +91,7 @@ struct luks2_reencrypt {
struct crypt_lock_handle *reenc_lock;
};
-
+#if USE_LUKS2_REENCRYPTION
static int reencrypt_keyslot_update(struct crypt_device *cd,
const struct luks2_reencrypt *rh)
{
@@ -195,7 +195,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");
@@ -254,7 +254,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;
@@ -670,7 +670,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;
@@ -776,7 +776,7 @@ void LUKS2_reencrypt_free(struct crypt_device *cd, struct luks2_reencrypt *rh)
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)
{
@@ -2669,7 +2669,7 @@ static int reencrypt_load(struct crypt_device *cd, struct luks2_hdr *hdr,
return 0;
}
-
+#endif
static int reencrypt_lock_internal(struct crypt_device *cd, const char *uuid, struct crypt_lock_handle **reencrypt_lock)
{
int r;
@@ -2731,7 +2731,7 @@ void LUKS2_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)
{
@@ -3000,7 +3000,7 @@ static int reencrypt_recovery_by_passphrase(struct crypt_device *cd,
LUKS2_reencrypt_unlock(cd, reencrypt_lock);
return r;
}
-
+#endif
static int reencrypt_init_by_passphrase(struct crypt_device *cd,
const char *name,
const char *passphrase,
@@ -3011,6 +3011,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;
@@ -3066,6 +3067,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,
@@ -3118,6 +3123,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_reencrypt *rh,
@@ -3351,10 +3357,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;
@@ -3421,8 +3428,13 @@ 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,
@@ -3458,7 +3470,7 @@ err:
return r;
}
-
+#endif
/*
* use only for calculation of minimal data device size.
* The real data offset is taken directly from segments!
@@ -3514,7 +3526,7 @@ int LUKS2_reencrypt_check_device_size(struct crypt_device *cd, struct luks2_hdr
return 0;
}
-
+#if USE_LUKS2_REENCRYPTION
/* returns keyslot number on success (>= 0) or negative errnor otherwise */
int LUKS2_reencrypt_locked_recovery_by_passphrase(struct crypt_device *cd,
int keyslot_old,
@@ -3564,7 +3576,7 @@ err:
return r < 0 ? r : keyslot;
}
-
+#endif
crypt_reencrypt_info LUKS2_reencrypt_get_params(struct luks2_hdr *hdr,
struct crypt_params_reencrypt *params)
{
diff --git a/lib/setup.c b/lib/setup.c
index c8936bc2..376b9202 100644
--- a/lib/setup.c
+++ b/lib/setup.c
@@ -3857,21 +3857,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 = crypt_volume_key_next(vk);
- }
-
- return 0;
-}
-
/* See fixmes in _open_and_activate_luks2 */
int update_reencryption_flag(struct crypt_device *cd, int enable, bool commit);
@@ -3919,6 +3904,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 = crypt_volume_key_next(vk);
+ }
+
+ return 0;
+}
+
static int _open_all_keys(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
@@ -4095,6 +4096,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_reencrypt_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,
diff --git a/tests/api-test-2.c b/tests/api-test-2.c
index a57a4dd8..c0bfc9ad 100644
--- a/tests/api-test-2.c
+++ b/tests/api-test-2.c
@@ -3692,6 +3692,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)
@@ -3702,7 +3703,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?
*/
@@ -4404,8 +4404,8 @@ static void Luks2Reencryption(void)
crypt_free(cd);
_cleanup_dmdevices();
-#endif
}
+#endif
static void Luks2Repair(void)
{
@@ -4521,7 +4521,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();
diff --git a/tests/luks2-reencryption-test b/tests/luks2-reencryption-test
index 7cf246cd..92f223d2 100755
--- a/tests/luks2-reencryption-test
+++ b/tests/luks2-reencryption-test
@@ -115,6 +115,7 @@ function fail()
function skip()
{
[ -n "$1" ] && echo "$1"
+ remove_mapping
exit 77
}
@@ -726,6 +727,7 @@ echo -n "[512 sector]"
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