aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin H. Johnson <robbat2@gentoo.org>2022-05-24 13:34:54 -0700
committerRobin H. Johnson <robbat2@gentoo.org>2022-05-24 13:34:54 -0700
commitedefa80c999972b0dffdc5c9cf9d880156e6e0db (patch)
tree895cb2bb1364702ce171dce6e032d8d8f2cffdd5
parentarch: Copy s390 config to s390x (it's 64bit anyway!) (diff)
parentgenkernel: add keyctl support for loading LUKS passphrase into a keyring (diff)
downloadgenkernel-edefa80c999972b0dffdc5c9cf9d880156e6e0db.tar.gz
genkernel-edefa80c999972b0dffdc5c9cf9d880156e6e0db.tar.bz2
genkernel-edefa80c999972b0dffdc5c9cf9d880156e6e0db.zip
add keyctl support for loading LUKS passphrase into a keyring
Merges: https://github.com/gentoo/genkernel/pull/10 Closes: https://github.com/gentoo/genkernel/pull/10 Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
-rw-r--r--defaults/initrd.scripts52
-rw-r--r--defaults/linuxrc34
-rw-r--r--defaults/software.sh7
-rw-r--r--doc/genkernel.8.txt24
-rwxr-xr-xgen_cmdline.sh6
-rwxr-xr-xgen_determineargs.sh2
-rwxr-xr-xgen_initramfs.sh29
-rw-r--r--genkernel.conf3
-rw-r--r--gkbuilds/keyutils.gkbuild27
9 files changed, 181 insertions, 3 deletions
diff --git a/defaults/initrd.scripts b/defaults/initrd.scripts
index 49327839..eb556d6e 100644
--- a/defaults/initrd.scripts
+++ b/defaults/initrd.scripts
@@ -2108,6 +2108,54 @@ openLUKS() {
[ -d "${mntkey}" ] && run rmdir -p "${mntkey}" >/dev/null 2>&1
}
+keyctl_keyadd() {
+ if [ -n "${KEYCTL_KEYDESC}" ]
+ then
+ if [ ! -x /bin/keyctl ]
+ then
+ bad_msg "keyctl program is missing. Was initramfs built without --keyctl parameter?"
+ exit 1
+ fi
+
+ # not using read to avoid secrets being left in memory
+ stty -echo
+ echo -n "Please type the key '${KEYCTL_KEYDESC}' for the user keyring then press Ctrl-D twice: "
+ KEYCTL_KEYID=`keyctl padd user "${KEYCTL_KEYDESC}" @u`
+ echo
+ stty echo
+
+ if [ -n "${KEYCTL_KEYID}" -a -n "${KEYCTL_KEYTIMEOUT}" ]
+ then
+ keyctl timeout "${KEYCTL_KEYID}" "${KEYCTL_KEYTIMEOUT}"
+ fi
+ fi
+}
+
+keyctl_keyremove() {
+ if [ -n "${KEYCTL_KEYID}" -a -z "${KEYCTL_KEYKEEP}" ]
+ then
+ if [ ! -x /bin/keyctl ]
+ then
+ bad_msg "keyctl program is missing. Was initramfs built without --keyctl parameter?"
+ exit 1
+ fi
+
+ keyctl revoke "${KEYCTL_KEYID}"
+ keyctl unlink "${KEYCTL_KEYID}" >/dev/null
+
+ # trust but verify
+ if keyctl show "${KEYCTL_KEYID}" >/dev/null 2>&1
+ then
+ # better reboot than leave the user passphrase accidentally exposed
+ bad_msg "unable to remove the newly added key from keyring, rebooting in 5 seconds for security"
+ sleep 5
+ reboot -f
+ fi
+
+ KEYCTL_KEYID=
+ fi
+}
+
iface_name() {
local ifname="${1}"
@@ -2437,7 +2485,7 @@ ipv6_tentative() {
fi
}
-start_LUKS() {
+start_LUKS_root() {
# if key is set but neither ssh enabled or key device is given, find
# the key device
@@ -2461,7 +2509,9 @@ start_LUKS() {
REAL_ROOT="/dev/mapper/root"
fi
fi
+}
+start_LUKS_swap() {
if [ -n "${CRYPT_SWAP_KEY}" ]
then
# same for swap, but no need to sleep if root was unencrypted
diff --git a/defaults/linuxrc b/defaults/linuxrc
index 15fbf7cc..5ee78044 100644
--- a/defaults/linuxrc
+++ b/defaults/linuxrc
@@ -272,6 +272,15 @@ do
swap_keydev_fstype=*)
CRYPT_SWAP_KEYDEV_FSTYPE=${x#*=}
;;
+ keyctl_keydesc=*)
+ KEYCTL_KEYDESC=${x#*=}
+ ;;
+ keyctl_keytimeout=*)
+ KEYCTL_KEYTIMEOUT=${x#*=}
+ ;;
+ keyctl_keykeep)
+ KEYCTL_KEYKEEP=1
+ ;;
real_resume=*|resume=*)
REAL_RESUME=${x#*=}
;;
@@ -656,10 +665,23 @@ then
start_sshd
fi
+keyctl_keyadd
+
# Initialize LUKS root device except for livecd's
if [ "${CDROOT}" != '1' ]
then
- start_LUKS
+ if ( [ -n "${CRYPT_SWAP_KEY}" ] && [ -z "${CRYPT_SWAP_KEYDEV}" ] ) || \
+ ( [ -n "${CRYPT_SWAP_HEADER}" ] && [ -z "${CRYPT_SWAP_HEADERDEV}" ] )
+ then
+ # the swap key or header might be on the root fs so start it first in this case
+ start_LUKS_root
+ luks_root_started=1
+ start_LUKS_swap
+ else
+ # we don't need to start the root at all if we are resuming from suspend
+ start_LUKS_swap
+ fi
+
if [ "${NORESUME}" != '1' ] && [ -n "${REAL_RESUME}" ]
then
case "${REAL_RESUME}" in
@@ -691,6 +713,11 @@ then
do_resume
fi
+
+ if [ -z "${luks_root_started}" ]
+ then
+ start_LUKS_root
+ fi
fi
run mkdir -p "${NEW_ROOT}"
@@ -1060,7 +1087,8 @@ then
losetup /dev/loop0 "${CDROOT_PATH}/${LOOPEXT}${LOOP}"
test_success 'Preparing loop filesystem'
- start_LUKS
+ start_LUKS_root
+ start_LUKS_swap
case ${LOOPTYPE} in
normal)
@@ -1302,6 +1330,8 @@ else
fi
fi # if [ "${CDROOT}" = '1' ]
+keyctl_keyremove
+
# Re-run to ensure $NEWROOT/etc/initramfs.mounts was processed at least once
process_initramfs_mounts
diff --git a/defaults/software.sh b/defaults/software.sh
index ec2bacb6..0dce9e15 100644
--- a/defaults/software.sh
+++ b/defaults/software.sh
@@ -128,6 +128,13 @@ GKPKG_JSON_C_SRCTAR="${GKPKG_JSON_C_SRCTAR:-${DISTDIR}/json-c-${GKPKG_JSON_C_PV}
GKPKG_JSON_C_SRCDIR="${GKPKG_JSON_C_SRCDIR:-json-c-${GKPKG_JSON_C_PV}}"
GKPKG_JSON_C_BINPKG="${GKPKG_JSON_C_BINPKG:-%%CACHE%%/json-c-${GKPKG_JSON_C_PV}-%%ARCH%%.tar.xz}"
+GKPKG_KEYUTILS_PN="keyutils"
+GKPKG_KEYUTILS_PV="${GKPKG_KEYUTILS_PV:-1.6.3}"
+GKPKG_KEYUTILS_DEPS=""
+GKPKG_KEYUTILS_SRCTAR="${GKPKG_KEYUTILS_SRCTAR:-${DISTDIR}/keyutils-${GKPKG_KEYUTILS_PV}.tar.gz}"
+GKPKG_KEYUTILS_SRCDIR="${GKPKG_KEYUTILS_SRCDIR:-keyutils-${GKPKG_KEYUTILS_PV}}"
+GKPKG_KEYUTILS_BINPKG="${GKPKG_KEYUTILS_BINPKG:-%%CACHE%%/keyutils-${GKPKG_KEYUTILS_PV}-%%ARCH%%.tar.xz}"
+
GKPKG_KMOD_PN="kmod"
GKPKG_KMOD_PV="${GKPKG_KMOD_PV:-VERSION_KMOD}"
GKPKG_KMOD_DEPS="zlib xz zstd"
diff --git a/doc/genkernel.8.txt b/doc/genkernel.8.txt
index ba8fd0a9..a5c0b922 100644
--- a/doc/genkernel.8.txt
+++ b/doc/genkernel.8.txt
@@ -468,6 +468,12 @@ system is able to load multiple initramfs.
`gpg --symmetric -o /path/to/LUKS-key.gpg /path/to/LUKS-key` .
After that, re-point the *root_key* argument to the new .gpg file.
+*--*[*no-*]*keyctl*::
+ Includes or excludes support for keyutils keyctl.
+ This way a LUKS passphrase can be loaded into a keyring at boot time
+ to unlock multiple devices (root, swap, etc.) without retyping it for each
+ one.
+
*--*[*no-*]*b2sum*::
Includes or excludes b2sum in the initramfs.
When enabled, this will compile coreutils' b2sum for you.
@@ -737,6 +743,24 @@ recognized by the kernel itself.
*swap_keydev_fstype*=<...>::
Used filesystem for *swap_keydev*. See *rootfstype* for more details.
+*keyctl_keydesc*=<...>::
+ Load a passphrase into a keyring at boot time under the key name provided
+ as an argument to this option.
+ This way multiple devices (root, swap, etc.) can be unlocked without
+ retyping the passphrase for each one.
+ You'll need to add this key name as a keyring token to every LUKS device
+ that it is supposed to unlock - have a look at cryptsetup 'token add'
+ operation.
+
+*keyctl_keykeep*::
+ Don't remove the newly added key before starting the real init.
+ Useful if you want to utilize it to unlock LUKS devices post-initramfs.
+
+*keyctl_keytimeout*=<...>::
+ Enable a timeout (in seconds) for the newly added key.
+ This option normally only makes sense when used together with the
+ *keyctl_keykeep* option.
+
*crypt_silent*::
Set this to silent all the output related to the cryptographic
software, and in case your encrypted device isn't open with the
diff --git a/gen_cmdline.sh b/gen_cmdline.sh
index e53de690..0cba7d15 100755
--- a/gen_cmdline.sh
+++ b/gen_cmdline.sh
@@ -181,6 +181,8 @@ longusage() {
echo " --no-luks Exclude LUKS support"
echo " --gpg Include GPG-armored LUKS key support"
echo " --no-gpg Exclude GPG-armored LUKS key support"
+ echo " --keyctl Include keyctl support for loading LUKS passphrase into a keyring"
+ echo " --no-keyctl Exclude keyctl support for loading LUKS passphrase into a keyring"
echo " --b2sum Include b2sum"
echo " --no-b2sum Exclude b2sum"
echo " --busybox Include busybox"
@@ -837,6 +839,10 @@ parse_cmdline() {
CMD_GPG=$(parse_optbool "$*")
print_info 3 "CMD_GPG: ${CMD_GPG}"
;;
+ --keyctl|--no-keyctl)
+ CMD_KEYCTL=$(parse_optbool "$*")
+ print_info 3 "CMD_KEYCTL: ${CMD_KEYCTL}"
+ ;;
--firmware|--no-firmware)
CMD_FIRMWARE=$(parse_optbool "$*")
print_info 3 "CMD_FIRMWARE: ${CMD_FIRMWARE}"
diff --git a/gen_determineargs.sh b/gen_determineargs.sh
index 07b22029..ef69414e 100755
--- a/gen_determineargs.sh
+++ b/gen_determineargs.sh
@@ -433,6 +433,7 @@ determine_real_args() {
set_config_with_override STRING REAL_ROOT CMD_REAL_ROOT
set_config_with_override BOOL LUKS CMD_LUKS "no"
set_config_with_override BOOL GPG CMD_GPG "no"
+ set_config_with_override BOOL KEYCTL CMD_KEYCTL "no"
set_config_with_override BOOL MDADM CMD_MDADM "no"
set_config_with_override STRING MDADM_CONFIG CMD_MDADM_CONFIG
set_config_with_override BOOL E2FSPROGS CMD_E2FSPROGS "no"
@@ -1099,6 +1100,7 @@ determine_real_args() {
FEATURES_REQUIRING_BUSYBOX+=( KEYMAP )
FEATURES_REQUIRING_BUSYBOX+=( LVM )
FEATURES_REQUIRING_BUSYBOX+=( LUKS )
+ FEATURES_REQUIRING_BUSYBOX+=( KEYCTL )
FEATURES_REQUIRING_BUSYBOX+=( MDADM )
FEATURES_REQUIRING_BUSYBOX+=( MULTIPATH )
FEATURES_REQUIRING_BUSYBOX+=( SPLASH )
diff --git a/gen_initramfs.sh b/gen_initramfs.sh
index 0b74f4c0..227badd5 100755
--- a/gen_initramfs.sh
+++ b/gen_initramfs.sh
@@ -484,6 +484,7 @@ append_base_layout() {
isTrue "${ZFS}" && build_parameters+=( --zfs ) || build_parameters+=( --no-zfs )
isTrue "${SPLASH}" && build_parameters+=( --splash ) || build_parameters+=( --no-splash )
isTrue "${STRACE}" && build_parameters+=( --strace ) || build_parameters+=( --no-strace )
+ isTrue "${KEYCTL}" && build_parameters+=( --keyctl ) || build_parameters+=( --no-keyctl )
isTrue "${GPG}" && build_parameters+=( --gpg ) || build_parameters+=( --no-gpg )
isTrue "${LUKS}" && build_parameters+=( --luks ) || build_parameters+=( --no-luks )
isTrue "${FIRMWARE}" && build_parameters+=( --firmware ) || build_parameters+=( --no-firmware )
@@ -901,6 +902,33 @@ append_iscsi() {
fi
}
+append_keyutils() {
+ local PN=keyutils
+ local TDIR="${TEMP}/initramfs-${PN}-temp"
+ if [ -d "${TDIR}" ]
+ then
+ rm -r "${TDIR}" || gen_die "Failed to clean out existing '${TDIR}'!"
+ fi
+
+ populate_binpkg ${PN}
+
+ mkdir "${TDIR}" || gen_die "Failed to create '${TDIR}'!"
+
+ unpack "$(get_gkpkg_binpkg "${PN}")" "${TDIR}"
+
+ cd "${TDIR}" || gen_die "Failed to chdir to '${TDIR}'!"
+
+ log_future_cpio_content
+ find . -print0 | "${CPIO_COMMAND}" ${CPIO_ARGS} --append -F "${CPIO_ARCHIVE}" \
+ || gen_die "Failed to append ${PN} to cpio!"
+
+ cd "${TEMP}" || die "Failed to chdir to '${TEMP}'!"
+ if isTrue "${CLEANUP}"
+ then
+ rm -rf "${TDIR}"
+ fi
+}
+
append_lvm() {
local PN=lvm
local TDIR="${TEMP}/initramfs-${PN}-temp"
@@ -2050,6 +2078,7 @@ create_initramfs() {
append_data 'e2fsprogs' "${E2FSPROGS}"
append_data 'gpg' "${GPG}"
append_data 'iscsi' "${ISCSI}"
+ append_data 'keyutils' "${KEYCTL}"
append_data 'luks' "${LUKS}"
append_data 'lvm' "${LVM}"
append_data 'bcache' "${BCACHE}"
diff --git a/genkernel.conf b/genkernel.conf
index 7d104962..7045e187 100644
--- a/genkernel.conf
+++ b/genkernel.conf
@@ -80,6 +80,9 @@ NOCOLOR="false"
# Add GnuPG support
#GPG="no"
+# Add keyctl support for loading LUKS passphrase into a keyring
+#KEYCTL="no"
+
# Add in early microcode support: this sets the kernel options for early microcode loading
# Possible values: empty/"no", "all", "intel", "amd"
#MICROCODE="all"
diff --git a/gkbuilds/keyutils.gkbuild b/gkbuilds/keyutils.gkbuild
new file mode 100644
index 00000000..dc232be1
--- /dev/null
+++ b/gkbuilds/keyutils.gkbuild
@@ -0,0 +1,27 @@
+# Copyright 1999-2019 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+src_prepare() {
+ default
+
+ sed -i \
+ -e "1iRPATH = -static" \
+ -e 's:-Werror::' \
+ -e '/^NO_SOLIB/d' \
+ Makefile || die
+}
+
+src_compile() {
+ export NO_SOLIB=1
+
+ gkmake keyctl
+}
+
+src_install() {
+ mkdir "${D}"/bin || die "Failed to create '${D}/bin'!"
+ cp -a keyctl "${D}"/bin/ \
+ || die "Failed to copy '${S}/keyctl'!"
+
+ "${STRIP}" --strip-all "${D}"/bin/keyctl \
+ || die "Failed to strip keyctl!"
+}