Fix dm-integrity HMAC recalculation problem.

This patch adds support for Linux kernel (since version 5.11) dm-integrity
fixes that disables integrity recalculation if keyed algorithms (HMAC) is used.

Original dm-integrity superblock version <=4 is recalculation offset
field not protected by HMAC. An attacker can move this pointer and force
the kernel to recalculate the data area, ignoring original HMAC tags.

N.B. dm-integrity was not intended to protect against intentional changes.
Better use authenticated encryption (AEAD) in combination with dm-crypt.
It is designed to protect against random data corruption caused by hardware
or storage medium faults.

Despite that, we try to keep the system secure if keyed algorithms are used.

There are two possible keyed algorithms in dm-integrity - algorithm used
to protect journal and superblock (--journal-integrity) and algorithms
for protecting data (--integrity).
The dm-integrity superblock is guarded by --journal-integrity, so if you want
to protect data with HMAC, you should always also use HMAC for --journal-integrity.
The keys are independent. If HMAC is used for data but not for the journal,
recalculation is disabled by default.

For new kernel dm-integrity, the HMAC option also uses salt in superblock
to avoid an easy way to distinguish that the HMAC key is the same for two devices
(if data are the same).

The new HMAC and superblock are enabled automatically if the kernel supports it
(you can see superblock version 5 and fix_hmac flag in dump command).

If you need to use (insecure) backward compatibility, then two new integritysetup
options are introduced:

 Use --integrity-legacy-recalc (instead of --integrity-recalc) to allow recalculation
 on legacy devices.

 Use --integrity-legacy-hmac in format action to force old insecure version
 format (with HMAC).

Libcryptsetup API also introduces flags
  CRYPT_COMPAT_LEGACY_INTEGRITY_HMAC and
  CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC
to set these through crypt_set_compatibility() call.
This commit is contained in:
Milan Broz
2021-01-23 20:08:19 +01:00
parent 6df3488654
commit 586b0a39d8
10 changed files with 117 additions and 5 deletions

View File

@@ -14,6 +14,7 @@ DEV_LOOP=""
DEV=test123.img
DEV2=test124.img
KEY_FILE=key.img
KEY_FILE2=key2.img
dmremove() { # device
udevadm settle >/dev/null 2>&1
@@ -25,7 +26,7 @@ cleanup() {
[ -b /dev/mapper/$DEV_NAME2 ] && dmremove $DEV_NAME2
[ -n "$DEV_LOOP" ] && losetup -d "$DEV_LOOP"
DEV_LOOP=""
rm -f $DEV $DEV2 $KEY_FILE >/dev/null 2>&1
rm -f $DEV $DEV2 $KEY_FILE $KEY_FILE2 >/dev/null 2>&1
}
fail()
@@ -60,11 +61,15 @@ function dm_integrity_features()
[ $VER_MIN -gt 2 ] && {
DM_INTEGRITY_BITMAP=1
}
[ $VER_MIN -gt 6 ] && {
DM_INTEGRITY_HMAC_FIX=1
}
}
add_device() {
cleanup
dd if=/dev/urandom of=$KEY_FILE bs=1 count=512 >/dev/null 2>&1
dd if=/dev/urandom of=$KEY_FILE2 bs=1 count=32 >/dev/null 2>&1
dd if=/dev/zero of=$DEV bs=1M count=32 >/dev/null 2>&1
dd if=/dev/zero of=$DEV2 bs=1M count=32 >/dev/null 2>&1
sync
@@ -459,4 +464,35 @@ else
echo "[N/A]"
fi
echo -n "Fixed HMAC and legacy flags:"
if [ -n "$DM_INTEGRITY_HMAC_FIX" ] ; then
add_device
# only data HMAC
ARGS="--integrity hmac-sha256 --integrity-key-file $KEY_FILE --integrity-key-size 32"
$INTSETUP format -q $DEV --integrity-legacy-hmac --no-wipe --tag-size 32 $ARGS || fail "Cannot format device."
$INTSETUP open $DEV $DEV_NAME --integrity-recalculate $ARGS >/dev/null 2>&1 && fail "Cannot activate device."
$INTSETUP open $DEV $DEV_NAME --integrity-legacy-recalculate $ARGS || fail "Cannot activate device."
$INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
# New version - must fail (no journal HMAC)
$INTSETUP format -q $DEV --no-wipe --tag-size 32 $ARGS || fail "Cannot format device."
$INTSETUP open $DEV $DEV_NAME --integrity-recalculate $ARGS >/dev/null 2>&1 && fail "Cannot activate device."
$INTSETUP open $DEV $DEV_NAME --integrity-legacy-recalculate $ARGS || fail "Cannot activate device."
$INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
# data and journal HMAC
ARGS="$ARGS --journal-integrity hmac-sha256 --journal-integrity-key-file $KEY_FILE2 --journal-integrity-key-size 32"
$INTSETUP format -q $DEV --integrity-legacy-hmac --no-wipe --tag-size 32 $ARGS || fail "Cannot format device."
$INTSETUP open $DEV $DEV_NAME --integrity-recalculate $ARGS >/dev/null 2>&1 && fail "Cannot activate device."
$INTSETUP open $DEV $DEV_NAME --integrity-legacy-recalculate $ARGS || fail "Cannot activate device."
$INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
# New fixed version
$INTSETUP format -q $DEV --no-wipe --tag-size 32 $ARGS || fail "Cannot format device."
$INTSETUP dump $DEV | grep "flags" | grep -q "fix_hmac" || fail "Flag for HMAC not set."
$INTSETUP open $DEV $DEV_NAME --integrity-recalculate $ARGS || fail "Cannot activate device."
$INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
echo "[OK]"
else
echo "[N/A]"
fi
cleanup