227 lines
9.1 KiB
Diff
227 lines
9.1 KiB
Diff
|
From 37502d4c8974370a38496f44e279d56061fe67c3 Mon Sep 17 00:00:00 2001
|
||
|
From: Antz <antzz@protonmail.ch>
|
||
|
Date: Sat, 29 Aug 2020 14:54:19 +0200
|
||
|
Subject: [PATCH] 90crypt: make `rd.luks.key` usable with encrypted keydev.
|
||
|
|
||
|
Introduce prefix `keysource:` for the values of `rd.luks.partuuid`,
|
||
|
`rd.luks.serial` and `rd.luks.uuid`.
|
||
|
If specified, ask for passphrase instead of waiting for keydevs to come
|
||
|
online.
|
||
|
---
|
||
|
dracut.cmdline.7.asc | 45 ++++++++++++++++++++++++++++++++++++++
|
||
|
modules.d/90crypt/cryptroot-ask.sh | 18 +++++++++++++--
|
||
|
modules.d/90crypt/parse-crypt.sh | 43 ++++++++++++++++++++++++++----------
|
||
|
3 files changed, 92 insertions(+), 14 deletions(-)
|
||
|
|
||
|
diff --git a/dracut.cmdline.7.asc b/dracut.cmdline.7.asc
|
||
|
index c37d427e..dbbbfed0 100644
|
||
|
--- a/dracut.cmdline.7.asc
|
||
|
+++ b/dracut.cmdline.7.asc
|
||
|
@@ -302,6 +302,8 @@ crypto LUKS
|
||
|
The comparisons also matches, if _<luks uuid>_ is only the beginning of the
|
||
|
LUKS UUID, so you don't have to specify the full UUID.
|
||
|
This parameter can be specified multiple times.
|
||
|
+ _<luks uuid>_ may be prefixed by the keyword `keysource:`, see
|
||
|
+ _rd.luks.key_ below.
|
||
|
|
||
|
**rd.luks.allow-discards=**__<luks uuid>__::
|
||
|
Allow using of discards (TRIM) requests for LUKS partitions with the given
|
||
|
@@ -397,6 +399,49 @@ head -32c /dev/urandom > rootkey.key
|
||
|
cryptsetup --batch-mode --key-file rootkey.key \
|
||
|
luksFormat /dev/sda47
|
||
|
--
|
||
|
+
|
||
|
+You can also use regular key files on an encrypted _keydev_.
|
||
|
+
|
||
|
+Compared to using GPG encrypted keyfiles on an unencrypted
|
||
|
+device this provides the following advantages:
|
||
|
+
|
||
|
+- you can unlock your disk(s) using multiple passphrases
|
||
|
+- better security by not loosing the key stretching mechanism
|
||
|
+
|
||
|
+To use an encrypted _keydev_ you *must* ensure that it becomes
|
||
|
+available by using the keyword `keysource`, e.g.
|
||
|
+`rd.luks.uuid=keysource:aaaa`
|
||
|
+_aaaa_ being the uuid of the encrypted _keydev_.
|
||
|
+
|
||
|
+Example:
|
||
|
+
|
||
|
+Lets assume you have three disks _A_, _B_ and _C_ with the uuids
|
||
|
+_aaaa_, _bbbb_ and _cccc_. +
|
||
|
+You want to unlock _A_ and _B_ using keyfile _keyfile_. +
|
||
|
+The unlocked volumes be _A'_, _B'_ and _C'_ with the uuids
|
||
|
+_AAAA_, _BBBB_ and _CCCC_. +
|
||
|
+_keyfile_ is saved on _C'_ as _/keyfile_.
|
||
|
+
|
||
|
+One luks keyslot of each _A_, _B_ and _C_ is setup with a
|
||
|
+passphrase. +
|
||
|
+Another luks keyslot of each _A_ and _B_ is setup with _keyfile_.
|
||
|
+
|
||
|
+To boot this configuration you could use:
|
||
|
+[listing]
|
||
|
+--
|
||
|
+rd.luks.uuid=aaaa
|
||
|
+rd.luks.uuid=bbbb
|
||
|
+rd.luks.uuid=keysource:cccc
|
||
|
+rd.luks.key=/keyfile:UUID=CCCC
|
||
|
+--
|
||
|
+Dracut asks for the passphrase for _C_ and uses the
|
||
|
+keyfile to unlock _A_ and _B_. +
|
||
|
+If getting the passphrase for _C_ fails it falls back to
|
||
|
+asking for the passphrases for _A_ and _B_.
|
||
|
+
|
||
|
+If you want _C'_ to stay unlocked, specify a luks name for
|
||
|
+it, e.g. `rd.luks.name=cccc=mykeys`, otherwise it gets closed
|
||
|
+when not needed anymore.
|
||
|
===============================
|
||
|
|
||
|
MD RAID
|
||
|
diff --git a/modules.d/90crypt/cryptroot-ask.sh b/modules.d/90crypt/cryptroot-ask.sh
|
||
|
index 97047ae9..19d2bcb4 100755
|
||
|
--- a/modules.d/90crypt/cryptroot-ask.sh
|
||
|
+++ b/modules.d/90crypt/cryptroot-ask.sh
|
||
|
@@ -20,8 +20,11 @@ fi
|
||
|
# default luksname - luks-UUID
|
||
|
luksname=$2
|
||
|
|
||
|
+# is_keysource - ask for passphrase even if a rd.luks.key argument is set
|
||
|
+is_keysource=${3:-0}
|
||
|
+
|
||
|
# number of tries
|
||
|
-numtries=${3:-10}
|
||
|
+numtries=${4:-10}
|
||
|
|
||
|
# TODO: improve to support what cmdline does
|
||
|
if [ -f /etc/crypttab ] && getargbool 1 rd.luks.crypttab -d -n rd_NO_CRYPTTAB; then
|
||
|
@@ -137,6 +140,8 @@ if [ -n "$luksfile" -a "$luksfile" != "none" -a -e "$luksfile" ]; then
|
||
|
if cryptsetup --key-file "$luksfile" $cryptsetupopts luksOpen "$device" "$luksname"; then
|
||
|
ask_passphrase=0
|
||
|
fi
|
||
|
+elif [ "$is_keysource" -ne 0 ]; then
|
||
|
+ info "Asking for passphrase because $device is a keysource."
|
||
|
else
|
||
|
while [ -n "$(getarg rd.luks.key)" ]; do
|
||
|
if tmp=$(getkey /tmp/luks.keys $device); then
|
||
|
@@ -151,7 +156,7 @@ else
|
||
|
info "No key found for $device. Will try $numtries time(s) more later."
|
||
|
initqueue --unique --onetime --settled \
|
||
|
--name cryptroot-ask-$luksname \
|
||
|
- $(command -v cryptroot-ask) "$device" "$luksname" "$(($numtries-1))"
|
||
|
+ $(command -v cryptroot-ask) "$device" "$luksname" "$is_keysource" "$(($numtries-1))"
|
||
|
exit 0
|
||
|
fi
|
||
|
unset tmp
|
||
|
@@ -178,6 +183,15 @@ if [ $ask_passphrase -ne 0 ]; then
|
||
|
unset _timeout
|
||
|
fi
|
||
|
|
||
|
+if [ "$is_keysource" -ne 0 -a ${luksname##luks-} != "$luksname" ]; then
|
||
|
+ luks_close="$(command -v cryptsetup) close"
|
||
|
+ {
|
||
|
+ printf -- '[ -e /dev/mapper/%s ] && ' "$luksname"
|
||
|
+ printf -- '%s "%s"\n' "$luks_close" "$luksname"
|
||
|
+ } >> "$hookdir/cleanup/31-crypt-keysource.sh"
|
||
|
+ unset luks_close
|
||
|
+fi
|
||
|
+
|
||
|
unset device luksname luksfile
|
||
|
|
||
|
# mark device as asked
|
||
|
diff --git a/modules.d/90crypt/parse-crypt.sh b/modules.d/90crypt/parse-crypt.sh
|
||
|
index f6911cc8..4e899fed 100755
|
||
|
--- a/modules.d/90crypt/parse-crypt.sh
|
||
|
+++ b/modules.d/90crypt/parse-crypt.sh
|
||
|
@@ -49,6 +49,12 @@ else
|
||
|
if [ -n "$PARTUUID" ]; then
|
||
|
for uuid in $PARTUUID; do
|
||
|
|
||
|
+ is_keysource=0
|
||
|
+ _uuid=$uuid
|
||
|
+ uuid=${uuid#keysource:}
|
||
|
+ [ $uuid != $_uuid ] && is_keysource=1
|
||
|
+ unset _uuid
|
||
|
+
|
||
|
uuid=${uuid##luks-}
|
||
|
if luksname=$(_cryptgetargsname "rd.luks.name=$uuid="); then
|
||
|
luksname="${luksname#$uuid=}"
|
||
|
@@ -61,7 +67,7 @@ else
|
||
|
printf -- 'ENV{ID_PART_ENTRY_UUID}=="*%s*", ' "$uuid"
|
||
|
printf -- 'RUN+="%s --settled --unique --onetime ' "$(command -v initqueue)"
|
||
|
printf -- '--name cryptroot-ask-%%k %s ' "$(command -v cryptroot-ask)"
|
||
|
- printf -- '$env{DEVNAME} %s %s"\n' "$luksname" "$tout"
|
||
|
+ printf -- '$env{DEVNAME} %s %s"\n' "$luksname" "$is_keysource" "$tout"
|
||
|
} >> /etc/udev/rules.d/70-luks.rules.new
|
||
|
else
|
||
|
luksname=$(dev_unit_name "$luksname")
|
||
|
@@ -81,6 +87,12 @@ else
|
||
|
elif [ -n "$SERIAL" ]; then
|
||
|
for serialid in $SERIAL; do
|
||
|
|
||
|
+ is_keysource=0
|
||
|
+ _serialid=$serialid
|
||
|
+ serialid=${serialid#keysource:}
|
||
|
+ [ $serialid != $_serialid ] && is_keysource=1
|
||
|
+ unset _serialid
|
||
|
+
|
||
|
serialid=${serialid##luks-}
|
||
|
if luksname=$(_cryptgetargsname "rd.luks.name=$serialid="); then
|
||
|
luksname="${luksname#$serialid=}"
|
||
|
@@ -93,7 +105,7 @@ else
|
||
|
printf -- 'ENV{ID_SERIAL_SHORT}=="*%s*", ' "$serialid"
|
||
|
printf -- 'RUN+="%s --settled --unique --onetime ' "$(command -v initqueue)"
|
||
|
printf -- '--name cryptroot-ask-%%k %s ' "$(command -v cryptroot-ask)"
|
||
|
- printf -- '$env{DEVNAME} %s %s"\n' "$luksname" "$tout"
|
||
|
+ printf -- '$env{DEVNAME} %s %s"\n' "$luksname" "$is_keysource" "$tout"
|
||
|
} >> /etc/udev/rules.d/70-luks.rules.new
|
||
|
else
|
||
|
luksname=$(dev_unit_name "$luksname")
|
||
|
@@ -113,6 +125,12 @@ else
|
||
|
elif [ -n "$LUKS" ]; then
|
||
|
for luksid in $LUKS; do
|
||
|
|
||
|
+ is_keysource=0
|
||
|
+ _luksid=$luksid
|
||
|
+ luksid=${luksid#keysource:}
|
||
|
+ [ $luksid != $_luksid ] && is_keysource=1
|
||
|
+ unset _luksid
|
||
|
+
|
||
|
luksid=${luksid##luks-}
|
||
|
if luksname=$(_cryptgetargsname "rd.luks.name=$luksid="); then
|
||
|
luksname="${luksname#$luksid=}"
|
||
|
@@ -126,7 +144,7 @@ else
|
||
|
printf -- 'ENV{ID_FS_UUID}=="*%s*", ' "$luksid"
|
||
|
printf -- 'RUN+="%s --settled --unique --onetime ' "$(command -v initqueue)"
|
||
|
printf -- '--name cryptroot-ask-%%k %s ' "$(command -v cryptroot-ask)"
|
||
|
- printf -- '$env{DEVNAME} %s %s"\n' "$luksname" "$tout"
|
||
|
+ printf -- '$env{DEVNAME} %s %s %s"\n' "$luksname" "$is_keysource" "$tout"
|
||
|
} >> /etc/udev/rules.d/70-luks.rules.new
|
||
|
else
|
||
|
luksname=$(dev_unit_name "$luksname")
|
||
|
@@ -143,15 +161,16 @@ else
|
||
|
fi
|
||
|
fi
|
||
|
|
||
|
- uuid=$luksid
|
||
|
- while [ "$uuid" != "${uuid#*-}" ]; do uuid=${uuid%%-*}${uuid#*-}; done
|
||
|
- printf -- '[ -e /dev/disk/by-id/dm-uuid-CRYPT-LUKS?-*%s*-* ] || exit 1\n' $uuid \
|
||
|
- >> "$hookdir/initqueue/finished/90-crypt.sh"
|
||
|
-
|
||
|
- {
|
||
|
- printf -- '[ -e /dev/disk/by-uuid/*%s* ] || ' $luksid
|
||
|
- printf -- 'warn "crypto LUKS UUID "%s" not found"\n' $luksid
|
||
|
- } >> "$hookdir/emergency/90-crypt.sh"
|
||
|
+ if [ $is_keysource -eq 0 ]; then
|
||
|
+ uuid=$luksid
|
||
|
+ while [ "$uuid" != "${uuid#*-}" ]; do uuid=${uuid%%-*}${uuid#*-}; done
|
||
|
+ printf -- '[ -e /dev/disk/by-id/dm-uuid-CRYPT-LUKS?-*%s*-* ] || exit 1\n' $uuid \
|
||
|
+ >> "$hookdir/initqueue/finished/90-crypt.sh"
|
||
|
+ {
|
||
|
+ printf -- '[ -e /dev/disk/by-uuid/*%s* ] || ' $luksid
|
||
|
+ printf -- 'warn "crypto LUKS UUID "%s" not found"\n' $luksid
|
||
|
+ } >> "$hookdir/emergency/90-crypt.sh"
|
||
|
+ fi
|
||
|
done
|
||
|
elif getargbool 0 rd.auto; then
|
||
|
if [ -z "$DRACUT_SYSTEMD" ]; then
|
||
|
|