From c75d740f9abd8a005975517008f780b16d103b0a Mon Sep 17 00:00:00 2001 From: Ondrej Kozina Date: Thu, 6 Jan 2022 12:24:26 +0100 Subject: [PATCH 20/28] Make reencryption flag and keyslot inseparable. LUKS2 validation code now requires reencrypt keyslot together with online-reencryption flag or none of those. --- lib/luks2/luks2_keyslot.c | 25 +++++++++++++++++++++++++ lib/luks2/luks2_reencrypt.c | 17 +++++++++++------ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/lib/luks2/luks2_keyslot.c b/lib/luks2/luks2_keyslot.c index 2ad5632c..d93f2dda 100644 --- a/lib/luks2/luks2_keyslot.c +++ b/lib/luks2/luks2_keyslot.c @@ -878,10 +878,17 @@ int LUKS2_keyslots_validate(struct crypt_device *cd, json_object *hdr_jobj) const keyslot_handler *h; int keyslot; json_object *jobj_keyslots, *jobj_type; + uint32_t reqs, reencrypt_count = 0; + struct luks2_hdr dummy = { + .jobj = hdr_jobj + }; if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj_keyslots)) return -EINVAL; + if (LUKS2_config_get_requirements(cd, &dummy, &reqs)) + return -EINVAL; + json_object_object_foreach(jobj_keyslots, slot, val) { keyslot = atoi(slot); json_object_object_get_ex(val, "type", &jobj_type); @@ -897,6 +904,24 @@ int LUKS2_keyslots_validate(struct crypt_device *cd, json_object *hdr_jobj) log_dbg(cd, "Keyslot %d is not assigned to exactly 1 digest.", keyslot); return -EINVAL; } + + if (!strcmp(h->name, "reencrypt")) + reencrypt_count++; + } + + if ((reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT) && reencrypt_count == 0) { + log_dbg(cd, "Missing reencryption keyslot."); + return -EINVAL; + } + + if (!(reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT) && reencrypt_count) { + log_dbg(cd, "Missing reencryption requirement flag."); + return -EINVAL; + } + + if (reencrypt_count > 1) { + log_dbg(cd, "Too many reencryption keyslots."); + return -EINVAL; } return 0; diff --git a/lib/luks2/luks2_reencrypt.c b/lib/luks2/luks2_reencrypt.c index f68675de..104871a4 100644 --- a/lib/luks2/luks2_reencrypt.c +++ b/lib/luks2/luks2_reencrypt.c @@ -3301,15 +3301,20 @@ static int reencrypt_teardown_ok(struct crypt_device *cd, struct luks2_hdr *hdr, log_dbg(cd, "Failed to set new keyslots area size."); if (rh->digest_old >= 0 && rh->digest_new != rh->digest_old) for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) - if (LUKS2_digest_by_keyslot(hdr, i) == rh->digest_old) - crypt_keyslot_destroy(cd, i); - crypt_keyslot_destroy(cd, rh->reenc_keyslot); + if (LUKS2_digest_by_keyslot(hdr, i) == rh->digest_old && crypt_keyslot_destroy(cd, i)) + log_err(cd, _("Failed to remove unused (unbound) keyslot %d."), i); + if (reencrypt_erase_backup_segments(cd, hdr)) log_dbg(cd, "Failed to erase backup segments"); - /* do we need atomic erase? */ - if (reencrypt_update_flag(cd, 0, true)) - log_err(cd, _("Failed to disable reencryption requirement flag.")); + if (reencrypt_update_flag(cd, 0, false)) + log_dbg(cd, "Failed to disable reencryption requirement 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; -- 2.27.0