Skip to content

Commit

Permalink
Updated basic TPM1 support for preparation for Dracut integration
Browse files Browse the repository at this point in the history
  • Loading branch information
oldium committed Jun 18, 2024
1 parent 3da07b0 commit a605080
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 47 deletions.
1 change: 1 addition & 0 deletions src/initramfs-tools/hooks/clevis.in
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ if [ -x @bindir@/clevis-decrypt-tpm2 ]; then
fi
if [ -x @bindir@/clevis-decrypt-tpm1 ]; then
copy_exec @bindir@/clevis-decrypt-tpm1 || die 1 "@bindir@/clevis-decrypt-tpm1 not found"
copy_exec @libexecdir@/clevis-luks-tpm1-functions || die 1 "@libexecdir@/clevis-luks-tpm1-functions not found"

tcsd_bin=$(find_binary "tcsd")
tpm_version_bin=$(find_binary "tpm_version")
Expand Down
7 changes: 6 additions & 1 deletion src/initramfs-tools/scripts/local-bottom/clevis.in
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,15 @@ esac

[ -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 -o pid,ppid | awk -v pid="$pid" '$2==pid { print $1 }')
for kill_pid in $pid $child_pids; do
kill "$kill_pid"
kill "$kill_pid"
done

# Not really worried about downing extra interfaces: they will come up
Expand Down
62 changes: 16 additions & 46 deletions src/initramfs-tools/scripts/local-top/clevis.in
Original file line number Diff line number Diff line change
Expand Up @@ -295,64 +295,34 @@ do_configure_networking() {
}

do_configure_tpm1() {
if ! [ -x @bindir@/clevis-decrypt-tpm1 ]; then
local tcsd_output
local tcsd_result

if ! [ -x @bindir@/clevis-decrypt-tpm1 ] || ! [ -f @libexecdir@/clevis-luks-tpm1-functions ]; then
log_failure_msg "clevis: clevis tpm1 pin is not installed in initramfs image - missing dependency?"
return 1
fi

if ! temp_dir="$(mktemp -d)"; then
log_failure_msg "clevis: Unable to create temporary directory"
return 1
fi
fifo_file="$temp_dir/fifo"
output_file="$temp_dir/output"
. @libexecdir@/clevis-luks-tpm1-functions

log_begin_msg "clevis: Starting TCSD daemon"

wait_for_udev 10

# If we have udev, let the initialization on udev
if ! [ -f /lib/udev/rules.d/60-tpm.rules ]; then
chown tss:tss /dev/tpm0
chmod 600 /dev/tpm0
fi

ip link set lo up || log_failure_msg "Unable to set-up loopback network device"

mkfifo "$fifo_file"

# Start timeout to finish TCSD startup
sleep 10 &
sleep_pid=$!

# The following loop ends when output side of FIFO closes (i.e. TCSD ends)
while IFS= read -r LINE; do
echo "$LINE" >> "$output_file"
case "$LINE" in
*"TCSD up and running"*)
log_success_msg "clevis: TCSD up and running"
kill $sleep_pid 2>/dev/null
;;
esac
done < $fifo_file && kill $sleep_pid 2>/dev/null &

# Start TCSD in foreground mode as background job. Redirected output is
# block-buffered, so in order to see any output we need to set it at to
# line-buffered with stdbuf
stdbuf -oL tcsd -f >$fifo_file 2>&1 &
tcsd_pid=$!
tcsd_output=$(start_tcsd 2>&1)
tcsd_result=$?

wait $sleep_pid 2>/dev/null

ps -o pid | awk -v pid="$tcsd_pid" '$1==pid {found=1} END {exit !found}'
ret=$?

[ $ret -ne 0 ] && [ -s "$output_file" ] && log_failure_msg "Unable to start TCSD: $(< "$output_file")"
if $tcsd_result -eq 0; then
log_success_msg "clevis: TCSD up and running"
else
if [ -n "$tcsd_output" ]; then
log_failure_msg "clevis: Unable to start TCSD: $tcsd_output"
else
log_failure_msg "clevis: Unable to start TCSD"
fi
fi

rm -rf "$temp_dir"
log_end_msg

return $ret
}

clevisloop &
Expand Down
96 changes: 96 additions & 0 deletions src/luks/clevis-luks-tpm1-functions
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/bin/sh
#
# Copyright (c) 2024 Red Hat, Inc.
# Author: Oldřich Jedlička <[email protected]>
#
# 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 <http://www.gnu.org/licenses/>.
#

start_tcsd() {
[ -s /run/tcsd.pid ] && return 0

if ! ip link show up dev lo | grep -qw UP; then
ip link set dev lo up && echo "lo" > /tmp/tcsd.if || :
if ! ip link show up dev lo | grep -qw UP; then
echo "Unable to set-up loopback network device"
return 1
fi
fi

if ! temp_dir="$(mktemp -d)"; then
echo "Unable to create temporary directory"
return 1
fi

fifo_file="$temp_dir/fifo"
output_file="$temp_dir/output"

# If we have udev, let the initialization on udev
if ! [ -f /lib/udev/rules.d/60-tpm-udev.rules ]; then
chown tss: /dev/tpm0
chmod 660 /dev/tpm0
fi

mkfifo "$fifo_file"

# Start timeout to finish TCSD startup
sleep 10 &
sleep_pid=$!

# The following loop ends when output side of FIFO closes (i.e. TCSD ends)
{ while IFS= read -r LINE; do
echo "$LINE"
case "$LINE" in
*"TCSD up and running"*)
kill $sleep_pid 2>/dev/null
;;
esac
done < $fifo_file && kill $sleep_pid; } >> "$output_file" 2>&1 &

# TCSD in background mode logs into syslogd, so we would not have any logs
# available for debugging, so start TCSD in foreground mode, but as a
# background job. Unfortunatelly the redirected output to pipe is
# block-buffered (see `man 3 setbuf`), so in order to see any output we
# need to set it to line-buffered with stdbuf tool
stdbuf -oL tcsd -f >$fifo_file 2>&1 &
tcsd_pid=$!

wait $sleep_pid 2>/dev/null

if ps -A -o pid | awk -v pid="$tcsd_pid" '$1==pid {found=1} END {exit !found}'; then
ret=0
echo $tcsd_pid > /run/tcsd.pid
else
ret=1
[ -s "$output_file" ] && cat "$output_file"
fi

rm -rf "$temp_dir"

return $ret
}

stop_tcsd() {
[ -s /run/tcsd.pid ] && {
pid=$(cat /run/tcsd.pid)
kill $pid >/dev/null 2>&1 || :
rm -f /run/tcsd.pid
}

[ -s /tmp/tcsd.if ] && {
ip link set dev lo down || :
ip addr flush dev lo || :
rm -f /tmp/tcsd.if
}
}
2 changes: 2 additions & 0 deletions src/luks/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ if libcryptsetup.found() and luksmeta.found()

bins += join_paths(meson.current_source_dir(), 'clevis-luks-pass')
mans += join_paths(meson.current_source_dir(), 'clevis-luks-pass.1')

install_data('clevis-luks-tpm1-functions', install_dir: libexecdir)
else
warning('Will not install LUKS support due to missing dependencies!')
endif
Expand Down

0 comments on commit a605080

Please sign in to comment.