Skip to content

Commit 15f9392

Browse files
committed
dracut: added TPM 1.2 support for Dracut
Signed-off-by: Oldřich Jedlička <oldium.pro@gmail.com>
1 parent 847dc3f commit 15f9392

File tree

5 files changed

+215
-0
lines changed

5 files changed

+215
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
dracut = dependency('dracut', required: false)
2+
3+
if dracut.found()
4+
dracutdir = dracut.get_pkgconfig_variable('dracutmodulesdir') + '/60' + meson.project_name() + '-pin-tpm1'
5+
6+
configure_file(
7+
input: 'module-setup.sh.in',
8+
output: 'module-setup.sh',
9+
install_dir: dracutdir,
10+
configuration: data,
11+
)
12+
else
13+
warning('Will not install dracut module clevis-pin-tpm1 due to missing dependencies!')
14+
endif
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
#!/bin/bash
2+
# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
3+
#
4+
# Copyright (c) 2024 Oldřich Jedlička
5+
#
6+
# Author: Oldřich Jedlička <oldium.pro@gmail.com>
7+
#
8+
# This program is free software: you can redistribute it and/or modify
9+
# it under the terms of the GNU General Public License as published by
10+
# the Free Software Foundation, either version 3 of the License, or
11+
# (at your option) any later version.
12+
#
13+
# This program is distributed in the hope that it will be useful,
14+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
# GNU General Public License for more details.
17+
#
18+
# You should have received a copy of the GNU General Public License
19+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
20+
#
21+
22+
require_file() {
23+
local path="$1"
24+
if ! [ -f "$path" ]; then
25+
# shellcheck disable=SC2154 # $moddir is a dracut variable
26+
local _module_name="${moddir##*/[0-9][0-9]}"
27+
dinfo "dracut module '${_module_name}' will not be installed, because file '$path' could not be found!"
28+
return 1
29+
fi
30+
return 0
31+
}
32+
33+
require_files() {
34+
local _ret=0
35+
for path in "$@"; do
36+
require_file "$path" || ((_ret++))
37+
done
38+
return "$_ret"
39+
}
40+
41+
require_dir() {
42+
local path="$1"
43+
if ! [ -d "$path" ]; then
44+
local _module_name="${moddir##*/[0-9][0-9]}"
45+
dinfo "dracut module '${_module_name}' will not be installed, because directory '$path' could not be found!"
46+
return 1
47+
fi
48+
return 0
49+
}
50+
51+
require_nonempty_dir() {
52+
local path="$1"
53+
require_dir "$path" || return 1
54+
# See https://superuser.com/a/667095 how to test empty dir
55+
files=$(shopt -s nullglob; shopt -u dotglob; echo "$path/"*)
56+
if ! [[ "$files" ]]; then
57+
local _module_name="${moddir##*/[0-9][0-9]}"
58+
dinfo "dracut module '${_module_name}' will not be installed, because directory '$path' is empty!"
59+
return 1
60+
fi
61+
return 0
62+
}
63+
64+
check() {
65+
local _module_name="${moddir##*/[0-9][0-9]}"
66+
67+
require_binaries clevis-decrypt-tpm1 tpm_version tpm_unsealdata tcsd stdbuf || return 1
68+
if [[ $hostonly ]]; then
69+
require_nonempty_dir /var/lib/tpm || return 1
70+
else
71+
[ -f /usr/share/trousers/system.data.auth ] || \
72+
[ -f /var/lib/tpm/system.data.auth ] || \
73+
ddebug " ${_module_name}: no usable system.data.auth in /usr/share/trousers nor /var/lib/tpm found, using built-in one"
74+
fi
75+
if dracut_module_included "systemd"; then
76+
# shellcheck disable=SC2154 # $systemdsystemunitdir is a dracut variable
77+
require_files \
78+
"$systemdsystemunitdir"/tcsd.service \
79+
"$systemdsystemunitdir"/tcsd.service.d/clevis-tcsd.conf \
80+
|| return 1
81+
fi
82+
return 0
83+
}
84+
85+
depends() {
86+
echo clevis network
87+
return 0
88+
}
89+
90+
install() {
91+
if dracut_module_included "systemd"; then
92+
inst_multiple \
93+
"$systemdsystemunitdir/tcsd.service" \
94+
"$systemdsystemunitdir/tcsd.service.d/clevis-tcsd.conf"
95+
# shellcheck disable=SC2154 # $initdir is a dracut variable
96+
systemctl -q --root "$initdir" add-wants cryptsetup.target tcsd.service
97+
else
98+
inst_multiple \
99+
awk chmod chown mkfifo mktemp ip ps stdbuf \
100+
@libexecdir@/clevis-luks-tpm1-functions
101+
if [ -f /usr/libexec/coreutils/libstdbuf.so ]; then
102+
inst_multiple /usr/libexec/coreutils/libstdbuf.so*
103+
else
104+
inst_libdir_file 'coreutils/libstdbuf.so*'
105+
fi
106+
fi
107+
108+
inst_multiple \
109+
clevis-decrypt-tpm1 \
110+
tcsd \
111+
tpm_version \
112+
tpm_unsealdata
113+
114+
inst_rules 60-tpm-udev.rules
115+
116+
if ! [[ $hostonly ]] || ! dracut_module_included "systemd"; then
117+
# /etc/hosts is installed only in host-only mode with systemd, so
118+
# we need to create our own in order to get tpm tools working.
119+
# The localhost entry is required by tpm tools.
120+
if [ ! -f "$initdir/etc/hosts" ]; then
121+
echo "127.0.0.1 localhost" >> "$initdir/etc/hosts"
122+
echo "::1 localhost ip6-localhost ip6-loopback" >> "$initdir/etc/hosts"
123+
echo "ff02::1 ip6-allnodes" >> "$initdir/etc/hosts"
124+
echo "ff02::2 ip6-allrouters" >> "$initdir/etc/hosts"
125+
fi
126+
fi
127+
128+
if [[ $hostonly ]]; then
129+
inst /etc/tcsd.conf
130+
inst_multiple /var/lib/tpm/*
131+
else
132+
inst_dir /etc
133+
touch "$initdir/etc/tcsd.conf"
134+
if [ -f "/etc/tcsd.conf" ] && [[ $(stat -c "0%a" "/etc/tcsd.conf") = "0600" ]]; then
135+
# Compatibility with tcsd version 0.3.14
136+
chmod 0600 "$initdir/etc/tcsd.conf"
137+
chown tss:tss "$initdir/etc/tcsd.conf"
138+
else
139+
chmod 0640 "$initdir/etc/tcsd.conf"
140+
chown root:tss "$initdir/etc/tcsd.conf"
141+
fi
142+
143+
inst_dir /var/lib/tpm
144+
if [ -f /usr/share/trousers/system.data.auth ]; then
145+
inst /usr/share/trousers/system.data.auth /var/lib/tpm/system.data
146+
elif [ -f /var/lib/tpm/system.data.auth ]; then
147+
inst /var/lib/tpm/system.data.auth /var/lib/tpm/system.data
148+
else
149+
jose b64 dec -i- >"$initdir/var/lib/tpm/system.data" <<EOM
150+
AQEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAABLwEAAAAAAwAAAAAAAAAAAAAA
151+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
152+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
153+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
154+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
155+
AAAAAAAAAAAAAAAAAAAAAAAAAQEABgARAAAAAAEAAAABAAMAAQAAAAwAAAgAAAAAAgAAAAAAAAAA
156+
AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
157+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
158+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
159+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
160+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
161+
EOM
162+
fi
163+
fi
164+
165+
chown -R tss:tss "$initdir/var/lib/tpm"
166+
chmod -R u=rwX,go= "$initdir/var/lib/tpm"
167+
}
168+
169+
installkernel() {
170+
hostonly='' instmods '=drivers/char/tpm'
171+
}

src/luks/dracut/clevis/clevis-cleanup.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222

2323
. clevis-luks-common-functions
2424

25+
if [ -f @libexecdir@/clevis-luks-tpm1-functions ]; then
26+
. @libexecdir@/clevis-luks-tpm1-functions
27+
stop_tcsd
28+
fi
29+
2530
pid=$(cat /run/clevis.pid)
2631
clevis_kill_pid $pid
2732

src/luks/dracut/clevis/clevis-password-unlocker.in

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ clevisloop() {
115115
local askpass_info
116116
local sleep_time
117117
local OLD_CRYPTTAB_SOURCE=""
118+
local tpm1cfg_attempted=0
118119

119120
while true; do
120121
# Re-get the askpass PID in case there are multiple encrypted devices
@@ -138,6 +139,11 @@ EOM
138139
[ "$CRYPTTAB_SOURCE" = "$OLD_CRYPTTAB_SOURCE" ] && continue
139140
OLD_CRYPTTAB_SOURCE="$CRYPTTAB_SOURCE"
140141

142+
if [[ " $pins " == *" tpm1 "* ]] && [ $tpm1cfg_attempted -eq 0 ]; then
143+
tpm1cfg_attempted=1
144+
do_configure_tpm1
145+
fi
146+
141147
if luks_decrypt "${CRYPTTAB_SOURCE}" "${PASSFIFO}"; then
142148
info "Unlocked ${CRYPTTAB_SOURCE} with clevis"
143149

@@ -153,6 +159,24 @@ EOM
153159
done
154160
}
155161

162+
do_configure_tpm1() {
163+
local tcsd_output=
164+
165+
[ -x @bindir@/clevis-decrypt-tpm1 ] && [ -f @libexecdir@/clevis-luks-tpm1-functions ] || return
166+
167+
. @libexecdir@/clevis-luks-tpm1-functions
168+
169+
info "Starting TCSD daemon"
170+
171+
if ! tcsd_output=$(start_tcsd 2>&1); then
172+
if [ -n "$tcsd_output" ]; then
173+
echo "Unable to start TCSD: $tcsd_output" | vwarn
174+
else
175+
warn "Unable to start TCSD"
176+
fi
177+
fi
178+
}
179+
156180
mkdir -p /var/cache/clevis-disks
157181
chmod 0700 /var/cache/clevis-disks
158182

src/luks/dracut/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
subdir('clevis')
22
subdir('clevis-pin-tang')
3+
subdir('clevis-pin-tpm1')
34
subdir('clevis-pin-tpm2')
45
subdir('clevis-pin-sss')
56
subdir('clevis-pin-null')

0 commit comments

Comments
 (0)