From fd15ed865fbb94bd46b434f4734d9e8dfaeacb30 Mon Sep 17 00:00:00 2001 From: Ole Tange Date: Sun, 3 May 2020 01:50:28 +0200 Subject: [PATCH] decrypt-root-with-usb: Updated to Ubuntu-20.04 LTS. --- .../{ => debian-2018}/cryptroot.patch | 0 .../scripts/local-top/cryptroot | 0 .../ubuntu-20.04/cryptroot.patch | 58 ++++ .../scripts/local-top/cryptroot | 261 ++++++++++++++++++ 4 files changed, 319 insertions(+) rename decrypt-root-with-usb/{ => debian-2018}/cryptroot.patch (100%) rename decrypt-root-with-usb/{ => debian-2018}/usr/share/initramfs-tools/scripts/local-top/cryptroot (100%) create mode 100644 decrypt-root-with-usb/ubuntu-20.04/cryptroot.patch create mode 100644 decrypt-root-with-usb/ubuntu-20.04/usr/share/initramfs-tools/scripts/local-top/cryptroot diff --git a/decrypt-root-with-usb/cryptroot.patch b/decrypt-root-with-usb/debian-2018/cryptroot.patch similarity index 100% rename from decrypt-root-with-usb/cryptroot.patch rename to decrypt-root-with-usb/debian-2018/cryptroot.patch diff --git a/decrypt-root-with-usb/usr/share/initramfs-tools/scripts/local-top/cryptroot b/decrypt-root-with-usb/debian-2018/usr/share/initramfs-tools/scripts/local-top/cryptroot similarity index 100% rename from decrypt-root-with-usb/usr/share/initramfs-tools/scripts/local-top/cryptroot rename to decrypt-root-with-usb/debian-2018/usr/share/initramfs-tools/scripts/local-top/cryptroot diff --git a/decrypt-root-with-usb/ubuntu-20.04/cryptroot.patch b/decrypt-root-with-usb/ubuntu-20.04/cryptroot.patch new file mode 100644 index 0000000..ba76ce1 --- /dev/null +++ b/decrypt-root-with-usb/ubuntu-20.04/cryptroot.patch @@ -0,0 +1,58 @@ +--- /usr/share/initramfs-tools/scripts/local-top/cryptroot.orig 2020-05-03 01:25:43.388812582 +0200 ++++ /usr/share/initramfs-tools/scripts/local-top/cryptroot 2020-05-03 01:25:43.392812547 +0200 +@@ -123,6 +123,23 @@ + fi + fi + ++ if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ]; then ++ # Wait for USB to settle ++ /bin/sleep 3 ++ ++ # Test all devices ++ mkdir /mnt ++ echo -n "Searching for cryptkey.txt on available disks... " ++ local partition ++ for partition in `cat /proc/partitions |awk '{print $4}'|tail -n +3`; do ++ if mount /dev/$partition /mnt 2>/dev/null; then ++ cat /mnt/cryptkey.txt >> /tmp/cryptkeys.txt 2>/dev/null ++ umount /dev/$partition ++ fi ++ done ++ echo "done." ++ fi ++ + get_crypt_type # set CRYPTTAB_TYPE to the type of crypt device + local count=0 maxtries="${CRYPTTAB_OPTION_tries:-3}" fstype vg rv + while [ $maxtries -le 0 ] || [ $count -lt $maxtries ]; do +@@ -130,8 +147,29 @@ + # unlock via keyfile + unlock_mapping "$CRYPTTAB_KEY" + else +- # unlock interactively or via keyscript +- run_keyscript "$CRYPTTAB_KEY" "$count" | unlock_mapping ++ if [ -s /tmp/cryptkeys.txt ]; then ++ local keyfound ++ keyfound=0 ++ echo Trying keys from cryptkey.txt ++ for key in `cat /tmp/cryptkeys.txt`; do ++ if echo -n "$key" | unlock_mapping; then ++ # Found the key ++ echo Key found in cryptkey.txt ++ keyfound=1 ++ key="" ++ fi ++ done ++ # Remove traces of the key ++ rm /tmp/cryptkeys.txt ++ unset key ++ if [ "$keyfound" = "0" ]; then ++ # Fall back to manual entry ++ run_keyscript "$CRYPTTAB_KEY" "$count" | unlock_mapping ++ fi ++ else ++ # unlock interactively or via keyscript ++ run_keyscript "$CRYPTTAB_KEY" "$count" | unlock_mapping ++ fi + fi + rv=$? + count=$(( $count + 1 )) diff --git a/decrypt-root-with-usb/ubuntu-20.04/usr/share/initramfs-tools/scripts/local-top/cryptroot b/decrypt-root-with-usb/ubuntu-20.04/usr/share/initramfs-tools/scripts/local-top/cryptroot new file mode 100644 index 0000000..5d7151f --- /dev/null +++ b/decrypt-root-with-usb/ubuntu-20.04/usr/share/initramfs-tools/scripts/local-top/cryptroot @@ -0,0 +1,261 @@ +#!/bin/sh + +PREREQ="cryptroot-prepare" + +# +# Standard initramfs preamble +# +prereqs() +{ + # Make sure that cryptroot is run last in local-top + local req + for req in "${0%/*}"/*; do + script="${req##*/}" + if [ "$script" != "${0##*/}" ]; then + printf '%s\n' "$script" + fi + done +} + +case $1 in +prereqs) + prereqs + exit 0 + ;; +esac + +. /scripts/functions + +[ -f /lib/cryptsetup/functions ] || return 0 +. /lib/cryptsetup/functions + + +# wait_for_source() +# Wait for encrypted $CRYPTTAB_SOURCE for up to 180s. Set +# $CRYPTTAB_SOURCE to its normalized device name when it shows up; +# return 1 if timeout. +wait_for_source() { + wait_for_udev 10 + + if crypttab_resolve_source; then + # the device is here already, no need to loop + return 0 + fi + + # The lines below has been taken from + # /usr/share/initramfs-tools/scripts/local's local_device_setup(), + # as suggested per https://launchpad.net/bugs/164044 + + # If the source device hasn't shown up yet, give it a little while + # to allow for asynchronous device discovery (e.g. USB). + + cryptsetup_message "Waiting for encrypted source device $CRYPTTAB_SOURCE..." + + # Default delay is 180s, cf. initramfs-tools(8) + local slumber="${ROOTDELAY:-180}" + while [ $slumber -gt 0 ]; do + sleep 1 + + if [ -x /scripts/local-block/lvm2 ]; then + # activate any VG that might hold $CRYPTTAB_SOURCE + /scripts/local-block/lvm2 "$CRYPTTAB_SOURCE" + fi + + if crypttab_resolve_source; then + wait_for_udev 10 + return 0 + fi + + slumber=$(( $slumber - 1 )) + done + return 1 +} + +# setup_mapping() +# Set up a crypttab(5) mapping defined by $CRYPTTAB_NAME, +# $CRYPTTAB_SOURCE, $CRYPTTAB_KEY, $CRYPTTAB_OPTIONS. +setup_mapping() { + local dev + + # The same target can be specified multiple times + # e.g. root and resume lvs-on-lvm-on-crypto + if dm_blkdevname "$CRYPTTAB_NAME" >/dev/null; then + return 0 + fi + + crypttab_parse_options --export --missing-path=fail || return 1 + + if ! wait_for_source; then + # we've given up + if [ -n "$panic" ]; then + panic "ALERT! encrypted source device $CRYPTTAB_SOURCE does not exist, can't unlock $CRYPTTAB_NAME." + else + # let the user fix matters if they can + echo " ALERT! encrypted source device $CRYPTTAB_SOURCE does not exist, can't unlock $CRYPTTAB_NAME." + echo " Check cryptopts=source= bootarg: cat /proc/cmdline" + echo " or missing modules, devices: cat /proc/modules; ls /dev" + panic "Dropping to a shell." + fi + return 1 # can't continue because environment is lost + fi + + # our `cryptroot-unlock` script searches for cryptsetup processes + # with a given CRYPTTAB_NAME it their environment + export CRYPTTAB_NAME + + if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ]; then + # no keyscript: interactive unlocking, or key file + + if [ "${CRYPTTAB_KEY#/FIXME-initramfs-rootmnt/}" != "$CRYPTTAB_KEY" ]; then + # skip the mapping for now if the root FS is not mounted yet + sed -rn 's/^\s*[^#[:blank:]]\S*\s+(\S+)\s.*/\1/p' /proc/mounts | grep -Fxq -- "$rootmnt" || return 1 + # substitute the "/FIXME-initramfs-rootmnt/" prefix by the real root FS mountpoint otherwise + CRYPTTAB_KEY="$rootmnt/${CRYPTTAB_KEY#/FIXME-initramfs-rootmnt/}" + fi + + if [ "$CRYPTTAB_KEY" != "none" ]; then + if [ ! -e "$CRYPTTAB_KEY" ]; then + cryptsetup_message "ERROR: Skipping target $CRYPTTAB_NAME: non-existing key file $CRYPTTAB_KEY" + return 1 + fi + # try only once if we have a key file + CRYPTTAB_OPTION_tries=1 + fi + fi + + if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ]; then + # Wait for USB to settle + /bin/sleep 3 + + # Test all devices + mkdir /mnt + echo -n "Searching for cryptkey.txt on available disks... " + local partition + for partition in `cat /proc/partitions |awk '{print $4}'|tail -n +3`; do + if mount /dev/$partition /mnt 2>/dev/null; then + cat /mnt/cryptkey.txt >> /tmp/cryptkeys.txt 2>/dev/null + umount /dev/$partition + fi + done + echo "done." + fi + + get_crypt_type # set CRYPTTAB_TYPE to the type of crypt device + local count=0 maxtries="${CRYPTTAB_OPTION_tries:-3}" fstype vg rv + while [ $maxtries -le 0 ] || [ $count -lt $maxtries ]; do + if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ] && [ "$CRYPTTAB_KEY" != "none" ]; then + # unlock via keyfile + unlock_mapping "$CRYPTTAB_KEY" + else + if [ -s /tmp/cryptkeys.txt ]; then + local keyfound + keyfound=0 + echo Trying keys from cryptkey.txt + for key in `cat /tmp/cryptkeys.txt`; do + if echo -n "$key" | unlock_mapping; then + # Found the key + echo Key found in cryptkey.txt + keyfound=1 + key="" + fi + done + # Remove traces of the key + rm /tmp/cryptkeys.txt + unset key + if [ "$keyfound" = "0" ]; then + # Fall back to manual entry + run_keyscript "$CRYPTTAB_KEY" "$count" | unlock_mapping + fi + else + # unlock interactively or via keyscript + run_keyscript "$CRYPTTAB_KEY" "$count" | unlock_mapping + fi + fi + rv=$? + count=$(( $count + 1 )) + + if [ $rv -ne 0 ]; then + cryptsetup_message "ERROR: $CRYPTTAB_NAME: cryptsetup failed, bad password or options?" + sleep 1 + continue + elif ! dev="$(dm_blkdevname "$CRYPTTAB_NAME")"; then + cryptsetup_message "ERROR: $CRYPTTAB_NAME: unknown error setting up device mapping" + return 1 + fi + + if ! fstype="$(get_fstype "$dev")" || [ "$fstype" = "unknown" ]; then + if [ "$CRYPTTAB_TYPE" != "luks" ]; then + # bad password for plain dm-crypt device? or mkfs not run yet? + cryptsetup_message "ERROR: $CRYPTTAB_NAME: unknown fstype, bad password or options?" + wait_for_udev 10 + /sbin/cryptsetup remove -- "$CRYPTTAB_NAME" + sleep 1 + continue + fi + elif [ "$fstype" = lvm2 ]; then + if [ ! -x /sbin/lvm ]; then + cryptsetup_message "WARNING: $CRYPTTAB_NAME: lvm is not available" + return 1 + elif vg="$(lvm pvs --noheadings -o vg_name --config 'log{prefix=""}' -- "$dev")"; then + # activate the VG held by the PV we just unlocked + lvm lvchange -a y --sysinit --ignoreskippedcluster -- "$vg" + fi + fi + + cryptsetup_message "$CRYPTTAB_NAME: set up successfully" + wait_for_udev 10 + return 0 + done + + cryptsetup_message "ERROR: $CRYPTTAB_NAME: maximum number of tries exceeded" + exit 1 +} + + +####################################################################### +# Begin real processing + +mkdir -p /cryptroot # might not exist yet if the main system has no crypttab(5) + +# Do we have any kernel boot arguments? +if ! grep -qE '^(.*\s)?cryptopts=' /proc/cmdline; then + # ensure $TABFILE exists and has a mtime greater than the boot time + # (existing $TABFILE is preserved) + touch -- "$TABFILE" +else + # let the read builtin unescape the '\' as GRUB substitutes '\' by '\\' in the cmdline + tr ' ' '\n' "$TABFILE" +fi + +# Do we have any settings from the $TABFILE? +if [ -s "$TABFILE" ]; then + # Create locking directory before invoking cryptsetup(8) to avoid warnings + mkdir -pm0700 /run/cryptsetup + modprobe -q dm_crypt + + crypttab_foreach_entry setup_mapping +fi + +exit 0