import cryptsetup-2.3.3-4.el8_5.1

This commit is contained in:
CentOS Sources 2022-02-01 15:14:28 -05:00 committed by Stepan Oksanichenko
parent 70d758caba
commit e6a2c875ba
16 changed files with 2368 additions and 1 deletions

View File

@ -0,0 +1,206 @@
diff -rupN cryptsetup-2.3.3.old/lib/libcryptsetup.h cryptsetup-2.3.3/lib/libcryptsetup.h
--- cryptsetup-2.3.3.old/lib/libcryptsetup.h 2022-01-18 09:15:34.523672069 +0100
+++ cryptsetup-2.3.3/lib/libcryptsetup.h 2022-01-18 09:16:43.251047191 +0100
@@ -2194,6 +2194,8 @@ int crypt_activate_by_token(struct crypt
#define CRYPT_REENCRYPT_RESUME_ONLY (1 << 2)
/** Run reencryption recovery only. (in) */
#define CRYPT_REENCRYPT_RECOVERY (1 << 3)
+/** Reencryption requires metadata protection. (in/out) */
+#define CRYPT_REENCRYPT_REPAIR_NEEDED (1 << 4)
/**
* Reencryption direction
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2.h cryptsetup-2.3.3/lib/luks2/luks2.h
--- cryptsetup-2.3.3.old/lib/luks2/luks2.h 2022-01-18 09:15:34.520672053 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2.h 2022-01-18 09:16:43.252047196 +0100
@@ -561,6 +561,8 @@ int LUKS2_config_set_flags(struct crypt_
int LUKS2_config_get_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t *reqs);
int LUKS2_config_set_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t reqs, bool commit);
+int LUKS2_config_get_reencrypt_version(struct luks2_hdr *hdr, uint32_t *version);
+
int LUKS2_unmet_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t reqs_mask, int quiet);
int LUKS2_key_description_by_segment(struct crypt_device *cd,
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_json_metadata.c cryptsetup-2.3.3/lib/luks2/luks2_json_metadata.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_json_metadata.c 2022-01-18 09:15:34.521672058 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_json_metadata.c 2022-01-18 09:16:43.253047201 +0100
@@ -1469,6 +1469,49 @@ static const struct requirement_flag *ge
return &unknown_requirement_flag;
}
+int LUKS2_config_get_reencrypt_version(struct luks2_hdr *hdr, uint32_t *version)
+{
+ json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
+ int i, len;
+ const struct requirement_flag *req;
+
+ assert(hdr && version);
+ if (!hdr || !version)
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(jobj_config, "requirements", &jobj_requirements))
+ return -ENOENT;
+
+ if (!json_object_object_get_ex(jobj_requirements, "mandatory", &jobj_mandatory))
+ return -ENOENT;
+
+ len = (int) json_object_array_length(jobj_mandatory);
+ if (len <= 0)
+ return -ENOENT;
+
+ for (i = 0; i < len; i++) {
+ jobj = json_object_array_get_idx(jobj_mandatory, i);
+
+ /* search for requirements prefixed with "online-reencrypt" */
+ if (strncmp(json_object_get_string(jobj), "online-reencrypt", 16))
+ continue;
+
+ /* check current library is aware of the requirement */
+ req = get_requirement_by_name(json_object_get_string(jobj));
+ if (req->flag == (uint32_t)CRYPT_REQUIREMENT_UNKNOWN)
+ continue;
+
+ *version = req->version;
+
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
static const struct requirement_flag *stored_requirement_name_by_id(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t req_id)
{
json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_reencrypt.c cryptsetup-2.3.3/lib/luks2/luks2_reencrypt.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_reencrypt.c 2022-01-18 09:15:34.520672053 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_reencrypt.c 2022-01-18 09:25:26.870913236 +0100
@@ -2888,6 +2888,85 @@ static int reencrypt_recovery_by_passphr
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_reenc_context *rh;
+ crypt_reencrypt_info ri;
+ struct volume_key *vks = NULL;
+
+ log_dbg(cd, "Loading LUKS2 reencryption context for metadata repair.");
+
+ rh = crypt_get_reenc_context(cd);
+ if (rh) {
+ LUKS2_reenc_context_free(cd, rh);
+ crypt_set_reenc_context(cd, NULL);
+ rh = NULL;
+ }
+
+ ri = LUKS2_reenc_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 = crypt_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_reenc_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, passphrase, 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:
+ crypt_reencrypt_unlock(cd, reencrypt_lock);
+ crypt_free_volume_key(vks);
+ return r;
+
+}
+
static int reencrypt_init_by_passphrase(struct crypt_device *cd,
const char *name,
const char *passphrase,
@@ -2904,6 +2983,10 @@ static int reencrypt_init_by_passphrase(
uint32_t flags = params ? params->flags : 0;
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, keyslot_new, passphrase, passphrase_size);
+
/* short-circuit in recovery and finish immediately. */
if (flags & CRYPT_REENCRYPT_RECOVERY)
return reencrypt_recovery_by_passphrase(cd, hdr, keyslot_old, keyslot_new, passphrase, passphrase_size);
@@ -3459,12 +3542,28 @@ err:
crypt_reencrypt_info LUKS2_reencrypt_status(struct crypt_device *cd, struct crypt_params_reencrypt *params)
{
crypt_reencrypt_info ri;
+ int digest;
+ uint32_t version;
struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
ri = LUKS2_reenc_status(hdr);
if (ri == CRYPT_REENCRYPT_NONE || ri == CRYPT_REENCRYPT_INVALID || !params)
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->direction = reencrypt_direction(hdr);
params->resilience = reencrypt_resilience_type(hdr);

View File

@ -0,0 +1,502 @@
diff -rupN cryptsetup-2.3.3.old/tests/luks2-reencryption-mangle-test cryptsetup-2.3.3/tests/luks2-reencryption-mangle-test
--- cryptsetup-2.3.3.old/tests/luks2-reencryption-mangle-test 1970-01-01 01:00:00.000000000 +0100
+++ cryptsetup-2.3.3/tests/luks2-reencryption-mangle-test 2022-01-13 17:01:26.605785131 +0100
@@ -0,0 +1,470 @@
+#!/bin/bash
+
+PS4='$LINENO:'
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+CRYPTSETUP_RAW=$CRYPTSETUP
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+IMG=reenc-mangle-data
+IMG_HDR=$IMG.hdr
+IMG_JSON=$IMG.json
+KEY1=key1
+DEV_NAME=reenc3492834
+
+FAST_PBKDF2="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
+CS_PWPARAMS="--disable-keyring --key-file $KEY1"
+CS_PARAMS="-q --disable-locks $CS_PWPARAMS"
+JSON_MSIZE=16384
+
+function remove_mapping()
+{
+ [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME
+ rm -f $IMG $IMG_HDR $IMG_JSON $KEY1 >/dev/null 2>&1
+}
+
+function fail()
+{
+ local frame=0
+ [ -n "$1" ] && echo "$1"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ remove_mapping
+ exit 2
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ remove_mapping
+ exit 77
+}
+
+function bin_check()
+{
+ which $1 >/dev/null 2>&1 || skip "WARNING: test require $1 binary, test skipped."
+}
+
+function img_json_save()
+{
+ # FIXME: why --json-file cannot be used?
+ #$CRYPTSETUP luksDump --dump-json-metadata $IMG | jq -c -M | tr -d '\n' >$IMG_JSON
+ local LUKS2_JSON_SIZE=$(($JSON_MSIZE - 4096))
+ _dd if=$IMG count=$LUKS2_JSON_SIZE skip=4096 | jq -c -M | tr -d '\n' >$IMG_JSON
+}
+
+function img_json_dump()
+{
+ img_json_save
+ jq . $IMG_JSON
+}
+
+function img_hash_save()
+{
+ IMG_HASH=$(sha256sum $IMG | cut -d' ' -f 1)
+}
+
+function img_hash_unchanged()
+{
+ local IMG_HASH2=$(sha256sum $IMG | cut -d' ' -f 1)
+ [ "$IMG_HASH" != "$IMG_HASH2" ] && fail "Image changed!"
+}
+
+function img_prepare_raw() # $1 options
+{
+ remove_mapping
+
+ if [ ! -e $KEY1 ]; then
+ dd if=/dev/urandom of=$KEY1 count=1 bs=32 >/dev/null 2>&1
+ fi
+
+ truncate -s 32M $IMG || fail
+ $CRYPTSETUP luksFormat $FAST_PBKDF2 $CS_PARAMS --luks2-metadata-size $JSON_MSIZE $IMG $1 || fail
+}
+
+function img_prepare() # $1 options
+{
+ img_prepare_raw
+ # FIXME: resilience is not saved here (always none)?
+ $CRYPTSETUP reencrypt $IMG $CS_PARAMS -q --init-only --resilience none $1 >/dev/null 2>&1
+ [ $? -ne 0 ] && skip "Reencryption unsupported, test skipped."
+ img_json_save
+ img_hash_save
+}
+
+function _dd()
+{
+ dd $@ status=none conv=notrunc bs=1
+}
+
+# header mangle functions
+function img_update_json()
+{
+ local LUKS2_BIN1_OFFSET=448
+ local LUKS2_BIN2_OFFSET=$((LUKS2_BIN1_OFFSET + $JSON_MSIZE))
+ local LUKS2_JSON_SIZE=$(($JSON_MSIZE - 4096))
+
+ # if present jq script, mangle JSON
+ if [ -n "$1" ]; then
+ local JSON=$(cat $IMG_JSON)
+ echo $JSON | jq -M -c "$1" >$IMG_JSON || fail
+ local JSON=$(cat $IMG_JSON)
+ echo $JSON | tr -d '\n' >$IMG_JSON || fail
+ fi
+
+ # wipe JSON areas
+ _dd if=/dev/zero of=$IMG count=$LUKS2_JSON_SIZE seek=4096
+ _dd if=/dev/zero of=$IMG count=$LUKS2_JSON_SIZE seek=$(($JSON_MSIZE + 4096))
+
+ # write JSON data
+ _dd if=$IMG_JSON of=$IMG count=$LUKS2_JSON_SIZE seek=4096
+ _dd if=$IMG_JSON of=$IMG count=$LUKS2_JSON_SIZE seek=$(($JSON_MSIZE + 4096))
+
+ # erase sha256 checksums
+ _dd if=/dev/zero of=$IMG count=64 seek=$LUKS2_BIN1_OFFSET
+ _dd if=/dev/zero of=$IMG count=64 seek=$LUKS2_BIN2_OFFSET
+
+ # calculate sha256 and write chexksums
+ local SUM1_HEX=$(_dd if=$IMG count=$JSON_MSIZE | sha256sum | cut -d ' ' -f 1)
+ echo $SUM1_HEX | xxd -r -p | _dd of=$IMG seek=$LUKS2_BIN1_OFFSET count=64 || fail
+
+ local SUM2_HEX=$(_dd if=$IMG skip=$JSON_MSIZE count=$JSON_MSIZE | sha256sum | cut -d ' ' -f 1)
+ echo $SUM2_HEX | xxd -r -p | _dd of=$IMG seek=$LUKS2_BIN2_OFFSET count=64 || fail
+
+ img_hash_save
+}
+
+function img_check_ok()
+{
+ if [ $(id -u) == 0 ]; then
+ $CRYPTSETUP open $CS_PWPARAMS $IMG $DEV_NAME || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ fi
+
+ $CRYPTSETUP repair $IMG $CS_PARAMS || fail
+}
+
+function img_check_fail()
+{
+ if [ $(id -u) == 0 ]; then
+ $CRYPTSETUP open $CS_PWPARAMS $IMG $DEV_NAME 2>/dev/null && fail
+ fi
+
+ $CRYPTSETUP repair $IMG $CS_PARAMS 2>/dev/null && fail
+ img_hash_unchanged
+}
+
+function img_run_reenc_ok()
+{
+local EXPECT_TIMEOUT=5
+[ -n "$VALG" ] && EXPECT_TIMEOUT=60
+# For now, we cannot run reencryption in batch mode for non-block device. Just fake the terminal here.
+expect_run - >/dev/null <<EOF
+proc abort {} { send_error "Timeout. "; exit 2 }
+set timeout $EXPECT_TIMEOUT
+eval spawn $CRYPTSETUP_RAW reencrypt $IMG $CS_PWPARAMS --disable-locks --resilience none
+expect timeout abort "Are you sure? (Type 'yes' in capital letters):"
+send "YES\n"
+expect timeout abort eof
+exit
+EOF
+[ $? -eq 0 ] || fail "Expect script failed."
+}
+
+function valgrind_setup()
+{
+ bin_check valgrind
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+ CRYPTSETUP=valgrind_run
+ CRYPTSETUP_RAW="./valg.sh ${CRYPTSETUP_VALGRIND}"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+function expect_run()
+{
+ export INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}"
+ expect "$@"
+}
+
+bin_check jq
+bin_check sha256sum
+bin_check xxd
+bin_check expect
+
+export LANG=C
+
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+
+#while false; do
+
+echo "[1] Reencryption with old flag is rejected"
+img_prepare
+img_update_json '.config.requirements.mandatory = ["online-reencryptx"]'
+img_check_fail
+img_update_json '.config.requirements.mandatory = ["online-reencrypt-v2"]'
+img_check_ok
+img_run_reenc_ok
+img_check_ok
+
+# Simulate old reencryption with no digest
+img_prepare
+img_update_json 'del(.digests."2") | .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail
+
+# This must fail for new releases
+echo "[2] Old reencryption in-progress (journal)"
+img_prepare
+img_update_json '
+ del(.digests."2") |
+ .keyslots."2".area.type = "journal" |
+ .segments = {
+ "0" : (.segments."0" +
+ {"size" : .keyslots."2".area.size} +
+ {"flags" : ["in-reencryption"]}),
+ "1" : (.segments."0" +
+ {"offset" : ((.segments."0".offset|tonumber) +
+ (.keyslots."2".area.size|tonumber))|tostring}),
+ "2" : .segments."1",
+ "3" : .segments."2"
+ } |
+ .digests."0".segments = ["1","2"] |
+ .digests."1".segments = ["0","3"] |
+ .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail
+
+echo "[3] Old reencryption in-progress (checksum)"
+img_prepare
+img_update_json '
+ del(.digests."2") |
+ .keyslots."2".area.type = "checksum" |
+ .keyslots."2".area.hash = "sha256" |
+ .keyslots."2".area.sector_size = 4096 |
+ .segments = {
+ "0" : (.segments."0" +
+ {"size" : .keyslots."2".area.size} +
+ {"flags" : ["in-reencryption"]}),
+ "1" : (.segments."0" +
+ {"offset": ((.segments."0".offset|tonumber) +
+ (.keyslots."2".area.size|tonumber))|tostring}),
+ "2" : .segments."1",
+ "3" : .segments."2"
+ } |
+ .digests."0".segments = ["1","2"] |
+ .digests."1".segments = ["0","3"] |
+ .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail
+
+# Note: older tools cannot create this from commandline
+echo "[4] Old decryption in-progress (journal)"
+img_prepare
+img_update_json '
+ del(.digests."1") |
+ del(.digests."2") |
+ del(.keyslots."1") |
+ .keyslots."2".mode = "decrypt" |
+ .keyslots."2".area.type = "journal" |
+ .segments = {
+ "0" : {
+ "type" : "linear",
+ "offset" : .segments."0".offset,
+ "size" : .keyslots."2".area.size,
+ "flags" : ["in-reencryption"]
+ },
+ "1" : (.segments."0" +
+ {"offset" : ((.segments."0".offset|tonumber) +
+ (.keyslots."2".area.size|tonumber))|tostring}),
+ "2" : .segments."1",
+ "3" : {
+ "type" : "linear",
+ "offset" : .segments."0".offset,
+ "size" : "dynamic",
+ "flags" : ["backup-final"]
+ }
+ } |
+ .digests."0".segments = ["1","2"] |
+ .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail
+
+echo "[5] Old decryption in-progress (checksum)"
+img_prepare
+img_update_json '
+ del(.digests."1") |
+ del(.digests."2") |
+ del(.keyslots."1") |
+ .keyslots."2".mode = "decrypt" |
+ .keyslots."2".area.type = "checksum" |
+ .keyslots."2".area.hash = "sha256" |
+ .keyslots."2".area.sector_size = 4096 |
+ .segments = {
+ "0" : {
+ "type" : "linear",
+ "offset" : .segments."0".offset,
+ "size" : .keyslots."2".area.size,
+ "flags" : ["in-reencryption"]
+ },
+ "1" : (.segments."0" +
+ {"offset" : ((.segments."0".offset|tonumber) +
+ (.keyslots."2".area.size|tonumber))|tostring}),
+ "2" : .segments."1",
+ "3" : {
+ "type" : "linear",
+ "offset" : .segments."0".offset,
+ "size" : "dynamic",
+ "flags" : ["backup-final"]
+ }
+ } |
+ .digests."0".segments = ["1","2"] |
+ .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail
+
+# Note - offset is set to work with the old version (with a datashift bug)
+echo "[6] Old reencryption in-progress (datashift)"
+img_prepare
+img_update_json '
+ del(.digests."2") |
+ .keyslots."2".direction = "backward" |
+ .keyslots."2".area.type = "datashift" |
+ .keyslots."2".area.size = "4096" |
+ .keyslots."2".area.shift_size = ((1 * 1024 * 1024)|tostring) |
+ .segments = {
+ "0" : (.segments."0" +
+ {"size" : ((13 * 1024 * 1024)|tostring)}),
+ "1" : (.segments."0" +
+ {"offset" : ((30 * 1024 * 1024)|tostring)}),
+ "2" : .segments."1",
+ "3" : (.segments."2" +
+ {"offset" : ((17 * 1024 * 1024)|tostring)}),
+ } |
+ .digests."0".segments = ["0","2"] |
+ .digests."1".segments = ["1","3"] |
+ .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail
+
+#
+# NEW metadata (with reenc digest)
+#
+echo "[7] Reencryption with various mangled metadata"
+
+# Normal situation
+img_prepare
+img_run_reenc_ok
+img_check_ok
+
+# The same in various steps.
+# Repair must validate not only metadata, but also reencryption digest.
+img_prepare
+img_update_json 'del(.digests."2")'
+img_check_fail
+
+img_prepare '--reduce-device-size 2M'
+img_update_json '.keyslots."2".area.shift_size = ((.keyslots."2".area.shift_size|tonumber / 2)|tostring)'
+img_check_fail
+
+#FIXME: cannot check with correct digest for now (--init-only does not store area type)
+img_prepare
+img_update_json '
+ .keyslots."2".area.type = "checksum" |
+ .keyslots."2".area.hash = "sha256" |
+ .keyslots."2".area.sector_size = 4096'
+img_check_fail
+
+img_prepare
+img_update_json '.keyslots."2".area.type = "journal"'
+img_check_fail
+
+img_prepare
+img_update_json '.keyslots."2".mode = "decrypt"'
+img_check_fail
+
+img_prepare
+img_update_json '.keyslots."2".direction = "backward"'
+img_check_fail
+
+# key_size must be 1
+img_prepare
+img_update_json '.keyslots."2".key_size = 16'
+img_check_fail
+
+# Mangling segments
+img_prepare
+img_update_json 'del(.segments."1")'
+img_check_fail
+
+img_prepare
+img_update_json '.segments."0".encryption = "aes-cbc-null"'
+img_check_fail
+
+img_prepare
+img_update_json '.segments."1".encryption = "aes-cbc-null"'
+img_check_fail
+
+img_prepare
+img_update_json '.segments."2".encryption = "aes-cbc-null"'
+img_check_fail
+
+# Mangling digests
+img_prepare
+img_update_json '
+ .digests."2" = .digests."0" |
+ .digests."2".keyslots = ["2"] |
+ .digests."2".segments = []'
+img_check_fail
+
+img_prepare
+img_update_json '.digests."2".iterations = 1111'
+img_check_fail
+
+# Simulate correct progress
+img_prepare
+img_update_json '
+ .segments = {
+ "0" : (.segments."0" +
+ {"size" : ((1 * 1024 * 1024)|tostring)}),
+ "1" : (.segments."0" +
+ {"offset" : ((17 * 1024 * 1024)|tostring)}),
+ "2" : .segments."1",
+ "3" : .segments."2"
+ } |
+ .digests."0".segments = ["1","2"] |
+ .digests."1".segments = ["0","3"]'
+img_check_ok
+
+# Mangling keyslots
+
+# Set reencrypt slot to non-ignore priority
+# This should be benign, just avoid noisy messages
+img_prepare
+img_update_json 'del(.keyslots."2".priority)'
+img_check_ok
+
+# Flags
+
+# Remove mandatory reenc flag, but keep reenc metadata
+img_prepare
+img_update_json '.config.requirements.mandatory = []'
+img_check_fail
+
+# Unknown segment flag, should be ignored
+img_prepare
+img_update_json '.segments."0".flags = ["dead-parrot"]'
+img_check_ok
+
+echo "[8] Reencryption with AEAD is not supported"
+img_prepare_raw
+img_json_save
+img_update_json '
+ .segments."0".integrity = {
+ "type" : "hmac(sha256)",
+ "journal_encryption": "none",
+ "journal_integrity": "none"
+ }'
+$CRYPTSETUP reencrypt $IMG $CS_PARAMS >/dev/null 2>&1 && fail
+
+remove_mapping
+exit 0
diff -rupN cryptsetup-2.3.3.old/tests/Makefile.am cryptsetup-2.3.3/tests/Makefile.am
--- cryptsetup-2.3.3.old/tests/Makefile.am 2022-01-13 17:01:05.450651531 +0100
+++ cryptsetup-2.3.3/tests/Makefile.am 2022-01-13 17:03:47.726676343 +0100
@@ -25,7 +25,7 @@ TESTS += verity-compat-test
endif
if REENCRYPT
-TESTS += reencryption-compat-test reencryption-compat-test2 luks2-reencryption-test
+TESTS += reencryption-compat-test reencryption-compat-test2 luks2-reencryption-test luks2-reencryption-mangle-test
endif
if INTEGRITYSETUP
@@ -57,6 +57,7 @@ EXTRA_DIST = compatimage.img.xz compatv1
reencryption-compat-test \
reencryption-compat-test2 \
luks2-reencryption-test \
+ luks2-reencryption-mangle-test \
tcrypt-compat-test \
luks1-compat-test \
luks2-validation-test generators \
@@ -119,6 +120,7 @@ valgrind-check: api-test api-test-2 diff
@INFOSTRING="api-test-000" ./valg-api.sh ./api-test
@INFOSTRING="api-test-002" ./valg-api.sh ./api-test-2
@VALG=1 ./luks2-reencryption-test
+ @VALG=1 ./luks2-reencryption-mangle-test
@VALG=1 ./compat-test
.PHONY: valgrind-check

View File

@ -0,0 +1,113 @@
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_internal.h cryptsetup-2.3.3/lib/luks2/luks2_internal.h
--- cryptsetup-2.3.3.old/lib/luks2/luks2_internal.h 2022-01-17 16:14:07.530136302 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_internal.h 2022-01-17 16:15:29.134422136 +0100
@@ -207,5 +207,6 @@ static inline const char *crypt_reencryp
}
bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len);
+bool json_segment_cmp(json_object *jobj_segment_1, json_object *jobj_segment_2);
#endif
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_json_metadata.c cryptsetup-2.3.3/lib/luks2/luks2_json_metadata.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_json_metadata.c 2022-01-17 16:14:07.530136302 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_json_metadata.c 2022-01-17 16:16:34.382650680 +0100
@@ -606,6 +606,63 @@ static int reqs_reencrypt_online(uint32_
return reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
}
+/*
+ * Config section requirements object must be valid.
+ * Also general segments section must be validated first.
+ */
+static int validate_reencrypt_segments(struct crypt_device *cd, json_object *hdr_jobj, json_object *jobj_segments, int first_backup, int segments_count)
+{
+ json_object *jobj, *jobj_backup_previous = NULL, *jobj_backup_final = NULL;
+ uint32_t reqs;
+ int i, r;
+ struct luks2_hdr dummy = {
+ .jobj = hdr_jobj
+ };
+
+ r = LUKS2_config_get_requirements(cd, &dummy, &reqs);
+ if (r)
+ return 1;
+
+ if (reqs_reencrypt_online(reqs)) {
+ for (i = first_backup; i < segments_count; i++) {
+ jobj = json_segments_get_segment(jobj_segments, i);
+ if (!jobj)
+ return 1;
+ if (json_segment_contains_flag(jobj, "backup-final", 0))
+ jobj_backup_final = jobj;
+ else if (json_segment_contains_flag(jobj, "backup-previous", 0))
+ jobj_backup_previous = jobj;
+ }
+
+ if (!jobj_backup_final || !jobj_backup_previous) {
+ log_dbg(cd, "Backup segment is missing.");
+ return 1;
+ }
+
+ for (i = 0; i < first_backup; i++) {
+ jobj = json_segments_get_segment(jobj_segments, i);
+ if (!jobj)
+ return 1;
+
+ if (json_segment_contains_flag(jobj, "in-reencryption", 0)) {
+ if (!json_segment_cmp(jobj, jobj_backup_final)) {
+ log_dbg(cd, "Segment in reencryption does not match backup final segment.");
+ return 1;
+ }
+ continue;
+ }
+
+ if (!json_segment_cmp(jobj, jobj_backup_final) &&
+ !json_segment_cmp(jobj, jobj_backup_previous)) {
+ log_dbg(cd, "Segment does not match neither backup final or backup previous segment.");
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
{
json_object *jobj_segments, *jobj_digests, *jobj_offset, *jobj_size, *jobj_type, *jobj_flags, *jobj;
@@ -732,7 +789,7 @@ static int hdr_validate_segments(struct
}
}
- return 0;
+ return validate_reencrypt_segments(cd, hdr_jobj, jobj_segments, first_backup, count);
}
uint64_t LUKS2_metadata_size(json_object *jobj)
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_segment.c cryptsetup-2.3.3/lib/luks2/luks2_segment.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_segment.c 2022-01-17 16:14:07.531136305 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_segment.c 2022-01-17 16:14:43.952263876 +0100
@@ -410,3 +410,23 @@ json_object *LUKS2_get_segment_by_flag(s
return jobj_segment;
}
+
+/* compares key characteristics of both segments */
+bool json_segment_cmp(json_object *jobj_segment_1, json_object *jobj_segment_2)
+{
+ const char *type = json_segment_type(jobj_segment_1);
+ const char *type2 = json_segment_type(jobj_segment_2);
+
+ if (!type || !type2)
+ return false;
+
+ if (strcmp(type, type2))
+ return false;
+
+ if (!strcmp(type, "crypt"))
+ return (json_segment_get_sector_size(jobj_segment_1) == json_segment_get_sector_size(jobj_segment_2) &&
+ !strcmp(json_segment_get_cipher(jobj_segment_1),
+ json_segment_get_cipher(jobj_segment_2)));
+
+ return true;
+}

View File

@ -0,0 +1,219 @@
diff -rupN cryptsetup-2.3.3.old/man/cryptsetup.8 cryptsetup-2.3.3/man/cryptsetup.8
--- cryptsetup-2.3.3.old/man/cryptsetup.8 2022-01-13 17:19:58.082434394 +0100
+++ cryptsetup-2.3.3/man/cryptsetup.8 2022-01-13 17:20:19.860557992 +0100
@@ -803,6 +803,13 @@ are fixable. This command will only chan
any key-slot data. You may enforce LUKS version by adding \-\-type
option.
+It also repairs (upgrades) LUKS2 reencryption metadata by adding
+metadata digest that protects it against malicious changes.
+
+If LUKS2 reencryption was interrupted in the middle of writting
+reencryption segment the repair command can be used to perform
+reencryption recovery so that reencryption can continue later.
+
\fBWARNING:\fR Always create a binary backup of the original
header before calling this command.
.PP
diff -rupN cryptsetup-2.3.3.old/src/cryptsetup.c cryptsetup-2.3.3/src/cryptsetup.c
--- cryptsetup-2.3.3.old/src/cryptsetup.c 2022-01-13 17:19:58.064434292 +0100
+++ cryptsetup-2.3.3/src/cryptsetup.c 2022-01-13 17:21:29.108950976 +0100
@@ -1072,17 +1072,59 @@ static int set_keyslot_params(struct cry
return crypt_set_pbkdf_type(cd, &pbkdf);
}
-static int _do_luks2_reencrypt_recovery(struct crypt_device *cd)
+static int reencrypt_metadata_repair(struct crypt_device *cd)
+{
+ char *password;
+ size_t passwordLen;
+ int r;
+ struct crypt_params_reencrypt params = {
+ .flags = CRYPT_REENCRYPT_REPAIR_NEEDED
+ };
+
+ if (!opt_batch_mode &&
+ !yesDialog(_("Unprotected LUKS2 reencryption metadata detected. "
+ "Please verify the reencryption operation is desirable (see luksDump output)\n"
+ "and continue (upgrade metadata) only if you acknowledge the operation as genuine."),
+ _("Operation aborted.\n")))
+ return -EINVAL;
+
+ r = tools_get_key(_("Enter passphrase to protect and uppgrade reencryption metadata: "),
+ &password, &passwordLen, opt_keyfile_offset,
+ opt_keyfile_size, opt_key_file, opt_timeout,
+ _verify_passphrase(0), 0, cd);
+ if (r < 0)
+ return r;
+
+ r = crypt_reencrypt_init_by_passphrase(cd, NULL, password, passwordLen,
+ opt_key_slot, opt_key_slot, NULL, NULL, &params);
+ tools_passphrase_msg(r);
+ if (r < 0)
+ goto out;
+
+ r = crypt_activate_by_passphrase(cd, NULL, opt_key_slot,
+ password, passwordLen, 0);
+ tools_passphrase_msg(r);
+ if (r >= 0)
+ r = 0;
+
+out:
+ crypt_safe_free(password);
+ return r;
+}
+
+static int luks2_reencrypt_repair(struct crypt_device *cd)
{
int r;
size_t passwordLen;
const char *msg;
char *password = NULL;
- struct crypt_params_reencrypt recovery_params = {
- .flags = CRYPT_REENCRYPT_RECOVERY
- };
+ struct crypt_params_reencrypt params = {};
+
+ crypt_reencrypt_info ri = crypt_reencrypt_status(cd, &params);
+
+ if (params.flags & CRYPT_REENCRYPT_REPAIR_NEEDED)
+ return reencrypt_metadata_repair(cd);
- crypt_reencrypt_info ri = crypt_reencrypt_status(cd, NULL);
switch (ri) {
case CRYPT_REENCRYPT_NONE:
return 0;
@@ -1120,7 +1162,8 @@ static int _do_luks2_reencrypt_recovery(
}
r = crypt_reencrypt_init_by_passphrase(cd, NULL, password, passwordLen,
- opt_key_slot, opt_key_slot, NULL, NULL, &recovery_params);
+ opt_key_slot, opt_key_slot, NULL, NULL,
+ &(struct crypt_params_reencrypt){ .flags = CRYPT_REENCRYPT_RECOVERY });
if (r > 0)
r = 0;
out:
@@ -1155,8 +1198,9 @@ static int action_luksRepair(void)
if (r == 0)
r = crypt_repair(cd, luksType(opt_type), NULL);
skip_repair:
+ /* Header is ok, check if reencryption metadata needs repair/recovery. */
if (!r && crypt_get_type(cd) && !strcmp(crypt_get_type(cd), CRYPT_LUKS2))
- r = _do_luks2_reencrypt_recovery(cd);
+ r = luks2_reencrypt_repair(cd);
out:
crypt_free(cd);
return r;
diff -rupN cryptsetup-2.3.3.old/tests/luks2-reencryption-mangle-test cryptsetup-2.3.3/tests/luks2-reencryption-mangle-test
--- cryptsetup-2.3.3.old/tests/luks2-reencryption-mangle-test 2022-01-13 17:19:58.073434343 +0100
+++ cryptsetup-2.3.3/tests/luks2-reencryption-mangle-test 2022-01-13 17:20:19.861557997 +0100
@@ -172,6 +172,42 @@ EOF
[ $? -eq 0 ] || fail "Expect script failed."
}
+function img_run_reenc_fail()
+{
+local EXPECT_TIMEOUT=5
+[ -n "$VALG" ] && EXPECT_TIMEOUT=60
+# For now, we cannot run reencryption in batch mode for non-block device. Just fake the terminal here.
+expect_run - >/dev/null <<EOF
+proc abort {} { send_error "Timeout. "; exit 42 }
+set timeout $EXPECT_TIMEOUT
+eval spawn $CRYPTSETUP_RAW reencrypt $IMG $CS_PWPARAMS --disable-locks
+expect timeout abort "Are you sure? (Type 'yes' in capital letters):"
+send "YES\n"
+expect timeout abort eof
+catch wait result
+exit [lindex \$result 3]
+EOF
+local ret=$?
+[ $ret -eq 0 ] && fail "Reencryption passed (should have failed)."
+[ $ret -eq 42 ] && fail "Expect script failed."
+img_hash_unchanged
+}
+
+function img_check_fail_repair_ok()
+{
+ if [ $(id -u) == 0 ]; then
+ $CRYPTSETUP open $CS_PWPARAMS $IMG $DEV_NAME 2>/dev/null && fail
+ fi
+
+ img_run_reenc_fail
+
+ # repair metadata
+ $CRYPTSETUP repair $IMG $CS_PARAMS || fail
+
+ img_check_ok
+ img_run_reenc_ok
+}
+
function valgrind_setup()
{
bin_check valgrind
@@ -212,10 +248,10 @@ img_check_ok
img_run_reenc_ok
img_check_ok
-# Simulate old reencryption with no digest
+# Simulate old reencryption with no digest (repairable)
img_prepare
img_update_json 'del(.digests."2") | .config.requirements.mandatory = ["online-reencrypt"]'
-img_check_fail
+img_check_fail_repair_ok
# This must fail for new releases
echo "[2] Old reencryption in-progress (journal)"
@@ -236,7 +272,7 @@ img_update_json '
.digests."0".segments = ["1","2"] |
.digests."1".segments = ["0","3"] |
.config.requirements.mandatory = ["online-reencrypt"]'
-img_check_fail
+img_check_fail_repair_ok
echo "[3] Old reencryption in-progress (checksum)"
img_prepare
@@ -258,7 +294,7 @@ img_update_json '
.digests."0".segments = ["1","2"] |
.digests."1".segments = ["0","3"] |
.config.requirements.mandatory = ["online-reencrypt"]'
-img_check_fail
+img_check_fail_repair_ok
# Note: older tools cannot create this from commandline
echo "[4] Old decryption in-progress (journal)"
@@ -289,7 +325,7 @@ img_update_json '
} |
.digests."0".segments = ["1","2"] |
.config.requirements.mandatory = ["online-reencrypt"]'
-img_check_fail
+img_check_fail_repair_ok
echo "[5] Old decryption in-progress (checksum)"
img_prepare
@@ -321,7 +357,7 @@ img_update_json '
} |
.digests."0".segments = ["1","2"] |
.config.requirements.mandatory = ["online-reencrypt"]'
-img_check_fail
+img_check_fail_repair_ok
# Note - offset is set to work with the old version (with a datashift bug)
echo "[6] Old reencryption in-progress (datashift)"
@@ -344,7 +380,7 @@ img_update_json '
.digests."0".segments = ["0","2"] |
.digests."1".segments = ["1","3"] |
.config.requirements.mandatory = ["online-reencrypt"]'
-img_check_fail
+img_check_fail_repair_ok
#
# NEW metadata (with reenc digest)
@@ -360,7 +396,7 @@ img_check_ok
# Repair must validate not only metadata, but also reencryption digest.
img_prepare
img_update_json 'del(.digests."2")'
-img_check_fail
+img_check_fail_repair_ok
img_prepare '--reduce-device-size 2M'
img_update_json '.keyslots."2".area.shift_size = ((.keyslots."2".area.shift_size|tonumber / 2)|tostring)'

View File

@ -0,0 +1,65 @@
From 18cb1eeeb9d320d9fb4f9bc3289a23f6694f9d60 Mon Sep 17 00:00:00 2001
From: Milan Broz <gmazyland@gmail.com>
Date: Sun, 2 Jan 2022 16:57:31 +0100
Subject: [PATCH 13/28] Do not run reencryption recovery when not needed.
---
src/cryptsetup.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/src/cryptsetup.c b/src/cryptsetup.c
index 5547b3cc..206575c7 100644
--- a/src/cryptsetup.c
+++ b/src/cryptsetup.c
@@ -1125,6 +1125,7 @@ static int _do_luks2_reencrypt_recovery(struct crypt_device *cd)
{
int r;
size_t passwordLen;
+ const char *msg;
char *password = NULL;
struct crypt_params_reencrypt recovery_params = {
.flags = CRYPT_REENCRYPT_RECOVERY
@@ -1133,12 +1134,8 @@ static int _do_luks2_reencrypt_recovery(struct crypt_device *cd)
crypt_reencrypt_info ri = crypt_reencrypt_status(cd, NULL);
switch (ri) {
case CRYPT_REENCRYPT_NONE:
- /* fall through */
+ return 0;
case CRYPT_REENCRYPT_CLEAN:
- r = noDialog(_("Seems device does not require reencryption recovery.\n"
- "Do you want to proceed anyway?"), NULL);
- if (!r)
- return 0;
break;
case CRYPT_REENCRYPT_CRASH:
r = yesDialog(_("Really proceed with LUKS2 reencryption recovery?"),
@@ -1150,8 +1147,12 @@ static int _do_luks2_reencrypt_recovery(struct crypt_device *cd)
return -EINVAL;
}
- r = tools_get_key(_("Enter passphrase for reencryption recovery: "),
- &password, &passwordLen, opt_keyfile_offset,
+ if (ri == CRYPT_REENCRYPT_CLEAN)
+ msg = _("Enter passphrase to verify reencryption metadata digest: ");
+ else
+ msg = _("Enter passphrase for reencryption recovery: ");
+
+ r = tools_get_key(msg, &password, &passwordLen, opt_keyfile_offset,
opt_keyfile_size, opt_key_file, opt_timeout,
_verify_passphrase(0), 0, cd);
if (r < 0)
@@ -1162,6 +1163,11 @@ static int _do_luks2_reencrypt_recovery(struct crypt_device *cd)
if (r < 0)
goto out;
+ if (ri == CRYPT_REENCRYPT_CLEAN) {
+ r = 0;
+ goto out;
+ }
+
r = crypt_reencrypt_init_by_passphrase(cd, NULL, password, passwordLen,
opt_key_slot, opt_key_slot, NULL, NULL, &recovery_params);
if (r > 0)
--
2.27.0

View File

@ -0,0 +1,22 @@
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_internal.h cryptsetup-2.3.3/lib/luks2/luks2_internal.h
--- cryptsetup-2.3.3.old/lib/luks2/luks2_internal.h 2022-01-17 16:10:00.756271915 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_internal.h 2022-01-17 16:11:59.845689051 +0100
@@ -206,4 +206,6 @@ static inline const char *crypt_reencryp
return "<unknown>";
}
+bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len);
+
#endif
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_segment.c cryptsetup-2.3.3/lib/luks2/luks2_segment.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_segment.c 2022-01-17 16:10:00.756271915 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_segment.c 2022-01-17 16:10:34.422389838 +0100
@@ -123,7 +123,7 @@ static json_object *json_segment_get_fla
return jobj;
}
-static bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len)
+bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len)
{
int r, i;
json_object *jobj, *jobj_flags = json_segment_get_flags(jobj_segment);

View File

@ -0,0 +1,783 @@
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2.h cryptsetup-2.3.3/lib/luks2/luks2.h
--- cryptsetup-2.3.3.old/lib/luks2/luks2.h 2022-01-17 15:03:03.689201103 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2.h 2022-01-17 15:06:42.149966321 +0100
@@ -606,4 +606,8 @@ void crypt_reencrypt_unlock(struct crypt
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);
+int LUKS2_reencrypt_digest_verify(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct volume_key *vks);
+
#endif
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_internal.h cryptsetup-2.3.3/lib/luks2/luks2_internal.h
--- cryptsetup-2.3.3.old/lib/luks2/luks2_internal.h 2022-01-17 15:03:03.689201103 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_internal.h 2022-01-17 15:51:20.125346606 +0100
@@ -128,6 +128,12 @@ int placeholder_keyslot_alloc(struct cry
/* validate all keyslot implementations in hdr json */
int LUKS2_keyslots_validate(struct crypt_device *cd, json_object *hdr_jobj);
+int LUKS2_keyslot_jobj_area(json_object *jobj_keyslot, uint64_t *offset, uint64_t *length);
+
+int LUKS2_keyslot_reencrypt_digest_create(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct volume_key *vks);
+
typedef struct {
const char *name;
keyslot_alloc_func alloc;
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_json_metadata.c cryptsetup-2.3.3/lib/luks2/luks2_json_metadata.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_json_metadata.c 2022-01-17 15:03:03.689201103 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_json_metadata.c 2022-01-17 15:05:48.165777220 +0100
@@ -1371,24 +1371,63 @@ int LUKS2_config_set_flags(struct crypt_
*/
/* LUKS2 library requirements */
-static const struct {
+struct requirement_flag {
uint32_t flag;
+ uint32_t version;
const char *description;
-} requirements_flags[] = {
- { CRYPT_REQUIREMENT_OFFLINE_REENCRYPT, "offline-reencrypt" },
- { CRYPT_REQUIREMENT_ONLINE_REENCRYPT, "online-reencrypt" },
- { 0, NULL }
};
-static uint32_t get_requirement_by_name(const char *requirement)
+static const struct requirement_flag unknown_requirement_flag = { CRYPT_REQUIREMENT_UNKNOWN, 0, NULL };
+
+static const struct requirement_flag requirements_flags[] = {
+ { CRYPT_REQUIREMENT_OFFLINE_REENCRYPT,1, "offline-reencrypt" },
+ { CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 2, "online-reencrypt-v2" },
+ { CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 1, "online-reencrypt" },
+ { 0, 0, NULL }
+};
+
+static const struct requirement_flag *get_requirement_by_name(const char *requirement)
{
int i;
for (i = 0; requirements_flags[i].description; i++)
if (!strcmp(requirement, requirements_flags[i].description))
- return requirements_flags[i].flag;
+ return requirements_flags + i;
+
+ return &unknown_requirement_flag;
+}
+
+static const struct requirement_flag *stored_requirement_name_by_id(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t req_id)
+{
+ json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
+ int i, len;
+ const struct requirement_flag *req;
+
+ assert(hdr);
+ if (!hdr)
+ return NULL;
+
+ if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
+ return NULL;
+
+ if (!json_object_object_get_ex(jobj_config, "requirements", &jobj_requirements))
+ return NULL;
+
+ if (!json_object_object_get_ex(jobj_requirements, "mandatory", &jobj_mandatory))
+ return NULL;
+
+ len = (int) json_object_array_length(jobj_mandatory);
+ if (len <= 0)
+ return 0;
+
+ for (i = 0; i < len; i++) {
+ jobj = json_object_array_get_idx(jobj_mandatory, i);
+ req = get_requirement_by_name(json_object_get_string(jobj));
+ if (req->flag == req_id)
+ return req;
+ }
- return CRYPT_REQUIREMENT_UNKNOWN;
+ return NULL;
}
/*
@@ -1398,7 +1437,7 @@ int LUKS2_config_get_requirements(struct
{
json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
int i, len;
- uint32_t req;
+ const struct requirement_flag *req;
assert(hdr);
if (!hdr || !reqs)
@@ -1425,8 +1464,8 @@ int LUKS2_config_get_requirements(struct
jobj = json_object_array_get_idx(jobj_mandatory, i);
req = get_requirement_by_name(json_object_get_string(jobj));
log_dbg(cd, "%s - %sknown", json_object_get_string(jobj),
- reqs_unknown(req) ? "un" : "");
- *reqs |= req;
+ reqs_unknown(req->flag) ? "un" : "");
+ *reqs |= req->flag;
}
return 0;
@@ -1436,6 +1475,8 @@ int LUKS2_config_set_requirements(struct
{
json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
int i, r = -EINVAL;
+ const struct requirement_flag *req;
+ uint32_t req_id;
if (!hdr)
return -EINVAL;
@@ -1445,8 +1486,14 @@ int LUKS2_config_set_requirements(struct
return -ENOMEM;
for (i = 0; requirements_flags[i].description; i++) {
- if (reqs & requirements_flags[i].flag) {
- jobj = json_object_new_string(requirements_flags[i].description);
+ req_id = reqs & requirements_flags[i].flag;
+ if (req_id) {
+ /* retain already stored version of requirement flag */
+ req = stored_requirement_name_by_id(cd, hdr, req_id);
+ if (req)
+ jobj = json_object_new_string(req->description);
+ else
+ jobj = json_object_new_string(requirements_flags[i].description);
if (!jobj) {
r = -ENOMEM;
goto err;
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_keyslot.c cryptsetup-2.3.3/lib/luks2/luks2_keyslot.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_keyslot.c 2022-01-17 15:03:03.689201103 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_keyslot.c 2022-01-17 15:05:48.165777220 +0100
@@ -281,19 +281,9 @@ crypt_keyslot_info LUKS2_keyslot_info(st
return CRYPT_SLOT_ACTIVE;
}
-int LUKS2_keyslot_area(struct luks2_hdr *hdr,
- int keyslot,
- uint64_t *offset,
- uint64_t *length)
+int LUKS2_keyslot_jobj_area(json_object *jobj_keyslot, uint64_t *offset, uint64_t *length)
{
- json_object *jobj_keyslot, *jobj_area, *jobj;
-
- if(LUKS2_keyslot_info(hdr, keyslot) == CRYPT_SLOT_INVALID)
- return -EINVAL;
-
- jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
- if (!jobj_keyslot)
- return -ENOENT;
+ json_object *jobj_area, *jobj;
if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
return -EINVAL;
@@ -309,6 +299,23 @@ int LUKS2_keyslot_area(struct luks2_hdr
return 0;
}
+int LUKS2_keyslot_area(struct luks2_hdr *hdr,
+ int keyslot,
+ uint64_t *offset,
+ uint64_t *length)
+{
+ json_object *jobj_keyslot;
+
+ if (LUKS2_keyslot_info(hdr, keyslot) == CRYPT_SLOT_INVALID)
+ return -EINVAL;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+ if (!jobj_keyslot)
+ return -ENOENT;
+
+ return LUKS2_keyslot_jobj_area(jobj_keyslot, offset, length);
+}
+
static int _open_and_verify(struct crypt_device *cd,
struct luks2_hdr *hdr,
const keyslot_handler *h,
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_keyslot_reenc.c cryptsetup-2.3.3/lib/luks2/luks2_keyslot_reenc.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_keyslot_reenc.c 2022-01-17 15:03:03.689201103 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_keyslot_reenc.c 2022-01-17 15:59:15.897013127 +0100
@@ -179,6 +179,7 @@ static int reenc_keyslot_store(struct cr
int reenc_keyslot_update(struct crypt_device *cd,
const struct luks2_reenc_context *rh)
{
+ int r;
json_object *jobj_keyslot, *jobj_area, *jobj_area_type;
struct luks2_hdr *hdr;
@@ -208,11 +209,23 @@ int reenc_keyslot_update(struct crypt_de
} else
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 int reenc_keyslot_wipe(struct crypt_device *cd, int keyslot)
{
+ struct luks2_hdr *hdr;
+
+ if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
+ return -EINVAL;
+
+ /* remove reencryption verification data */
+ LUKS2_digest_assign(cd, hdr, keyslot, CRYPT_ANY_DIGEST, 0, 0);
+
return 0;
}
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_reencrypt.c cryptsetup-2.3.3/lib/luks2/luks2_reencrypt.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_reencrypt.c 2022-01-17 15:03:03.689201103 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_reencrypt.c 2022-01-17 15:57:08.906568302 +0100
@@ -2390,6 +2390,10 @@ static int reencrypt_init(struct crypt_d
if (r < 0)
goto err;
+ r = LUKS2_keyslot_reencrypt_digest_create(cd, hdr, *vks);
+ if (r < 0)
+ goto err;
+
if (name && params->mode != CRYPT_REENCRYPT_ENCRYPT) {
r = reencrypt_verify_and_upload_keys(cd, hdr, LUKS2_reencrypt_digest_old(hdr), LUKS2_reencrypt_digest_new(hdr), *vks);
if (r)
@@ -2520,20 +2524,28 @@ static int reencrypt_context_update(stru
static int reencrypt_load(struct crypt_device *cd, struct luks2_hdr *hdr,
uint64_t device_size,
const struct crypt_params_reencrypt *params,
+ struct volume_key *vks,
struct luks2_reenc_context **rh)
{
int r;
struct luks2_reenc_context *tmp = NULL;
crypt_reencrypt_info ri = LUKS2_reenc_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)
r = reencrypt_load_clean(cd, hdr, device_size, &tmp, params);
else if (ri == CRYPT_REENCRYPT_CRASH)
r = reencrypt_load_crashed(cd, hdr, device_size, &tmp);
- else if (ri == CRYPT_REENCRYPT_NONE) {
- log_err(cd, _("Device not marked for LUKS2 reencryption."));
- return -EINVAL;
- } else
+ else
r = -EINVAL;
if (r < 0 || !tmp) {
@@ -2781,7 +2793,7 @@ static int reencrypt_load_by_passphrase(
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)
goto err;
@@ -3001,13 +3013,6 @@ static reenc_status_t reencrypt_step(str
{
int r;
- /* update reencrypt keyslot protection parameters in memory only */
- r = reenc_keyslot_update(cd, rh);
- if (r < 0) {
- log_dbg(cd, "Keyslot update failed.");
- return REENC_ERR;
- }
-
/* in memory only */
r = reencrypt_make_segments(cd, hdr, rh, device_size);
if (r)
@@ -3272,6 +3277,15 @@ int crypt_reencrypt(struct crypt_device
rs = REENC_OK;
+ /* update reencrypt keyslot protection parameters in memory only */
+ if (!quit && (rh->device_size > rh->progress)) {
+ r = reenc_keyslot_update(cd, rh);
+ if (r < 0) {
+ log_dbg(cd, "Keyslot update failed.");
+ return reencrypt_teardown(cd, hdr, rh, REENC_ERR, quit, progress);
+ }
+ }
+
while (!quit && (rh->device_size > rh->progress)) {
rs = reencrypt_step(cd, hdr, rh, rh->device_size, rh->online);
if (rs != REENC_OK)
@@ -3304,7 +3318,7 @@ static int reencrypt_recovery(struct cry
int r;
struct luks2_reenc_context *rh = NULL;
- r = reencrypt_load(cd, hdr, device_size, NULL, &rh);
+ r = reencrypt_load(cd, hdr, device_size, NULL, vks, &rh);
if (r < 0) {
log_err(cd, _("Failed to load LUKS2 reencryption context."));
return r;
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_reencrypt_digest.c cryptsetup-2.3.3/lib/luks2/luks2_reencrypt_digest.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_reencrypt_digest.c 1970-01-01 01:00:00.000000000 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_reencrypt_digest.c 2022-01-17 15:05:48.166777223 +0100
@@ -0,0 +1,381 @@
+/*
+ * LUKS - Linux Unified Key Setup v2, reencryption digest helpers
+ *
+ * Copyright (C) 2022, Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2022, Ondrej Kozina
+ * Copyright (C) 2022, Milan Broz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "luks2_internal.h"
+#include <assert.h>
+
+#define MAX_STR 64
+
+struct jtype {
+ enum { JNONE = 0, JSTR, JU64, JX64, JU32 } type;
+ json_object *jobj;
+ const char *id;
+};
+
+static size_t sr(struct jtype *j, uint8_t *ptr)
+{
+ json_object *jobj;
+ size_t len = 0;
+ uint64_t u64;
+ uint32_t u32;
+
+ if (!json_object_is_type(j->jobj, json_type_object))
+ return 0;
+
+ if (!json_object_object_get_ex(j->jobj, j->id, &jobj))
+ return 0;
+
+ switch(j->type) {
+ case JSTR: /* JSON string */
+ if (!json_object_is_type(jobj, json_type_string))
+ return 0;
+ len = strlen(json_object_get_string(jobj));
+ if (len > MAX_STR)
+ return 0;
+ if (ptr)
+ memcpy(ptr, json_object_get_string(jobj), len);
+ break;
+ case JU64: /* Unsigned 64bit integer stored as string */
+ if (!json_object_is_type(jobj, json_type_string))
+ break;
+ len = sizeof(u64);
+ if (ptr) {
+ u64 = cpu_to_be64(crypt_jobj_get_uint64(jobj));
+ memcpy(ptr, &u64, len);
+ }
+ break;
+ case JX64: /* Unsigned 64bit segment size (allows "dynamic") */
+ if (!json_object_is_type(jobj, json_type_string))
+ break;
+ if (!strcmp(json_object_get_string(jobj), "dynamic")) {
+ len = strlen("dynamic");
+ if (ptr)
+ memcpy(ptr, json_object_get_string(jobj), len);
+ } else {
+ len = sizeof(u64);
+ u64 = cpu_to_be64(crypt_jobj_get_uint64(jobj));
+ if (ptr)
+ memcpy(ptr, &u64, len);
+ }
+ break;
+ case JU32: /* Unsigned 32bit integer, stored as JSON int */
+ if (!json_object_is_type(jobj, json_type_int))
+ return 0;
+ len = sizeof(u32);
+ if (ptr) {
+ u32 = cpu_to_be32(crypt_jobj_get_uint32(jobj));
+ memcpy(ptr, &u32, len);
+ }
+ break;
+ case JNONE:
+ return 0;
+ };
+
+ return len;
+}
+
+static size_t srs(struct jtype j[], uint8_t *ptr)
+{
+ size_t l, len = 0;
+
+ while(j->jobj) {
+ l = sr(j, ptr);
+ if (!l)
+ return 0;
+ len += l;
+ if (ptr)
+ ptr += l;
+ j++;
+ }
+ return len;
+}
+
+static size_t segment_linear_serialize(json_object *jobj_segment, uint8_t *buffer)
+{
+ struct jtype j[] = {
+ { JSTR, jobj_segment, "type" },
+ { JU64, jobj_segment, "offset" },
+ { JX64, jobj_segment, "size" },
+ {}
+ };
+ return srs(j, buffer);
+}
+
+static size_t segment_crypt_serialize(json_object *jobj_segment, uint8_t *buffer)
+{
+ struct jtype j[] = {
+ { JSTR, jobj_segment, "type" },
+ { JU64, jobj_segment, "offset" },
+ { JX64, jobj_segment, "size" },
+ { JU64, jobj_segment, "iv_tweak" },
+ { JSTR, jobj_segment, "encryption" },
+ { JU32, jobj_segment, "sector_size" },
+ {}
+ };
+ return srs(j, buffer);
+}
+
+static size_t segment_serialize(json_object *jobj_segment, uint8_t *buffer)
+{
+ json_object *jobj_type;
+ const char *segment_type;
+
+ if (!json_object_object_get_ex(jobj_segment, "type", &jobj_type))
+ return 0;
+
+ if (!(segment_type = json_object_get_string(jobj_type)))
+ return 0;
+
+ if (!strcmp(segment_type, "crypt"))
+ return segment_crypt_serialize(jobj_segment, buffer);
+ else if (!strcmp(segment_type, "linear"))
+ return segment_linear_serialize(jobj_segment, buffer);
+
+ return 0;
+}
+
+static size_t backup_segments_serialize(struct luks2_hdr *hdr, uint8_t *buffer)
+{
+ json_object *jobj_segment;
+ size_t l, len = 0;
+
+ jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-previous");
+ if (!jobj_segment || !(l = segment_serialize(jobj_segment, buffer)))
+ return 0;
+ len += l;
+ if (buffer)
+ buffer += l;
+
+ jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-final");
+ if (!jobj_segment || !(l = segment_serialize(jobj_segment, buffer)))
+ return 0;
+ len += l;
+ if (buffer)
+ buffer += l;
+
+ jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-moved-segment");
+ if (jobj_segment) {
+ if (!(l = segment_serialize(jobj_segment, buffer)))
+ return 0;
+ len += l;
+ }
+
+ return len;
+}
+
+static size_t reenc_keyslot_serialize(struct luks2_hdr *hdr, uint8_t *buffer)
+{
+ json_object *jobj_keyslot, *jobj_area, *jobj_type;
+ const char *area_type;
+ int keyslot_reencrypt;
+
+ keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
+ if (keyslot_reencrypt < 0)
+ return 0;
+
+ if (!(jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot_reencrypt)))
+ return 0;
+
+ if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
+ return 0;
+
+ if (!json_object_object_get_ex(jobj_area, "type", &jobj_type))
+ return 0;
+
+ if (!(area_type = json_object_get_string(jobj_type)))
+ return 0;
+
+ struct jtype j[] = {
+ { JSTR, jobj_keyslot, "mode" },
+ { JSTR, jobj_keyslot, "direction" },
+ { JSTR, jobj_area, "type" },
+ { JU64, jobj_area, "offset" },
+ { JU64, jobj_area, "size" },
+ {}
+ };
+ struct jtype j_datashift[] = {
+ { JSTR, jobj_keyslot, "mode" },
+ { JSTR, jobj_keyslot, "direction" },
+ { JSTR, jobj_area, "type" },
+ { JU64, jobj_area, "offset" },
+ { JU64, jobj_area, "size" },
+ { JU64, jobj_area, "shift_size" },
+ {}
+ };
+ struct jtype j_checksum[] = {
+ { JSTR, jobj_keyslot, "mode" },
+ { JSTR, jobj_keyslot, "direction" },
+ { JSTR, jobj_area, "type" },
+ { JU64, jobj_area, "offset" },
+ { JU64, jobj_area, "size" },
+ { JSTR, jobj_area, "hash" },
+ { JU32, jobj_area, "sector_size" },
+ {}
+ };
+
+ if (!strcmp(area_type, "datashift"))
+ return srs(j_datashift, buffer);
+ else if (!strcmp(area_type, "checksum"))
+ return srs(j_checksum, buffer);
+
+ return srs(j, buffer);
+}
+
+static size_t blob_serialize(void *blob, size_t length, uint8_t *buffer)
+{
+ if (buffer)
+ memcpy(buffer, blob, length);
+
+ return length;
+}
+
+static int reencrypt_assembly_verification_data(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct volume_key *vks,
+ struct volume_key **verification_data)
+{
+ uint8_t *ptr;
+ int digest_new, digest_old;
+ struct volume_key *data = NULL, *vk_old = NULL, *vk_new = NULL;
+ size_t keyslot_data_len, segments_data_len, data_len = 2;
+
+ /* Keys - calculate length */
+ digest_new = LUKS2_reencrypt_digest_new(hdr);
+ digest_old = LUKS2_reencrypt_digest_old(hdr);
+
+ if (digest_old >= 0) {
+ vk_old = crypt_volume_key_by_id(vks, digest_old);
+ if (!vk_old)
+ return -EINVAL;
+ data_len += blob_serialize(vk_old->key, vk_old->keylength, NULL);
+ }
+
+ if (digest_new >= 0 && digest_old != digest_new) {
+ vk_new = crypt_volume_key_by_id(vks, digest_new);
+ if (!vk_new)
+ return -EINVAL;
+ data_len += blob_serialize(vk_new->key, vk_new->keylength, NULL);
+ }
+
+ if (data_len == 2)
+ return -EINVAL;
+
+ /* Metadata - calculate length */
+ if (!(keyslot_data_len = reenc_keyslot_serialize(hdr, NULL)))
+ return -EINVAL;
+ data_len += keyslot_data_len;
+
+ if (!(segments_data_len = backup_segments_serialize(hdr, NULL)))
+ return -EINVAL;
+ data_len += segments_data_len;
+
+ /* Alloc and fill serialization data */
+ data = crypt_alloc_volume_key(data_len, NULL);
+ if (!data)
+ return -ENOMEM;
+
+ ptr = (uint8_t*)data->key;
+
+ /* v2 */
+ *ptr++ = 0x76;
+ *ptr++ = 0x32;
+
+ if (vk_old)
+ ptr += blob_serialize(vk_old->key, vk_old->keylength, ptr);
+
+ if (vk_new)
+ ptr += blob_serialize(vk_new->key, vk_new->keylength, ptr);
+
+ if (!reenc_keyslot_serialize(hdr, ptr))
+ goto bad;
+ ptr += keyslot_data_len;
+
+ if (!backup_segments_serialize(hdr, ptr))
+ goto bad;
+ ptr += segments_data_len;
+
+ assert((size_t)(ptr - (uint8_t*)data->key) == data_len);
+
+ *verification_data = data;
+
+ return 0;
+bad:
+ crypt_free_volume_key(data);
+ return -EINVAL;
+}
+
+int LUKS2_keyslot_reencrypt_digest_create(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct volume_key *vks)
+{
+ int digest_reencrypt, keyslot_reencrypt, r;
+ struct volume_key *data;
+
+ keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
+ if (keyslot_reencrypt < 0)
+ return keyslot_reencrypt;
+
+ r = reencrypt_assembly_verification_data(cd, hdr, vks, &data);
+ if (r < 0)
+ return r;
+
+ r = LUKS2_digest_create(cd, "pbkdf2", hdr, data);
+ crypt_free_volume_key(data);
+ if (r < 0)
+ return r;
+
+ digest_reencrypt = r;
+
+ r = LUKS2_digest_assign(cd, hdr, keyslot_reencrypt, CRYPT_ANY_DIGEST, 0, 0);
+ if (r < 0)
+ return r;
+
+ return LUKS2_digest_assign(cd, hdr, keyslot_reencrypt, digest_reencrypt, 1, 0);
+}
+
+int LUKS2_reencrypt_digest_verify(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct volume_key *vks)
+{
+ int r, keyslot_reencrypt;
+ struct volume_key *data;
+
+ keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
+ if (keyslot_reencrypt < 0)
+ return keyslot_reencrypt;
+
+ r = reencrypt_assembly_verification_data(cd, hdr, vks, &data);
+ if (r < 0)
+ return r;
+
+ r = LUKS2_digest_verify(cd, hdr, data, keyslot_reencrypt);
+ crypt_free_volume_key(data);
+
+ if (r < 0) {
+ if (r == -ENOENT)
+ log_dbg(cd, "Reencryption digest is missing.");
+ log_err(cd, _("Reencryption metadata is invalid."));
+ } else
+ log_dbg(cd, "Reencryption metadata verified.");
+
+ return r;
+}
diff -rupN cryptsetup-2.3.3.old/lib/Makemodule.am cryptsetup-2.3.3/lib/Makemodule.am
--- cryptsetup-2.3.3.old/lib/Makemodule.am 2022-01-17 15:03:03.687201096 +0100
+++ cryptsetup-2.3.3/lib/Makemodule.am 2022-01-17 15:05:48.164777216 +0100
@@ -104,6 +104,7 @@ libcryptsetup_la_SOURCES = \
lib/luks2/luks2_keyslot_luks2.c \
lib/luks2/luks2_keyslot_reenc.c \
lib/luks2/luks2_reencrypt.c \
+ lib/luks2/luks2_reencrypt_digest.c \
lib/luks2/luks2_segment.c \
lib/luks2/luks2_token_keyring.c \
lib/luks2/luks2_token.c \
diff -rupN cryptsetup-2.3.3.old/lib/setup.c cryptsetup-2.3.3/lib/setup.c
--- cryptsetup-2.3.3.old/lib/setup.c 2022-01-17 15:03:03.686201093 +0100
+++ cryptsetup-2.3.3/lib/setup.c 2022-01-17 16:00:07.797194917 +0100
@@ -4032,6 +4032,12 @@ static int _open_and_activate_reencrypt_
keyslot = r;
}
+ if (r >= 0) {
+ r = LUKS2_reencrypt_digest_verify(cd, hdr, vks);
+ if (r < 0)
+ goto err;
+ }
+
log_dbg(cd, "Entering clean reencryption state mode.");
if (r >= 0)
@@ -4059,8 +4065,9 @@ static int _open_and_activate_luks2(stru
uint32_t flags)
{
crypt_reencrypt_info ri;
- int r;
+ int r, rv;
struct luks2_hdr *hdr = &cd->u.luks2.hdr;
+ struct volume_key *vks = NULL;
ri = LUKS2_reenc_status(hdr);
if (ri == CRYPT_REENCRYPT_INVALID)
@@ -4070,9 +4077,17 @@ static int _open_and_activate_luks2(stru
if (name)
r = _open_and_activate_reencrypt_device(cd, hdr, keyslot, name, passphrase,
passphrase_size, flags);
- else
+ else {
r = _open_all_keys(cd, hdr, keyslot, passphrase,
- passphrase_size, flags, NULL);
+ passphrase_size, flags, &vks);
+ if (r < 0)
+ return r;
+
+ rv = LUKS2_reencrypt_digest_verify(cd, hdr, vks);
+ crypt_free_volume_key(vks);
+ if (rv < 0)
+ return rv;
+ }
} else
r = _open_and_activate(cd, keyslot, name, passphrase,
passphrase_size, flags);
diff -rupN cryptsetup-2.3.3.old/po/POTFILES.in cryptsetup-2.3.3/po/POTFILES.in
--- cryptsetup-2.3.3.old/po/POTFILES.in 2022-01-17 15:03:03.694201121 +0100
+++ cryptsetup-2.3.3/po/POTFILES.in 2022-01-17 15:05:48.166777223 +0100
@@ -37,6 +37,7 @@ lib/luks2/luks2_keyslot_luks2.c
lib/luks2/luks2_keyslot_reenc.c
lib/luks2/luks2_luks1_convert.c
lib/luks2/luks2_reencrypt.c
+lib/luks2/luks2_reencrypt_digest.c
lib/luks2/luks2_segment.c
lib/luks2/luks2_token.c
lib/luks2/luks2_token_keyring.c

View File

@ -0,0 +1,25 @@
From b1ef7cc3cdfb708bb08c90425a7dbdef383da84c Mon Sep 17 00:00:00 2001
From: Milan Broz <gmazyland@gmail.com>
Date: Thu, 13 Jan 2022 10:12:45 +0100
Subject: [PATCH 27/28] Fix reencrypt mangle test for older jq.
---
tests/luks2-reencryption-mangle-test | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/luks2-reencryption-mangle-test b/tests/luks2-reencryption-mangle-test
index 0cca23a0..8f308f5d 100755
--- a/tests/luks2-reencryption-mangle-test
+++ b/tests/luks2-reencryption-mangle-test
@@ -51,7 +51,7 @@ function img_json_save()
# FIXME: why --json-file cannot be used?
#$CRYPTSETUP luksDump --dump-json-metadata $IMG | jq -c -M | tr -d '\n' >$IMG_JSON
local LUKS2_JSON_SIZE=$(($JSON_MSIZE - 4096))
- _dd if=$IMG count=$LUKS2_JSON_SIZE skip=4096 | jq -c -M | tr -d '\n' >$IMG_JSON
+ _dd if=$IMG count=$LUKS2_JSON_SIZE skip=4096 | jq -c -M . | tr -d '\n' >$IMG_JSON
}
function img_json_dump()
--
2.27.0

View File

@ -0,0 +1,93 @@
From c75d740f9abd8a005975517008f780b16d103b0a Mon Sep 17 00:00:00 2001
From: Ondrej Kozina <okozina@redhat.com>
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

View File

@ -0,0 +1,60 @@
From 4e98b65c04b624888b39216c81da17b2d0aedfb8 Mon Sep 17 00:00:00 2001
From: Ondrej Kozina <okozina@redhat.com>
Date: Thu, 6 Jan 2022 14:28:36 +0100
Subject: [PATCH 15/28] Move requirement helpers for later changes.
---
lib/luks2/luks2_json_metadata.c | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/lib/luks2/luks2_json_metadata.c b/lib/luks2/luks2_json_metadata.c
index 6071b077..e45a9739 100644
--- a/lib/luks2/luks2_json_metadata.c
+++ b/lib/luks2/luks2_json_metadata.c
@@ -591,6 +591,21 @@ static bool validate_segment_intervals(struct crypt_device *cd,
return true;
}
+static int reqs_unknown(uint32_t reqs)
+{
+ return reqs & CRYPT_REQUIREMENT_UNKNOWN;
+}
+
+static int reqs_reencrypt(uint32_t reqs)
+{
+ return reqs & CRYPT_REQUIREMENT_OFFLINE_REENCRYPT;
+}
+
+static int reqs_reencrypt_online(uint32_t reqs)
+{
+ return reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
+}
+
static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
{
json_object *jobj_segments, *jobj_digests, *jobj_offset, *jobj_size, *jobj_type, *jobj_flags, *jobj;
@@ -1138,21 +1153,6 @@ int LUKS2_hdr_backup(struct crypt_device *cd, struct luks2_hdr *hdr,
return r;
}
-static int reqs_unknown(uint32_t reqs)
-{
- return reqs & CRYPT_REQUIREMENT_UNKNOWN;
-}
-
-static int reqs_reencrypt(uint32_t reqs)
-{
- return reqs & CRYPT_REQUIREMENT_OFFLINE_REENCRYPT;
-}
-
-static int reqs_reencrypt_online(uint32_t reqs)
-{
- return reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
-}
-
int LUKS2_hdr_restore(struct crypt_device *cd, struct luks2_hdr *hdr,
const char *backup_file)
{
--
2.27.0

View File

@ -0,0 +1,45 @@
From 7eeb45537af1db8a29b4e2956545ccde8ad13d32 Mon Sep 17 00:00:00 2001
From: Milan Broz <gmazyland@gmail.com>
Date: Sun, 2 Jan 2022 16:57:31 +0100
Subject: [PATCH 12/28] Reenc keyslot must have key_size == 1.
---
lib/luks2/luks2_keyslot_reenc.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/lib/luks2/luks2_keyslot_reenc.c b/lib/luks2/luks2_keyslot_reenc.c
index 1956fe27..9da7007d 100644
--- a/lib/luks2/luks2_keyslot_reenc.c
+++ b/lib/luks2/luks2_keyslot_reenc.c
@@ -230,7 +230,7 @@ static int reenc_keyslot_dump(struct crypt_device *cd, int keyslot)
static int reenc_keyslot_validate(struct crypt_device *cd, json_object *jobj_keyslot)
{
- json_object *jobj_mode, *jobj_area, *jobj_type, *jobj_shift_size, *jobj_hash, *jobj_sector_size, *jobj_direction;
+ json_object *jobj_mode, *jobj_area, *jobj_type, *jobj_shift_size, *jobj_hash, *jobj_sector_size, *jobj_direction, *jobj_key_size;
const char *mode, *type, *direction;
uint32_t sector_size;
uint64_t shift_size;
@@ -250,12 +250,18 @@ static int reenc_keyslot_validate(struct crypt_device *cd, json_object *jobj_key
!json_object_object_get_ex(jobj_area, "type", &jobj_type))
return -EINVAL;
+ jobj_key_size = json_contains(cd, jobj_keyslot, "", "reencrypt keyslot", "key_size", json_type_int);
jobj_mode = json_contains(cd, jobj_keyslot, "", "reencrypt keyslot", "mode", json_type_string);
jobj_direction = json_contains(cd, jobj_keyslot, "", "reencrypt keyslot", "direction", json_type_string);
- if (!jobj_mode || !jobj_direction)
+ if (!jobj_mode || !jobj_direction || !jobj_key_size)
return -EINVAL;
+ if (!validate_json_uint32(jobj_key_size) || crypt_jobj_get_uint32(jobj_key_size) != 1) {
+ log_dbg(cd, "Illegal reencrypt key size.");
+ return -EINVAL;
+ }
+
mode = json_object_get_string(jobj_mode);
type = json_object_get_string(jobj_type);
direction = json_object_get_string(jobj_direction);
--
2.27.0

View File

@ -0,0 +1,46 @@
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2.h cryptsetup-2.3.3/lib/luks2/luks2.h
--- cryptsetup-2.3.3.old/lib/luks2/luks2.h 2022-01-17 16:17:59.479948764 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2.h 2022-01-17 16:20:30.466477626 +0100
@@ -284,7 +284,7 @@ int LUKS2_keyslot_reencrypt_store(struct
const void *buffer,
size_t buffer_length);
-int LUKS2_keyslot_reencrypt_create(struct crypt_device *cd,
+int LUKS2_keyslot_reencrypt_allocate(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
const struct crypt_params_reencrypt *params);
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_keyslot.c cryptsetup-2.3.3/lib/luks2/luks2_keyslot.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_keyslot.c 2022-01-17 16:17:59.478948761 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_keyslot.c 2022-01-17 16:19:00.458162353 +0100
@@ -596,7 +596,7 @@ int LUKS2_keyslot_open(struct crypt_devi
return r;
}
-int LUKS2_keyslot_reencrypt_create(struct crypt_device *cd,
+int LUKS2_keyslot_reencrypt_allocate(struct crypt_device *cd,
struct luks2_hdr *hdr,
int keyslot,
const struct crypt_params_reencrypt *params)
@@ -626,9 +626,6 @@ int LUKS2_keyslot_reencrypt_create(struc
return r;
}
- if (LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN))
- return -EINVAL;
-
return 0;
}
diff -rupN cryptsetup-2.3.3.old/lib/luks2/luks2_reencrypt.c cryptsetup-2.3.3/lib/luks2/luks2_reencrypt.c
--- cryptsetup-2.3.3.old/lib/luks2/luks2_reencrypt.c 2022-01-17 16:17:59.478948761 +0100
+++ cryptsetup-2.3.3/lib/luks2/luks2_reencrypt.c 2022-01-17 16:19:00.459162357 +0100
@@ -2375,7 +2375,7 @@ static int reencrypt_init(struct crypt_d
goto err;
}
- r = LUKS2_keyslot_reencrypt_create(cd, hdr, reencrypt_keyslot,
+ r = LUKS2_keyslot_reencrypt_allocate(cd, hdr, reencrypt_keyslot,
params);
if (r < 0)
goto err;

View File

@ -0,0 +1,57 @@
From d0169a303de017ff0c847a5f752a2449a76fdd17 Mon Sep 17 00:00:00 2001
From: Ondrej Kozina <okozina@redhat.com>
Date: Thu, 6 Jan 2022 14:47:44 +0100
Subject: [PATCH 17/28] Split requirements validation from config section
validation.
---
lib/luks2/luks2_json_metadata.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/lib/luks2/luks2_json_metadata.c b/lib/luks2/luks2_json_metadata.c
index e45a9739..9109b07a 100644
--- a/lib/luks2/luks2_json_metadata.c
+++ b/lib/luks2/luks2_json_metadata.c
@@ -855,9 +855,10 @@ static int hdr_validate_digests(struct crypt_device *cd, json_object *hdr_jobj)
return 0;
}
+/* requirements being validated in stand-alone routine */
static int hdr_validate_config(struct crypt_device *cd, json_object *hdr_jobj)
{
- json_object *jobj_config, *jobj, *jobj1;
+ json_object *jobj_config, *jobj;
int i;
uint64_t keyslots_size, metadata_size, segment_offset;
@@ -912,6 +913,19 @@ static int hdr_validate_config(struct crypt_device *cd, json_object *hdr_jobj)
return 1;
}
+ return 0;
+}
+
+static int hdr_validate_requirements(struct crypt_device *cd, json_object *hdr_jobj)
+{
+ int i;
+ json_object *jobj_config, *jobj, *jobj1;
+
+ if (!json_object_object_get_ex(hdr_jobj, "config", &jobj_config)) {
+ log_dbg(cd, "Missing config section.");
+ return 1;
+ }
+
/* Requirements object is optional */
if (json_object_object_get_ex(jobj_config, "requirements", &jobj)) {
if (!json_contains(cd, jobj_config, "section", "Config", "requirements", json_type_object))
@@ -937,6 +951,7 @@ int LUKS2_hdr_validate(struct crypt_device *cd, json_object *hdr_jobj, uint64_t
struct {
int (*validate)(struct crypt_device *, json_object *);
} checks[] = {
+ { hdr_validate_requirements },
{ hdr_validate_tokens },
{ hdr_validate_digests },
{ hdr_validate_segments },
--
2.27.0

View File

@ -0,0 +1,74 @@
diff -rupN cryptsetup-2.3.3.old/Makefile.in cryptsetup-2.3.3/Makefile.in
--- cryptsetup-2.3.3.old/Makefile.in 2020-05-28 11:32:48.000000000 +0200
+++ cryptsetup-2.3.3/Makefile.in 2022-01-14 14:58:17.797173340 +0100
@@ -292,6 +292,7 @@ am_libcryptsetup_la_OBJECTS = lib/libcry
lib/luks2/libcryptsetup_la-luks2_keyslot_luks2.lo \
lib/luks2/libcryptsetup_la-luks2_keyslot_reenc.lo \
lib/luks2/libcryptsetup_la-luks2_reencrypt.lo \
+ lib/luks2/libcryptsetup_la-luks2_reencrypt_digest.lo \
lib/luks2/libcryptsetup_la-luks2_segment.lo \
lib/luks2/libcryptsetup_la-luks2_token_keyring.lo \
lib/luks2/libcryptsetup_la-luks2_token.lo \
@@ -530,6 +531,7 @@ am__depfiles_remade = lib/$(DEPDIR)/libc
lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_reenc.Plo \
lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_luks1_convert.Plo \
lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt.Plo \
+ lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt_digest.Plo \
lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Plo \
lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token.Plo \
lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token_keyring.Plo \
@@ -1005,6 +1009,7 @@ libcryptsetup_la_SOURCES = \
lib/luks2/luks2_keyslot_luks2.c \
lib/luks2/luks2_keyslot_reenc.c \
lib/luks2/luks2_reencrypt.c \
+ lib/luks2/luks2_reencrypt_digest.c \
lib/luks2/luks2_segment.c \
lib/luks2/luks2_token_keyring.c \
lib/luks2/luks2_token.c \
@@ -1493,6 +1498,8 @@ lib/luks2/libcryptsetup_la-luks2_keyslot
lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp)
lib/luks2/libcryptsetup_la-luks2_reencrypt.lo: \
lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp)
+lib/luks2/libcryptsetup_la-luks2_reencrypt_digest.lo: \
+ lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp)
lib/luks2/libcryptsetup_la-luks2_segment.lo: \
lib/luks2/$(am__dirstamp) lib/luks2/$(DEPDIR)/$(am__dirstamp)
lib/luks2/libcryptsetup_la-luks2_token_keyring.lo: \
@@ -1670,6 +1677,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_reenc.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_luks1_convert.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt_digest.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token_keyring.Plo@am__quote@ # am--include-marker
@@ -2138,6 +2146,13 @@ lib/luks2/libcryptsetup_la-luks2_reencry
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks2/libcryptsetup_la-luks2_reencrypt.lo `test -f 'lib/luks2/luks2_reencrypt.c' || echo '$(srcdir)/'`lib/luks2/luks2_reencrypt.c
+lib/luks2/libcryptsetup_la-luks2_reencrypt_digest.lo: lib/luks2/luks2_reencrypt_digest.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks2/libcryptsetup_la-luks2_reencrypt_digest.lo -MD -MP -MF lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt_digest.Tpo -c -o lib/luks2/libcryptsetup_la-luks2_reencrypt_digest.lo `test -f 'lib/luks2/luks2_reencrypt_digest.c' || echo '$(srcdir)/'`lib/luks2/luks2_reencrypt_digest.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt_digest.Tpo lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt_digest.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/luks2/luks2_reencrypt_digest.c' object='lib/luks2/libcryptsetup_la-luks2_reencrypt_digest.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -c -o lib/luks2/libcryptsetup_la-luks2_reencrypt_digest.lo `test -f 'lib/luks2/luks2_reencrypt_digest.c' || echo '$(srcdir)/'`lib/luks2/luks2_reencrypt_digest.c
+
lib/luks2/libcryptsetup_la-luks2_segment.lo: lib/luks2/luks2_segment.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcryptsetup_la_CPPFLAGS) $(CPPFLAGS) $(libcryptsetup_la_CFLAGS) $(CFLAGS) -MT lib/luks2/libcryptsetup_la-luks2_segment.lo -MD -MP -MF lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Tpo -c -o lib/luks2/libcryptsetup_la-luks2_segment.lo `test -f 'lib/luks2/luks2_segment.c' || echo '$(srcdir)/'`lib/luks2/luks2_segment.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Tpo lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Plo
@@ -2738,6 +2754,7 @@ distclean: distclean-recursive
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_reenc.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_luks1_convert.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt.Plo
+ -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt_digest.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token_keyring.Plo
@@ -2864,6 +2881,7 @@ maintainer-clean: maintainer-clean-recur
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_keyslot_reenc.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_luks1_convert.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt.Plo
+ -rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_reencrypt_digest.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_segment.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token.Plo
-rm -f lib/luks2/$(DEPDIR)/libcryptsetup_la-luks2_token_keyring.Plo

View File

@ -0,0 +1,19 @@
diff -rupN cryptsetup-2.3.3.old/tests/Makefile.in cryptsetup-2.3.3/tests/Makefile.in
--- cryptsetup-2.3.3.old/tests/Makefile.in 2022-01-14 16:25:59.283158424 +0100
+++ cryptsetup-2.3.3/tests/Makefile.in 2022-01-14 16:27:15.094215021 +0100
@@ -441,6 +441,7 @@ EXTRA_DIST = compatimage.img.xz compatv1
reencryption-compat-test \
reencryption-compat-test2 \
luks2-reencryption-test \
+ luks2-reencryption-mangle-test \
tcrypt-compat-test \
luks1-compat-test \
luks2-validation-test generators \
@@ -1023,6 +1024,7 @@ valgrind-check: api-test api-test-2 diff
@INFOSTRING="api-test-000" ./valg-api.sh ./api-test
@INFOSTRING="api-test-002" ./valg-api.sh ./api-test-2
@VALG=1 ./luks2-reencryption-test
+ @VALG=1 ./luks2-reencryption-mangle-test
@VALG=1 ./compat-test
.PHONY: valgrind-check

View File

@ -5,7 +5,7 @@ Obsoletes: cryptsetup-python3
Summary: A utility for setting up encrypted disks
Name: cryptsetup
Version: 2.3.3
Release: 4%{?dist}
Release: 4%{?dist}.1
License: GPLv2+ and LGPLv2+
Group: Applications/System
URL: https://gitlab.com/cryptsetup/cryptsetup
@ -27,6 +27,24 @@ Patch2: %{name}-2.3.4-luks2-validation-32bit-fix.patch
Patch3: %{name}-2.3.4-fix-crypto-backend-to-properly-handle-ECB-mode.patch
Patch4: %{name}-2.3.5-fix-reencryption-cipher_null.patch
# CVE-2021-4122 fix
Patch5: %{name}-2.3.7-Fix-CVE-2021-4122-LUKS2-reencryption-crash-recovery-.patch
Patch6: %{name}-2.3.7-Reenc-keyslot-must-have-key_size-1.patch
Patch7: %{name}-2.3.7-Do-not-run-reencryption-recovery-when-not-needed.patch
Patch8: %{name}-2.3.7-Move-requirement-helpers-for-later-changes.patch
Patch9: %{name}-2.3.7-Expose-json_segment_contains_flag-to-internal-librar.patch
Patch10: %{name}-2.3.7-Split-requirements-validation-from-config-section-va.patch
Patch11: %{name}-2.3.7-Add-segments-validation-for-reencryption.patch
Patch12: %{name}-2.3.7-Rename-LUKS2_keyslot_reencrypt_create-function.patch
Patch13: %{name}-2.3.7-Make-reencryption-flag-and-keyslot-inseparable.patch
Patch14: %{name}-2.3.7-Add-reencryption-mangle-test.patch
# cryptsetup manual repair command able to upgrade/verify reencryption metadata
Patch15: %{name}-2.3.7-Add-CRYPT_REENCRYPT_REPAIR_NEEDED-flag.patch
Patch16: %{name}-2.3.7-Allow-reencryption-metadata-repair-from-cryptsetup.patch
Patch17: %{name}-2.3.7-Fix-reencrypt-mangle-test-for-older-jq.patch
Patch18: %{name}-Makefile-in.patch
Patch19: %{name}-tests-Makefile-in.patch
%description
The cryptsetup package contains a utility for setting up
disk encryption using dm-crypt kernel module.
@ -85,8 +103,24 @@ can be used for offline reencryption of disk in situ.
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch0 -p1
chmod -x misc/dracut_90reencrypt/*
chmod +x tests/luks2-reencryption-mangle-test
%build
%configure --enable-fips --enable-pwquality --enable-internal-sse-argon2 --with-crypto_backend=openssl --with-default-luks-format=LUKS2
@ -144,6 +178,10 @@ rm -rf %{buildroot}/%{_libdir}/*.la
%clean
%changelog
* Fri Jan 14 2022 Ondrej Kozina <okozina@redhat.com> - 2.3.3-4.1
- patch: fix CVE-2021-4122.
- Resolves: #2036906
* Wed Feb 17 2021 Ondrej Kozina <okozina@redhat.com> - 2.3.3-4
- patch: Fix reencryption for custom devices with data segments
set to use cipher_null.