From 73a05632d61171685ac4960c6b684cefa6d82afd Mon Sep 17 00:00:00 2001 From: Dmitry Baranov Date: Wed, 14 Oct 2020 22:03:01 +0300 Subject: Add support for LUKS detached header Signed-off-by: Dmitry Baranov --- defaults/initrd.scripts | 162 +++++++++++++++++++++++++++++++++++++++++++----- defaults/linuxrc | 18 ++++++ doc/genkernel.8.txt | 22 +++++++ 3 files changed, 186 insertions(+), 16 deletions(-) diff --git a/defaults/initrd.scripts b/defaults/initrd.scripts index 33a48b3..5a83d93 100644 --- a/defaults/initrd.scripts +++ b/defaults/initrd.scripts @@ -306,7 +306,7 @@ bootstrapFS() { fi # Setup the filesystem nodes and directories - for i in ${CDROOT_PATH} /mnt/livecd /mnt/key /mnt/gentoo /tmp /tmp/.initrd /dev /proc /run /sys; do + for i in ${CDROOT_PATH} /mnt/header /mnt/livecd /mnt/key /mnt/gentoo /tmp /tmp/.initrd /dev /proc /run /sys; do run mkdir -p "${NEW_ROOT}${i}" run chmod 755 "${NEW_ROOT}${i}" done @@ -391,6 +391,14 @@ bootstrapCD() { fi } +bootstrapHeader() { + # $1 = ROOT/SWAP + local HEADERDEVS=$(devicelist) + eval local headerloc='"${CRYPT_'${1}'_HEADER}"' + + findmediamount "header" "${headerloc}" "CRYPT_${1}_HEADERDEV" "/mnt/header" ${HEADERDEVS} +} + bootstrapKey() { # $1 = ROOT/SWAP local KEYDEVS=$(devicelist) @@ -1828,12 +1836,17 @@ openLUKS() { local LUKS_NAME="${1}" eval local LUKS_DEVICE='"${CRYPT_'${TYPE}'}"' + eval local LUKS_HEADER='"${CRYPT_'${TYPE}'_HEADER}"' + eval local LUKS_HEADERDEV='"${CRYPT_'${TYPE}'_HEADERDEV}"' + eval local LUKS_HEADERDEV_FSTYPE='"${CRYPT_'${TYPE}'_HEADERDEV_FSTYPE}"' eval local LUKS_KEY='"${CRYPT_'${TYPE}'_KEY}"' eval local LUKS_KEYDEV='"${CRYPT_'${TYPE}'_KEYDEV}"' eval local LUKS_KEYDEV_FSTYPE='"${CRYPT_'${TYPE}'_KEYDEV_FSTYPE}"' eval local OPENED_LOCKFILE='"${CRYPT_'${TYPE}'_OPENED_LOCKFILE}"' - local DEV_ERROR=0 KEY_ERROR=0 KEYDEV_ERROR=0 - local mntkey="/mnt/key/" crypt_filter_ret= + local DEV_ERROR=0 + local HEADER_ERROR=0 HEADERDEV_ERROR=0 + local KEY_ERROR=0 KEYDEV_ERROR=0 + local mntheader="/mnt/header/" mntkey="/mnt/key/" crypt_filter_ret= if [ -z "${LUKS_DEVICE}" ] then @@ -1853,13 +1866,27 @@ openLUKS() { good_msg "The LUKS device ${LUKS_DEVICE} meanwhile was opened by someone else." break # if crypt_silent=1 and some error occurs, enter shell quietly - elif [ \( ${CRYPT_SILENT} -eq 1 \) -a \( \( \( ${DEV_ERROR} -eq 1 \) -o \( ${KEY_ERROR} -eq 1 \) \) -o \( ${KEYDEV_ERROR} -eq 1 \) \) ] + elif [ \( ${CRYPT_SILENT} -eq 1 \) -a \( \( \( ${DEV_ERROR} -eq 1 \) \) ] + then + run_emergency_shell + elif [ \( ${CRYPT_SILENT} -eq 1 \) -a \( \( \( ${HEADER_ERROR} -eq 1 \) \) -o \( ${HEADERDEV_ERROR} -eq 1 \) \) ] + then + run_emergency_shell + elif [ \( ${CRYPT_SILENT} -eq 1 \) -a \( \( \( ${KEY_ERROR} -eq 1 \) \) -o \( ${KEYDEV_ERROR} -eq 1 \) \) ] then run_emergency_shell elif [ ${DEV_ERROR} -eq 1 ] then prompt_user "LUKS_DEVICE" "${LUKS_NAME}" DEV_ERROR=0 + elif [ ${HEADER_ERROR} -eq 1 ] + then + prompt_user "LUKS_HEADER" "${LUKS_NAME} header" + HEADER_ERROR=0 + elif [ ${HEADERDEV_ERROR} -eq 1 ] + then + prompt_user "LUKS_HEADERDEV" "${LUKS_NAME} header device" + HEADERDEV_ERROR=0 elif [ ${KEY_ERROR} -eq 1 ] then prompt_user "LUKS_KEY" "${LUKS_NAME} key" @@ -1877,18 +1904,93 @@ openLUKS() { continue fi - if ! run cryptsetup isLuks ${LUKS_DEVICE} + # Handle headers + if [ -n "${LUKS_HEADER}" ] + then + local REAL_LUKS_HEADERDEV="${LUKS_HEADERDEV}" + if [ ! -e "${mntheader}${LUKS_HEADER}" ] + then + REAL_LUKS_HEADERDEV=$(find_real_device "${LUKS_HEADERDEV}") + if [ -b "${REAL_LUKS_HEADERDEV}" ] + then + good_msg "Using header device ${REAL_LUKS_HEADERDEV}." ${CRYPT_SILENT} + else + good_msg "Please insert removable device ${LUKS_HEADERDEV} for ${LUKS_NAME}" ${CRYPT_SILENT} + # abort after 10 secs + local count=10 + while [ ${count} -gt 0 ] + do + count=$((count-1)) + sleep 1 + REAL_LUKS_HEADERDEV=$(find_real_device "${LUKS_HEADERDEV}") + if [ -b "${REAL_LUKS_HEADERDEV}" ] + then + good_msg "Removable device ${REAL_LUKS_HEADERDEV} detected." ${CRYPT_SILENT} + break + fi + done + if [ ! -b "${REAL_LUKS_HEADERDEV}" ] + then + eval CRYPT_${TYPE}_HEADER=${LUKS_HEADER} + bootstrapHeader ${TYPE} + eval LUKS_HEADERDEV='"${CRYPT_'${TYPE}'_HEADERDEV}"' + REAL_LUKS_HEADERDEV=$(find_real_device "${LUKS_HEADERDEV}") + if [ ! -b "${REAL_LUKS_HEADERDEV}" ] + then + HEADERDEV_ERROR=1 + bad_msg "Removable device ${LUKS_HEADERDEV} not found." ${CRYPT_SILENT} + continue + fi + # continue otherwise will mount headerdev which is mounted by bootstrap + continue + fi + fi + + # At this point a device was recognized, now let's see if the header is there + [ ! -d "${mntheader}" ] && mkdir -p "${mntheader}" >/dev/null 2>&1 + + # determine fs -- 'auto' will not trigger module loading! + LUKS_HEADERDEV_FSTYPE=$(determine_fs "${REAL_LUKS_HEADERDEV}" "${LUKS_HEADERDEV_FSTYPE}") + + if ! run mount -n -t ${LUKS_HEADERDEV_FSTYPE} -o ro ${REAL_LUKS_HEADERDEV} ${mntheader} >/dev/null 2>&1 + then + HEADERDEV_ERROR=1 + bad_msg "Mounting of device ${REAL_LUKS_HEADERDEV} failed." ${CRYPT_SILENT} + continue + fi + + good_msg "Removable device ${REAL_LUKS_HEADERDEV} mounted." ${CRYPT_SILENT} + sleep 2 + + # headerfile exists? + if [ ! -e "${mntheader}${LUKS_HEADER}" ] + then + run umount -n "${mntheader}" >/dev/null 2>&1 + HEADER_ERROR=1 + HEADERDEV_ERROR=1 + bad_msg "Header {LUKS_HEADER} on device ${REAL_LUKS_HEADERDEV} not found." ${CRYPT_SILENT} + continue + fi + fi + + if ! run cryptsetup isLuks ${LUKS_DEVICE} --header ${mntheader}${LUKS_HEADER} + then + bad_msg "The LUKS device ${LUKS_DEVICE} does not contain a LUKS header" ${CRYPT_SILENT} + DEV_ERROR=1 + continue + fi + + # At this point a candidate header exists (either mounted before or not) + good_msg "${LUKS_HEADER} on device ${REAL_LUKS_HEADERDEV} found" ${CRYPT_SILENT} + + cryptsetup_options="${cryptsetup_options} --header ${mntheader}${LUKS_HEADER}" + elif ! run cryptsetup isLuks ${LUKS_DEVICE} then bad_msg "The LUKS device ${LUKS_DEVICE} does not contain a LUKS header" ${CRYPT_SILENT} DEV_ERROR=1 continue fi - if [ -n "${cryptsetup_options}" ] - then - good_msg "Using the following cryptsetup options for ${LUKS_NAME}: ${cryptsetup_options}" ${CRYPT_SILENT} - fi - # Handle keys if [ -n "${LUKS_KEY}" ] then @@ -1946,6 +2048,7 @@ openLUKS() { good_msg "Removable device ${REAL_LUKS_KEYDEV} mounted." ${CRYPT_SILENT} sleep 2 + # keyfile exists? if [ ! -e "${mntkey}${LUKS_KEY}" ] then @@ -1956,6 +2059,7 @@ openLUKS() { continue fi fi + # At this point a candidate key exists (either mounted before or not) good_msg "${LUKS_KEY} on device ${REAL_LUKS_KEYDEV} found" ${CRYPT_SILENT} @@ -1975,7 +2079,13 @@ openLUKS() { cryptsetup_options="${cryptsetup_options} -d ${mntkey}${LUKS_KEY}" fi fi - # At this point, keyfile or not, we're ready! + + if [ -n "${cryptsetup_options}" ] + then + good_msg "Using the following cryptsetup options for ${LUKS_NAME}: ${cryptsetup_options}" ${CRYPT_SILENT} + fi + + # At this point, {header,key}file or not, we're ready! crypt_filter "${gpg_cmd}cryptsetup ${cryptsetup_options} luksOpen ${LUKS_DEVICE} ${LUKS_NAME}" crypt_filter_ret=$? @@ -1992,6 +2102,8 @@ openLUKS() { then bad_msg "Failed to open LUKS device ${LUKS_DEVICE}" ${CRYPT_SILENT} DEV_ERROR=1 + HEADER_ERROR=1 + HEADERDEV_ERROR=1 KEY_ERROR=1 KEYDEV_ERROR=1 fi @@ -2000,11 +2112,17 @@ openLUKS() { udevsettle + if run mountpoint "${mntheader}" >/dev/null 2>&1 + then + run umount "${mntheader}" >/dev/null 2>&1 + fi + if run mountpoint "${mntkey}" >/dev/null 2>&1 then run umount "${mntkey}" >/dev/null 2>&1 fi + [ -d "${mntheader}" ] && run rmdir -p "${mntheader}" >/dev/null 2>&1 [ -d "${mntkey}" ] && run rmdir -p "${mntkey}" >/dev/null 2>&1 } @@ -2341,8 +2459,14 @@ start_LUKS() { # if key is set but neither ssh enabled or key device is given, find # the key device - [ -n "${CRYPT_ROOT_KEY}" ] && [ -z "${CRYPT_ROOT_KEYDEV}" ] \ - && sleep 6 && bootstrapKey "ROOT" + if [ -n "${CRYPT_ROOT_KEY}" ] + then + ( [ -z "${CRYPT_ROOT_KEYDEV}" ] || [ -z "${CRYPT_ROOT_HEADERDEV}" ] ) \ + && sleep 6 + + [ -z "${CRYPT_ROOT_KEYDEV}" ] && bootstrapKey "ROOT" + [ -z "${CRYPT_ROOT_HEADERDEV}" ] && bootstrapHeader "ROOT" + fi if [ -n "${CRYPT_ROOT}" ] then @@ -2356,9 +2480,15 @@ start_LUKS() { fi fi - # same for swap, but no need to sleep if root was unencrypted - [ -n "${CRYPT_SWAP_KEY}" ] && [ -z "${CRYPT_SWAP_KEYDEV}" ] \ - && { [ -z "${CRYPT_ROOT}" ] && sleep 6; bootstrapKey "SWAP"; } + if [ -n "${CRYPT_SWAP_KEY}" ] + then + # same for swap, but no need to sleep if root was unencrypted + ( [ -z "${CRYPT_ROOT_KEYDEV}" ] || [ -z "${CRYPT_ROOT_HEADERDEV}" ] ) \ + && [ -z "${CRYPT_ROOT}" ] && sleep 6 + + [ -z "${CRYPT_SWAP_KEYDEV}" ] && bootstrapKey "SWAP" + [ -z "${CRYPT_SWAP_HEADERDEV}" ] && bootstrapHeader "SWAP" + fi if [ -n "${CRYPT_SWAP}" ] then diff --git a/defaults/linuxrc b/defaults/linuxrc index 6ede740..ff08ba2 100644 --- a/defaults/linuxrc +++ b/defaults/linuxrc @@ -228,6 +228,15 @@ do crypt_swap_options=*) CRYPT_SWAP_OPTIONS=$(echo ${CRYPT_SWAP_OPTIONS} ${x#*=} | sed -e 's/,/ /g') ;; + root_header=*) + CRYPT_ROOT_HEADER=${x#*=} + ;; + root_headerdev=*) + CRYPT_ROOT_HEADERDEV=${x#*=} + ;; + root_headerdev_fstype=*) + CRYPT_ROOT_HEADERDEV_FSTYPE=${x#*=} + ;; root_key=*) CRYPT_ROOT_KEY=${x#*=} ;; @@ -245,6 +254,15 @@ do fi unset tmp_enabled ;; + swap_header=*) + CRYPT_SWAP_HEADER=${x#*=} + ;; + swap_headerdev=*) + CRYPT_SWAP_HEADERDEV=${x#*=} + ;; + swap_headerdev_fstype=*) + CRYPT_SWAP_HEADERDEV_FSTYPE=${x#*=} + ;; swap_key=*) CRYPT_SWAP_KEY=${x#*=} ;; diff --git a/doc/genkernel.8.txt b/doc/genkernel.8.txt index 262027b..33f7733 100644 --- a/doc/genkernel.8.txt +++ b/doc/genkernel.8.txt @@ -688,6 +688,19 @@ recognized by the kernel itself. cryptsetup when opening swap volume. Can be specified multiple times or separate multiple options with a comma. +*root_header*=<...>:: + In case your encrypted root uses a LUKS detached header, you can + use a device like a usb pen to store the header file. This value + should be the key path relative to the mount point. + +*root_headerdev*=<...>:: + If necessary provide the name of the device that carries the + root_header. If unset while using root_header, it will automatically + look for the device in every boot. + +*root_headerdev_fstype*=<...>:: + Used filesystem for *root_headerdev*. See *rootfstype* for more details. + *root_key*=<...>:: In case your root is encrypted with a key, you can use a device like a usb pen to store the key. This value should be the key @@ -706,6 +719,15 @@ recognized by the kernel itself. with SSD setups. Have a look at 'https://en.wikipedia.org/wiki/TRIM' for more information. +*swap_header*=<...>:: + Same as root_header for swap. + +*swap_headerdev*=<...>:: + Same as root_headerdev for swap. + +*swap_headerdev_fstype*=<...>:: + Used filesystem for *swap_headerdev*. See *rootfstype* for more details. + *swap_key*=<...>:: Same as root_key for swap. -- cgit v1.2.3-65-gdbad