tzpfms

TPM-based encryption keys for ZFS datasets.
Manpages
Why?
T P M
Z F S
Plus it's a pretty good annoyed sigh onomatopoeia.
What?
Essentially BitLocker, but for ZFS – a random raw key is generated and sealed to the TPM (both 2 and 1.x supported) with an additional optional password in front of it, tying the dataset to the platform and an additional optional secret (or to the posession of the back-up).
Both dracut (with/without Plymouth) (with/without hostonly) (only on systemd systems, I don't have a test-bed for the non-systemd path) and initramfs-tools (with/without Plymouth) are supported for ZFS-on-root set-ups.
Building
You'll need pkg-config
, ronn
, shellcheck
, libzfslinux-dev
, libtss2-dev
, libtspi-dev
, and make
should hopefully Just Work™ if you have a C++17-capable compiler.
The output binaries are trimmed of extraneous dependencies, so they're all just libc + libzfs and friends + the chosen TPM back-end, if any.
Installation
Copy the out/zfs-tpm*
binaries corresponding to the back-ends you want to /sbin
,
continue as the manual page instructs.
For initrd support, copy the content of either out/dracut/
or out/initramfs-tools/
over /
;
these need zfs-tpm-list
but will work with any combination of back-end *-load-key
binaries.
Testing
TPM2
Build swtpm
, then prepare and run it:
swtpm_setup --tpmstate tpm2-state --tpm2 --createek --display --logfile /dev/stdout --overwrite
swtpm socket --server type=tcp,port=2321 --ctrl type=tcp,port=2322 --tpm2 --tpmstate dir=tpm2-state --flags not-need-init --log level=10
If your platform has a TPM, switch to swtpm
by default:
ln -s /usr/lib/i386-linux-gnu/libtss2-tcti-{swtpm,default}.so
TPM1.x
Build swtpm
, then prepare and run it and
(hopefully) TrouSerS, as root
/tpm
:
swtpm_setup --tpmstate tpm1x-state --createek --display --logfile /dev/stdout --overwrite
swtpm cuse -n tpm --tpmstate dir=tpm1x-state --seccomp action=none --log level=10,file=/dev/fd/4 4>&1
swtpm_ioctl -i /dev/tpm
TPM_DEVICE=/dev/tpm swtpm_bios
tcsd -f
swtpm_ioctl -s /dev/tpm # to shut down, apparently
If your platform has a TPM, occupy it first by running exec 100<>/dev/tpm0
or equivalent. tcsd
looks at /dev/tpm0
before /dev/tpm
.
initrd
Running
swtpm socket --ctrl type=unixio,path=/tmp/swtpm --tpm2 --tpmstate dir=tpm2-state --flags not-need-init --log level=10
# or
swtpm socket --ctrl type=unixio,path=/tmp/swtpm --tpmstate dir=tpm1x-state --log level=10
instead, alongside passing
-chardev socket,id=chrtpm,path=/tmp/swtpm -tpmdev emulator,id=tpm0,chardev=chrtpm -device tpm-tis,tpmdev=tpm0
to QEMU will create a TPM device on the guest which Should® be fully funxional.
Reporting bugs
There's the tracker, but also see the list below.
Contributing
Send a patch inline, as an attachment, or a git link and a ref to pull from to the list (~nabijaczleweli/tzpfms@lists.sr.ht) or me directly. I'm not picky, just please include the repo name in the subject prefix.
Discussion
Please use the tracker, the list, or Twitter.
Special thanks
To all who support further development on Patreon, in particular:
- ThePhD
- Embark Studios