diff options
-rw-r--r-- | defaults/initrd.scripts | 52 | ||||
-rw-r--r-- | defaults/linuxrc | 34 | ||||
-rw-r--r-- | defaults/software.sh | 7 | ||||
-rw-r--r-- | doc/genkernel.8.txt | 24 | ||||
-rwxr-xr-x | gen_cmdline.sh | 6 | ||||
-rwxr-xr-x | gen_determineargs.sh | 2 | ||||
-rwxr-xr-x | gen_initramfs.sh | 29 | ||||
-rw-r--r-- | genkernel.conf | 3 | ||||
-rw-r--r-- | gkbuilds/keyutils.gkbuild | 27 |
9 files changed, 181 insertions, 3 deletions
diff --git a/defaults/initrd.scripts b/defaults/initrd.scripts index 4932783..eb556d6 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 15fbf7c..5ee7804 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 ec2bacb..0dce9e1 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 ba8fd0a..a5c0b92 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 e53de69..0cba7d1 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 07b2202..ef69414 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 0b74f4c..227badd 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 7d10496..7045e18 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 0000000..dc232be --- /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!" +} |