From e83e669732db8312604387ae9a10b935659612ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Old=C5=99ich=20Jedli=C4=8Dka?= Date: Sun, 23 Jun 2024 11:45:46 +0200 Subject: [PATCH] Added TPM 1.2 support for Dracut MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Oldřich Jedlička --- src/luks/dracut/clevis-pin-tpm1/meson.build | 14 +++ .../dracut/clevis-pin-tpm1/module-setup.sh.in | 106 ++++++++++++++++++ .../dracut/clevis/clevis-cleanup-hook.sh.in | 5 + .../dracut/clevis/clevis-password-unlocker.in | 25 +++++ src/luks/dracut/meson.build | 1 + 5 files changed, 151 insertions(+) create mode 100644 src/luks/dracut/clevis-pin-tpm1/meson.build create mode 100755 src/luks/dracut/clevis-pin-tpm1/module-setup.sh.in diff --git a/src/luks/dracut/clevis-pin-tpm1/meson.build b/src/luks/dracut/clevis-pin-tpm1/meson.build new file mode 100644 index 00000000..7751eeeb --- /dev/null +++ b/src/luks/dracut/clevis-pin-tpm1/meson.build @@ -0,0 +1,14 @@ +dracut = dependency('dracut', required: false) + +if dracut.found() + dracutdir = dracut.get_pkgconfig_variable('dracutmodulesdir') + '/60' + meson.project_name() + '-pin-tpm1' + + configure_file( + input: 'module-setup.sh.in', + output: 'module-setup.sh', + install_dir: dracutdir, + configuration: data, + ) +else + warning('Will not install dracut module clevis-pin-tpm2 due to missing dependencies!') +endif diff --git a/src/luks/dracut/clevis-pin-tpm1/module-setup.sh.in b/src/luks/dracut/clevis-pin-tpm1/module-setup.sh.in new file mode 100755 index 00000000..a47a94e5 --- /dev/null +++ b/src/luks/dracut/clevis-pin-tpm1/module-setup.sh.in @@ -0,0 +1,106 @@ +#!/bin/bash +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2024 Oldřich Jedlička +# +# Author: Oldřich Jedlička +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +check() { + require_binaries clevis-decrypt-tpm1 tpm_version tpm_unsealdata tcsd stdbuf || return 1 + if [[ $hostonly ]]; then + [ -d /var/lib/tpm ] || return 1 + else + [ -f /usr/share/trousers/system.data.auth ] || \ + [ -f /var/lib/tpm/system.data.auth ] || \ + return 1 + fi + if dracut_module_included "systemd"; then + # shellcheck disable=SC2154 # $systemdsystemunitdir is a dracut variable + [ -f "$systemdsystemunitdir"/tcsd.service ] || \ + [ -f "$systemdsystemunitdir"/tcsd.service.d/clevis-tcsd.conf ] || \ + return 1 + fi + return 0 +} + +depends() { + echo clevis network + return 0 +} + +install() { + if dracut_module_included "systemd"; then + inst_multiple \ + "$systemdsystemunitdir/tcsd.service" \ + "$systemdsystemunitdir/tcsd.service.d/clevis-tcsd.conf" + # shellcheck disable=SC2154 # $initdir is a dracut variable + systemctl -q --root "$initdir" add-wants cryptsetup.target tcsd.service + else + inst_multiple \ + awk chmod chown mkfifo mktemp ip ps stdbuf \ + @libexecdir@/clevis-luks-tpm1-functions + if [ -f /usr/libexec/coreutils/libstdbuf.so ]; then + inst_multiple /usr/libexec/coreutils/libstdbuf.so* + else + inst_libdir_file 'coreutils/libstdbuf.so*' + fi + fi + + inst_multiple \ + clevis-decrypt-tpm1 \ + tcsd \ + tpm_version \ + tpm_unsealdata + + inst_rules 60-tpm-udev.rules + + if ! [[ $hostonly ]] || ! dracut_module_included "systemd"; then + # /etc/hosts is installed only in host-only mode with systemd, so + # we need to create our own in order to get tpm tools working. + # The localhost entry is required by tpm tools. + if [ ! -f "$initdir/etc/hosts" ]; then + echo "127.0.0.1 localhost" >> "$initdir/etc/hosts" + echo "::1 localhost ip6-localhost ip6-loopback" >> "$initdir/etc/hosts" + echo "ff02::1 ip6-allnodes" >> "$initdir/etc/hosts" + echo "ff02::2 ip6-allrouters" >> "$initdir/etc/hosts" + fi + fi + + if [[ $hostonly ]]; then + inst /etc/tcsd.conf + inst_multiple /var/lib/tpm/* + else + inst_dir /etc + touch "$initdir/etc/tcsd.conf" + chmod 0640 "$initdir/etc/tcsd.conf" + chown root:tss "$initdir/etc/tcsd.conf" + + inst_dir /var/lib/tpm + if [ -f /usr/share/trousers/system.data.auth ]; then + inst /usr/share/trousers/system.data.auth /var/lib/tpm/system.data + else + inst /var/lib/tpm/system.data.auth /var/lib/tpm/system.data + fi + fi + + chown -R tss:tss "$initdir/var/lib/tpm" + chmod -R u=rwX,go= "$initdir/var/lib/tpm" +} + +installkernel() { + hostonly='' instmods '=drivers/char/tpm' +} diff --git a/src/luks/dracut/clevis/clevis-cleanup-hook.sh.in b/src/luks/dracut/clevis/clevis-cleanup-hook.sh.in index 74af4e91..230cc554 100755 --- a/src/luks/dracut/clevis/clevis-cleanup-hook.sh.in +++ b/src/luks/dracut/clevis/clevis-cleanup-hook.sh.in @@ -22,6 +22,11 @@ ( [ -s /run/clevis.pid ] || exit 0 + if [ -f @libexecdir@/clevis-luks-tpm1-functions ]; then + . @libexecdir@/clevis-luks-tpm1-functions + stop_tcsd + fi + pid=$(cat /run/clevis.pid) child_pids=$(ps -A -o pid,ppid | awk -v pid="$pid" '$2==pid { print $1 }') for kill_pid in $pid $child_pids; do diff --git a/src/luks/dracut/clevis/clevis-password-unlocker.in b/src/luks/dracut/clevis/clevis-password-unlocker.in index 32716e71..2dee1eb5 100755 --- a/src/luks/dracut/clevis/clevis-password-unlocker.in +++ b/src/luks/dracut/clevis/clevis-password-unlocker.in @@ -109,6 +109,7 @@ clevisloop() { local askpass_info local sleep_time local OLD_CRYPTTAB_SOURCE="" + local tpm1cfg_attempted=0 while true; do # Re-get the askpass PID in case there are multiple encrypted devices @@ -132,6 +133,11 @@ EOM [ "$CRYPTTAB_SOURCE" = "$OLD_CRYPTTAB_SOURCE" ] && continue OLD_CRYPTTAB_SOURCE="$CRYPTTAB_SOURCE" + if [[ " $pins " == *" tpm1 "* ]] && [ $tpm1cfg_attempted -eq 0 ]; then + tpm1cfg_attempted=1 + do_configure_tpm1 + fi + if luks_decrypt "${CRYPTTAB_SOURCE}" "${PASSFIFO}"; then info "Unlocked ${CRYPTTAB_SOURCE} with clevis" @@ -147,6 +153,25 @@ EOM done } +do_configure_tpm1() { + local tcsd_output= + local tcsd_result + + [ -x @bindir@/clevis-decrypt-tpm1 ] && [ -f @libexecdir@/clevis-luks-tpm1-functions ] || return + + . @libexecdir@/clevis-luks-tpm1-functions + + info "Starting TCSD daemon" + + if ! tcsd_output=$(start_tcsd 2>&1); then + if [ -n "$tcsd_output" ]; then + echo "Unable to start TCSD: $tcsd_output" | vwarn + else + warn "Unable to start TCSD" + fi + fi +} + mkdir -p -m 0755 /var/cache mkdir -p -m 0700 /var/cache/clevis-disks diff --git a/src/luks/dracut/meson.build b/src/luks/dracut/meson.build index 7ad5b14c..21aee0bc 100644 --- a/src/luks/dracut/meson.build +++ b/src/luks/dracut/meson.build @@ -1,5 +1,6 @@ subdir('clevis') subdir('clevis-pin-tang') +subdir('clevis-pin-tpm1') subdir('clevis-pin-tpm2') subdir('clevis-pin-sss') subdir('clevis-pin-null')