Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.debian.user > #200845
| From | Lfabbro <lfabbro11@protonmail.com> |
|---|---|
| Newsgroups | linux.debian.user |
| Subject | [stretch] unlock with keyfile LVM encrypted rootfs -- hung at boot |
| Date | 2018-10-03 11:10 +0200 |
| Message-ID | <wELkl-76A-1@gated-at.bofh.it> (permalink) |
| Organization | linux.* mail to news gateway |
[Multipart message — attachments visible in raw view] - view raw
Hello everyone!
I'm currently trying to find a method to decrypt my rootfs at boot time with a keyfile on debian stretch.
I've successfully implemented a method ([1] and [2]) which uses a custom script to read the first 2048bit
from the usbkey memory to decrypt the disk, but I actually need to store the keyfile on a filesystem.
Someone [3] told me about an old post on debian-user mailing list: https://lists.debian.org/debian-user/2017/12/msg00523.html
That's exactly what I need. I don't mind patching cryptroot script (appended [4]) to do it, so I decided to test it.
I've create a VM (kvm/qemu), partitioned the disks this way (a classic crypted debian LVM partitioning):
root@debian:~ $ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 1.2G 0 disk
vdb 8:16 0 20.8G 0 disk
├─vdb1 8:17 0 243M 0 part /boot
├─vdb2 8:18 0 1K 0 part
└─vdb5 8:21 0 20.5G 0 part
└─vdb5_crypt 254:0 0 20.5G 0 crypt
├─debian--vg-root 254:1 0 18G 0 lvm /
└─debian--vg-swap_1 254:2 0 2.3G 0 lvm [SWAP]
Configured as in the mailing list tutorial, updated initramfs, updated grub, rebooted.
I've followed the tutorial step by step, but still at boot time the system hung:
Reading all physical volumes. This may take a while...
WARNING: Failed to connect to lvmetad. Falling back to device scanning.
WARNING: Failed to connect to lvmetad. Falling back to device scanning.
Reading all physical volumes. This may take a while...
WARNING: Failed to connect to lvmetad. Falling back to device scanning.
...
ALERT! /dev/vdb5 does not exist.
Check cryptopts=source bootarg: cat /proc/cmdline
or missing modules. devices: cat /proc/modules: ls /dev
-r Dropping to a shell. Will skip /dev/vdb5 if you can't fix.
Busybox v1.22.1 (Debian 1:1.22.0-19+b3) built-in shell (ash)
Enter 'help' fro a list of built-int commands.
(initramfs)
(initramfs) _
It seems unable to find the disk to decrypt (/dev/vdb5).
I was so sad, I've thought I've found the right way...
So I digged more and suddenly I've thought maybe it could be my LVM partition scheme.
With no real expectations I've created another VM, with the following partition scheme:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sr0 11:0 1 1024M 0 rom
vda 254:0 0 20G 0 disk
|_vda1 254:0 0 953M 0 part /boot
|_vda2 254:0 0 1K 0 part
|_vda5 254:0 0 17G 0 part
|_vda5_crypt 254:0 0 17G 0 crypt /
|_vda6 254:0 0 2G 0 part
|_vda6_crypt 254:0 0 2G 0 crypt [SWAP]
Configured, updated, rebooted.
And it works!
So I'm a bit stuck here and I've decided to write to this mailing list hoping someone may illuminate me,
why does it hung with LVM partitioning?
Could there it be some tricks to make it work?
Now to my point of view I think it could be a missing or erroneous cmdline parameter, or/and the cryptroot script in the tutorial (appended [4]) maybe is causing this. But I don't know yet how to fix this.
The cmdline I used with LVM partitioning is:
BOOT_IMAGE=/vmlinuz-4.9.0-7-amd64 root=/dev/mapper/debian--vg-root ro cryptopts=target=vda5_crypt,source=/dev/disk/by-uuid/b59bb85d-abec-4562-90c3-1f3d0ab34036
The cmdline used without LVM:
BOOT_IMAGE=/vmlinuz-4.9.0-7-amd64 root=UUID=b59bb85d-abec-4562-90c3-1f3d0ab34036 ro quiet
I also tried to decrypt LVM partitioned device from initramfs panic shell, but I succeeded only on an actual machine, on a virtual machine the devices didn't appear (no /dev/vda).
A partitioning scheme without LVM may be ok to my usecase, but I would like to understand why it does not work and if it can be fixed.
Thank you for your time,
Lorenzo
REF:
[1] https://www.oxygenimpaired.com/debian-lenny-luks-encrypted-root-hidden-usb-keyfile
[2] https://www.oxygenimpaired.com/ubuntu-with-grub2-luks-encrypted-lvm-root-hidden-usb-keyfile
[3] https://unix.stackexchange.com/questions/471854/decrypt-root-device-at-boot-with-keyfile-on-usb-debian-stretch
[4] cryptroot script:
#!/bin/sh
PREREQ="cryptroot-prepare"
#
# Standard initramfs preamble
#
prereqs()
{
# Make sure that cryptroot is run last in local-top
for req in $(dirname $0)/*; do
script=${req##*/}
if [ $script != cryptroot ]; then
echo $script
fi
done
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
# source for log_*_msg() functions, see LP: #272301
. /scripts/functions
# define $askpass
askpass="/lib/cryptsetup/askpass"
#
# Helper functions
#
message()
{
if [ -x /bin/plymouth ] && plymouth --ping; then
plymouth message --text="$@"
else
echo "$@" >&2
fi
return 0
}
udev_settle()
{
# Wait for udev to be ready, see https://launchpad.net/bugs/85640
if command -v udevadm >/dev/null 2>&1; then
udevadm settle --timeout=30
elif command -v udevsettle >/dev/null 2>&1; then
udevsettle --timeout=30
fi
return 0
}
parse_options()
{
local cryptopts
cryptopts="$1"
if [ -z "$cryptopts" ]; then
return 1
fi
# Defaults
cryptcipher=aes-cbc-essiv:sha256
cryptsize=256
crypthash=ripemd160
crypttarget=cryptroot
cryptsource=""
cryptheader=""
cryptlvm=""
cryptkeyscript=""
cryptkey="" # This is only used as an argument to an eventual keyscript
cryptkeyslot=""
crypttries=3
crypttcrypt=""
cryptveracrypt=""
cryptrootdev=""
cryptdiscard=""
cryptaskpassfallback="yes"
CRYPTTAB_OPTIONS=""
local IFS=" ,"
for x in $cryptopts; do
case $x in
hash=*)
crypthash=${x#hash=}
;;
size=*)
cryptsize=${x#size=}
;;
cipher=*)
cryptcipher=${x#cipher=}
;;
target=*)
crypttarget=${x#target=}
export CRYPTTAB_NAME="$crypttarget"
;;
source=*)
cryptsource=${x#source=}
if [ ${cryptsource#UUID=} != $cryptsource ]; then
cryptsource="/dev/disk/by-uuid/${cryptsource#UUID=}"
elif [ ${cryptsource#LABEL=} != $cryptsource ]; then
cryptsource="/dev/disk/by-label/$(printf '%s' "${cryptsource#LABEL=}" | sed 's,/,\\x2f,g')"
fi
export CRYPTTAB_SOURCE="$cryptsource"
;;
header=*)
cryptheader=${x#header=}
if [ ! -e "$cryptheader" ] && [ -e "/conf/conf.d/cryptheader/$cryptheader" ]; then
cryptheader="/conf/conf.d/cryptheader/$cryptheader"
fi
export CRYPTTAB_HEADER="$cryptheader"
;;
lvm=*)
cryptlvm=${x#lvm=}
;;
keyscript=*)
cryptkeyscript=${x#keyscript=}
;;
key=*)
if [ "${x#key=}" != "none" ]; then
cryptkey=${x#key=}
fi
export CRYPTTAB_KEY="$cryptkey"
;;
keyslot=*)
cryptkeyslot=${x#keyslot=}
;;
tries=*)
crypttries="${x#tries=}"
case "$crypttries" in
*[![:digit:].]*)
crypttries=3
;;
esac
;;
tcrypt)
crypttcrypt="yes"
;;
veracrypt)
cryptveracrypt="--veracrypt"
;;
rootdev)
cryptrootdev="yes"
;;
discard)
cryptdiscard="yes"
;;
askpassfallback)
cryptaskpassfallback="yes"
;;
esac
PARAM="${x%=*}"
if [ "$PARAM" = "$x" ]; then
VALUE="yes"
else
VALUE="${x#*=}"
fi
CRYPTTAB_OPTIONS="$CRYPTTAB_OPTIONS $PARAM"
eval export CRYPTTAB_OPTION_$PARAM="\"$VALUE\""
done
export CRYPTTAB_OPTIONS
if [ -z "$cryptsource" ]; then
message "cryptsetup ($crypttarget): source parameter missing"
return 1
fi
return 0
}
activate_vg()
{
# Sanity checks
if [ ! -x /sbin/lvm ]; then
message "cryptsetup ($crypttarget): lvm is not available"
return 1
fi
# Detect and activate available volume groups
/sbin/lvm vgscan
/sbin/lvm vgchange -a y --sysinit
return $?
}
setup_mapping()
{
local opts count cryptopen cryptremove NEWROOT
opts="$1"
if [ -z "$opts" ]; then
return 0
fi
parse_options "$opts" || return 1
# disable cryptkeyscript - fall back to askpass.
if [ -n "$do_fallback" ]; then
cryptkeyscript=""
fi
if [ -z "$cryptkeyscript" ]; then
if [ ${cryptsource#/dev/disk/by-uuid/} != $cryptsource ]; then
# UUIDs are not very helpful
diskname="$crypttarget"
else
diskname="$cryptsource ($crypttarget)"
fi
cryptkeyscript=$askpass
cryptkey="Please unlock disk $diskname: "
elif ! type "$cryptkeyscript" >/dev/null; then
message "cryptsetup ($crypttarget): error - script \"$cryptkeyscript\" missing"
return 1
fi
if [ "$cryptkeyscript" = "cat" ] && [ "${cryptkey#/root/}" != "$cryptkey" ]; then
# skip the mapping if the root FS is not mounted yet
sed -rn 's/^\s*[^#]\S*\s+(\S+)\s.*/\1/p' /proc/mounts | grep -Fxq "$rootmnt" || return 1
# substitute the "/root" prefix by the real root FS mountpoint otherwise
cryptkey="${rootmnt}/${cryptkey#/root/}"
fi
if [ -n "$cryptheader" ] && ! type "$cryptheader" >/dev/null; then
message "cryptsetup ($crypttarget): error - LUKS header \"$cryptheader\" missing"
return 1
fi
# The same target can be specified multiple times
# e.g. root and resume lvs-on-lvm-on-crypto
if [ -e "/dev/mapper/$crypttarget" ]; then
return 0
fi
modprobe -q dm_crypt
# Make sure the cryptsource device is available
if [ ! -e $cryptsource ]; then
activate_vg
fi
# If the encrypted source device hasn't shown up yet, give it a
# little while to deal with removable devices
# the following lines below have been taken from
# /usr/share/initramfs-tools/scripts/local, as suggested per
# https://launchpad.net/bugs/164044
if [ ! -e "$cryptsource" ]; then
log_begin_msg "Waiting for encrypted source device..."
# Default delay is 180s
if [ -z "${ROOTDELAY}" ]; then
slumber=180
else
slumber=${ROOTDELAY}
fi
slumber=$(( ${slumber} * 10 ))
while [ ! -e "$cryptsource" ]; do
# retry for LVM devices every 10 seconds
if [ ${slumber} -eq $(( ${slumber}/100*100 )) ]; then
activate_vg
fi
/bin/sleep 0.1
slumber=$(( ${slumber} - 1 ))
[ ${slumber} -gt 0 ] || break
done
if [ ${slumber} -gt 0 ]; then
log_end_msg 0
else
log_end_msg 1 || true
fi
fi
udev_settle
# We've given up, but we'll let the user fix matters if they can
if [ ! -e "${cryptsource}" ]; then
echo " ALERT! ${cryptsource} does not exist."
echo " Check cryptopts=source= bootarg: cat /proc/cmdline"
echo " or missing modules, devices: cat /proc/modules; ls /dev"
panic -r "Dropping to a shell. Will skip ${cryptsource} if you can't fix."
fi
if [ ! -e "${cryptsource}" ]; then
return 1
fi
# Prepare commands
cryptopen="/sbin/cryptsetup -T 1"
if [ "$cryptdiscard" = "yes" ]; then
cryptopen="$cryptopen --allow-discards"
fi
if [ -n "$cryptheader" ]; then
cryptopen="$cryptopen --header=$cryptheader"
fi
if [ -n "$cryptkeyslot" ]; then
cryptopen="$cryptopen --key-slot=$cryptkeyslot"
fi
if /sbin/cryptsetup isLuks ${cryptheader:-$cryptsource} >/dev/null 2>&1; then
cryptopen="$cryptopen open --type luks $cryptsource $crypttarget --key-file=-"
elif [ "$crypttcrypt" = "yes" ]; then
cryptopen="$cryptopen open --type tcrypt $cryptveracrypt $cryptsource $crypttarget"
else
cryptopen="$cryptopen -c $cryptcipher -s $cryptsize -h $crypthash open --type plain $cryptsource $crypttarget --key-file=-"
fi
cryptremove="/sbin/cryptsetup remove $crypttarget"
NEWROOT="/dev/mapper/$crypttarget"
# Try to get a satisfactory password $crypttries times
count=0
while [ $crypttries -le 0 ] || [ $count -lt $crypttries ]; do
export CRYPTTAB_TRIED="$count"
count=$(( $count + 1 ))
if [ ! -e "$NEWROOT" ]; then
if ! crypttarget="$crypttarget" cryptsource="$cryptsource" \
$cryptkeyscript "$cryptkey" | $cryptopen; then
message "cryptsetup ($crypttarget): cryptsetup failed, bad password or options?"
# if not askpass, fall back to askpass on fail.
if [ -z "$cryptaskpassfallback" ]; then
continue
elif [ "$cryptkeyscript" = "$askpass" ]; then
continue
else
export do_fallback="$cryptaskpassfallback"
setup_mapping "$1"
return
fi
fi
fi
if [ ! -e "$NEWROOT" ]; then
message "cryptsetup ($crypttarget): unknown error setting up device mapping"
return 1
fi
#FSTYPE=''
#eval $(fstype < "$NEWROOT")
FSTYPE="$(/sbin/blkid -s TYPE -o value "$NEWROOT")"
# See if we need to setup lvm on the crypto device
#if [ "$FSTYPE" = "lvm" ] || [ "$FSTYPE" = "lvm2" ]; then
if [ "$FSTYPE" = "LVM_member" ] || [ "$FSTYPE" = "LVM2_member" ]; then
if [ -z "$cryptlvm" ]; then
message "cryptsetup ($crypttarget): lvm fs found but no lvm configured"
return 1
elif ! activate_vg; then
# disable error message, LP: #151532
#message "cryptsetup ($crypttarget): failed to setup lvm device"
return 1
fi
# Apparently ROOT is already set in /conf/param.conf for
# flashed kernels at least. See bugreport #759720.
if [ -f /conf/param.conf ] && grep -q "^ROOT=" /conf/param.conf; then
NEWROOT=$(sed -n 's/^ROOT=//p' /conf/param.conf)
else
NEWROOT=${cmdline_root:-/dev/mapper/$cryptlvm}
if [ "$cryptrootdev" = "yes" ]; then
# required for lilo to find the root device
echo "ROOT=$NEWROOT" >>/conf/param.conf
fi
fi
#eval $(fstype < "$NEWROOT")
FSTYPE="$(/sbin/blkid -s TYPE -o value "$NEWROOT")"
fi
#if [ -z "$FSTYPE" ] || [ "$FSTYPE" = "unknown" ]; then
if [ -z "$FSTYPE" ]; then
message "cryptsetup ($crypttarget): unknown fstype, bad password or options?"
udev_settle
$cryptremove
continue
fi
# decrease $count by 1, apparently last try was successful.
count=$(( $count - 1 ))
message "cryptsetup ($crypttarget): set up successfully"
break
done
failsleep=60 # make configurable later?
if [ "$cryptrootdev" = "yes" ] && [ $crypttries -gt 0 ] && [ $count -ge $crypttries ]; then
message "cryptsetup ($crypttarget): maximum number of tries exceeded"
message "cryptsetup: going to sleep for $failsleep seconds..."
sleep $failsleep
exit 1
fi
udev_settle
return 0
}
#
# Begin real processing
#
# Do we have any kernel boot arguments?
cmdline_cryptopts=''
unset cmdline_root
for opt in $(cat /proc/cmdline); do
case $opt in
cryptopts=*)
opt="${opt#cryptopts=}"
if [ -n "$opt" ]; then
if [ -n "$cmdline_cryptopts" ]; then
cmdline_cryptopts="$cmdline_cryptopts $opt"
else
cmdline_cryptopts="$opt"
fi
fi
;;
root=*)
opt="${opt#root=}"
case $opt in
/*) # Absolute path given. Not lilo major/minor number.
cmdline_root=$opt
;;
*) # lilo major/minor number (See #398957). Ignore
esac
;;
esac
done
if [ -n "$cmdline_cryptopts" ]; then
# Call setup_mapping separately for each possible cryptopts= setting
for cryptopt in $cmdline_cryptopts; do
setup_mapping "$cryptopt"
done
exit 0
fi
# Do we have any settings from the /conf/conf.d/cryptroot file?
if [ -r /conf/conf.d/cryptroot ]; then
while read mapping <&3; do
setup_mapping "$mapping" 3<&-
done 3< /conf/conf.d/cryptroot
fi
exit 0
Back to linux.debian.user | Previous | Next | Find similar | Unroll thread
[stretch] unlock with keyfile LVM encrypted rootfs -- hung at boot Lfabbro <lfabbro11@protonmail.com> - 2018-10-03 11:10 +0200
csiph-web