commit:     73a05632d61171685ac4960c6b684cefa6d82afd
Author:     Dmitry Baranov <reagentoo <AT> gmail <DOT> com>
AuthorDate: Wed Oct 14 19:03:01 2020 +0000
Commit:     Robin H. Johnson <robbat2 <AT> gentoo <DOT> org>
CommitDate: Sat Aug  7 17:20:10 2021 +0000
URL:        https://gitweb.gentoo.org/proj/genkernel.git/commit/?id=73a05632

Add support for LUKS detached header

Signed-off-by: Dmitry Baranov <reagentoo <AT> gmail.com>

 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.
 

Reply via email to