From 768b21c2e7d75e26f09eda70702011cd9b9abf54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Sun, 6 Dec 2020 18:14:48 +0100 Subject: [PATCH] Fix change-key for TPM1.X. Test and unfuck i-t TPM1.X Tested on Toshiba R700 --- initrd/initramfs-tools/hook | 38 +++++++++++++++++++++++++++-- initrd/initramfs-tools/zfs-patch.sh | 35 +++++++++++++++++++++++--- src/bin/zfs-tpm1x-change-key.cpp | 9 ++++--- 3 files changed, 72 insertions(+), 10 deletions(-) diff --git a/initrd/initramfs-tools/hook b/initrd/initramfs-tools/hook index b06e243..fabe150 100755 --- a/initrd/initramfs-tools/hook +++ b/initrd/initramfs-tools/hook @@ -13,10 +13,44 @@ sed -Ei 's/^decrypt_fs\(\)/__tzpfms__&/' "$DESTDIR/scripts/zfs" cat /usr/share/tzpfms/initramfs-tools-zfs-patch.sh >> "$DESTDIR/scripts/zfs" -for x in zfs-tpm-list zfs-tpm2-load-key zfs-tpm1x-load-key tcsd $(find /usr/lib -name 'libtss2-tcti*.so*'); do # TODO: there's got to be a better way™! +for x in tpm_resetdalock zfs-tpm-list zfs-tpm2-load-key zfs-tpm1x-load-key tcsd $(find /usr/lib -name 'libtss2-tcti*.so*'); do # TODO: there's got to be a better way™! xloc="$(command -v "$x")" [ "$xloc" = "" ] || copy_exec "$xloc" done +if command -v tcsd > /dev/null; then + # tcsd exits if it doesn't have tss group and user + grep tss /etc/group >> "$DESTDIR/etc/group" + grep tss /etc/passwd >> "$DESTDIR/etc/passwd" -add_loaded_modules '*tpm*' # TODO: is this the best way of going about this? + for f in /lib/udev/rules.d/*tpm*; do + copy_file rule $f + done + + if [ -e /etc/tcsd.conf ]; then + copy_file config /etc/tcsd.conf + system_ps_file="$(awk -F '[[:space:]]*=[[:space:]]*' '!/^[[:space:]]*#/ && !/^$/ && $1 ~ /system_ps_file$/ {gsub(/[[:space:]]*$/, "", $2); print $2}' /etc/tcsd.conf)" + system_ps_file="${system_ps_file:-/var/lib/tpm/system.data}" + fi + + # tcsd can't find SRK if state not present, refuses to start if it doesn't have parent to tss dir + mkdir -p "$DESTDIR/$(dirname "$(dirname "$system_ps_file")")" + [ -f "$system_ps_file" ] && copy_file state "$system_ps_file" +fi + +# localhost needs to resolve at the very least +for f in /etc/hosts /etc/resolv.conf /etc/host.conf /etc/gai.conf; do + [ -e $f ] && copy_file config $f +done +if [ -e /etc/nsswitch.conf ]; then + copy_file config /etc/nsswitch.conf + databases="$(awk '/^group|hosts/ {for(i = 2; i <= NF; ++i) print $i}' /etc/nsswitch.conf | sort | uniq)" + for db in $databases; do + for f in /lib/*/"libnss_$db"*; do + copy_exec "$f" + done + done +fi + + +copy_modules_dir 'kernel/drivers/char/tpm' diff --git a/initrd/initramfs-tools/zfs-patch.sh b/initrd/initramfs-tools/zfs-patch.sh index 405afd6..23ea667 100644 --- a/initrd/initramfs-tools/zfs-patch.sh +++ b/initrd/initramfs-tools/zfs-patch.sh @@ -24,9 +24,36 @@ decrypt_fs() { fi if command -v zfs-tpm1x-load-key > /dev/null && ! [ "$(zfs-tpm-list -Hub TPM1.X "$ENCRYPTIONROOT")" = "" ]; then - [ -z "$TZPFMS_TPM1X" ] && command -v tcsd > /dev/null && tcsd -f & + [ -z "$TZPFMS_TPM1X" ] && command -v tcsd > /dev/null && { + ip l | awk -F '[[:space:]]*:[[:space:]]*' '{if($2 == "lo") exit $3 ~ /UP/}' + lo_was_up="$?" + if [ "$lo_was_up" = "0" ]; then + ip l set up dev lo + while ! ip a show dev lo | grep -qE '::1|127.0.0.1'; do sleep 0.1; done + fi + + if [ "${quiet:-n}" = "y" ]; then + tcsd -f > /tcsd.log 2>&1 & + else + tcsd -f & + fi + tcsd_port="$(awk -F '[[:space:]]*=[[:space:]]*' '!/^[[:space:]]*#/ && !/^$/ && $1 ~ /port$/ {gsub(/[[:space:]]/, "", $2); print $2}' /etc/tcsd.conf)" + i=0; while [ "$i" -lt 100 ] && ! netstat -lt | grep -q "${tcsd_port:-30003}"; do sleep 0.1; i="$((i + 1))"; done + [ "$i" = 100 ] && echo "Couldn't start tcsd!" >&2 + } + with_promptable_tty zfs-tpm1x-load-key "$ENCRYPTIONROOT"; err="$?" - [ -z "$TZPFMS_TPM1X" ] && command -v tcsd > /dev/null && kill %+ + + [ -z "$TZPFMS_TPM1X" ] && command -v tcsd > /dev/null && { + kill %+ + + if [ "$lo_was_up" = "0" ]; then + ip l set down dev lo + # ::1 removed automatically + ip a del 127.0.0.1/8 dev lo 2>/dev/null + fi + } + return "$err" fi @@ -49,7 +76,7 @@ decrypt_fs() { with_promptable_tty() { if command -v plymouth > /dev/null && plymouth --ping; then plymouth hide-splash - grep -q 'quiet' /proc/cmdline && printf '\033c' + [ "${quiet:-n}" = "y" ] && printf '\033c' "$@"; ret="$?" @@ -61,7 +88,7 @@ with_promptable_tty() { "$@"; ret="$?" - [ "$printk" = "7" ] || echo 7 > /proc/sys/kernel/printk + [ "$printk" = "7" ] || echo "$printk" > /proc/sys/kernel/printk fi return "$ret" } diff --git a/src/bin/zfs-tpm1x-change-key.cpp b/src/bin/zfs-tpm1x-change-key.cpp index 87294fa..42e252f 100644 --- a/src/bin/zfs-tpm1x-change-key.cpp +++ b/src/bin/zfs-tpm1x-change-key.cpp @@ -88,11 +88,12 @@ int main(int argc, char ** argv) { Tspi_Context_CloseObject(ctx, sealed_object); }}; - TSS_HOBJECT bound_pcrs{}; // See tpm_sealdata.c from src:tpm-tools for more on flags here - TRY_TPM1X("create PCR list", Tspi_Context_CreateObject(ctx, TSS_OBJECT_TYPE_PCRS, 0, &bound_pcrs)); - quickscope_wrapper bound_pcrs_deleter{[&] { Tspi_Context_CloseObject(ctx, bound_pcrs); }}; + // This would need to replace the 0 below to handle PCRs + // TSS_HOBJECT bound_pcrs{}; // See tpm_sealdata.c from src:tpm-tools for more on flags here + // TRY_TPM1X("create PCR list", Tspi_Context_CreateObject(ctx, TSS_OBJECT_TYPE_PCRS, 0, &bound_pcrs)); + // quickscope_wrapper bound_pcrs_deleter{[&] { Tspi_Context_CloseObject(ctx, bound_pcrs); }}; - TRY_TPM1X("seal wrapping key data", Tspi_Data_Seal(sealed_object, parent_key, WRAPPING_KEY_LEN, wrap_key, bound_pcrs)); + TRY_TPM1X("seal wrapping key data", Tspi_Data_Seal(sealed_object, parent_key, WRAPPING_KEY_LEN, wrap_key, 0)); uint8_t * parent_key_blob{};