Add TPM 1.2 support
This patch series adds TPM 1.2 support and fixes few other things (I can split this into multiple Pull Requests if you wish):
- Added missing shutdown SystemD dependencies when using
DefaultDependencies=no. - When Dracut without SystemD is used, benefit cryptsetup unlocking workflow to let it handle the crypttab and other options. This uses pipe to unlock with password similarly like the initramfs-tools image does. See commit message for more details.
- Added full support for TPM 1.2.
Status:
- [✅ Done] Clevis encrypt, decrypt, bind support
- [✅ Done] initramfs-tools support
- [✅ Done] Systemd support
- [✅ Done] Manual page for
clevis-encrypt-tpm1 - [✅ Done] Tests for tpm1 pin
- [✅ Done] Dracut support
Example usage:
- Boot and unlock with TPM1.2:
clevis luks bind -d /dev/<device> tpm1 '{"pcr_ids":"0,4,7"}' - Encrypt and decrypt:
echo test | clevis encrypt tpm1 '{"pcr_ids":"0,4,7"}' | clevis decrypt
Tested:
- Tested with initramfs-tools, used both TPM 1.2 and null pins with
"fail":trueto test success and failed unlocking - Tested with Dracut with SystemD. Tested both success and failed cases
- Tested with Dracut without SystemD (module was disabled). Tested both success and failed cases
- Tested with Dracut without SystemD (module was disabled), with programmatically changed detection that null pin is a network pin. Tested that with
rd.neednetthe unlocking happens after network gets online.
Fixes: #84, #456
Work is done, pre-built packages for Debian 12 and amd64 arch are available here https://github.com/oldium/clevis/releases/tag/v20_tpm1
The CentOS test build image needs some love, the mirrorlist.centos.org site does not exist any more it seems.
Rebased to latest master to fix the build.
The build failure is caused by some hashes mismatch in centos:stream9, but when run locally with https://github.com/nektos/act, it works. Probably a temporary issue.
I will rebase the Pull Request and check if there is any update to clevis_luks_used_pins function necessary towards the new pkcs11 feature.
Rebased, manually pre-built packages (including pkcs11 pin, untested) for Debian 12 and amd64 arch are available here https://github.com/oldium/clevis/releases/tag/v21_tpm1
I see that the PKCS#11 tests use software emulation, so this is an inspiration for me to do the same with TPM 1 😁 (and maybe I can improve TPM 2 test as well) - I will try to do the same with swtpm.
For Debian, I added small patch to allow installation of pkcs11 files for dracut without actually the need to have pkcs11 pin installed, same as it is done for TPM1 and TPM2:
diff --git a/src/luks/dracut/clevis-pin-pkcs11/module-setup.sh.in b/src/luks/dracut/clevis-pin-pkcs11/module-setup.sh.in
index 39d06a0..4abac0f 100755
--- a/src/luks/dracut/clevis-pin-pkcs11/module-setup.sh.in
+++ b/src/luks/dracut/clevis-pin-pkcs11/module-setup.sh.in
@@ -17,6 +17,12 @@
#
# shellcheck disable=SC2154
#
+
+check() {
+ require_binaries pcscd pkcs11-tool socat clevis-decrypt-pkcs11 || return 1
+ return 0
+}
+
depends() {
echo clevis
return 255
--
I added the patch as a separate Pull Request #480
This is amazing work, @oldium! I sincerely hope this can be merged, as it makes it possible for my older thinkpads to utilize TPM 1.2 for LUKS unlocking in conjuction with coreboot/edk2, secure boot and unified kernel images. That's a very decent secure boot path up until logging in to the system.
I'll try to build this manually for void linux too.
Finally, I was able to get SW emulation working (with swtpm package), some custom tcsd LD_PRELOAD love was necessary to force it start during CI build, but nothing unsolvable 😅. I will update the Pull Request as soon as I tidy it up.
I just figured out that the CI is not updated to have the needed libraries, I will do it in the following days.
Otherwise the SW TPM1 tests work 😁
Finished work on tests, now it works on all build targets.
Observed issues:
-
swtpmsometimes does not stop on Fedora, so needs to be killed (this is handled by tests). -
swtpmdoes not support TPM 1.2 on CentOS Stream 9+ intentionally, which is a pity, so tests are skipped there. - CentOS Stream 10 does not have EPEL repository released yet (they are working on it).
It should be possible to add TPM 2 SW emulation support for tests rather easily I think.
Done. Tests for TPM 2 with SW TPM works too.
I got a feeling that this Pull Request is now ready with all the features it should have.
Any chance you can release a Fedora 40 RPM for this fork like you did for Debian 12? I'd love to pull that into a custom ublue image.
Any chance you can release a Fedora 40 RPM for this fork like you did for Debian 12? I'd love to pull that into a custom ublue image.
Yep, that should be possible. I will have a look at it during the weekend.
~~There is one incompatible change in libdl.so/libdl.so.2 in recent distros, I need to check that.~~
Edit: just meson compatibility, minimum version is 0.62.0.
Anyway, I need to check compilation on older Debian (bullseye) and few Fedoras to observe possible issues and minimum SW versions.
I was able to create Fedora package successfully, but I am not convinced about the approach Fedora packaging chose, because it contains dependency to both tpm1 and tpm2 (tpm-tools, trousers, tpm2-tools). The Debian packaging is more granular, so you just install what you need, either tpm1 or tpm2. I need to test it later today/tomorrow, I created a new VM with Fedora 40 for that.
Latest Debian 11 (bullseye), 12 (bookworm) and Fedora v39, v40 and v41 packages are available here https://github.com/oldium/clevis/releases/tag/v21_tpm1u2.
@sarroutbi I think it would be good to split first 5 commits into separate Pull Requests. They are rather independent improvements/fixes (including fix for #456), so they can be handled more easily. Right?
@sarroutbi I think it would be good to split first 5 commits into separate Pull Requests. They are rather independent improvements/fixes (including fix for #456), so they can be handled more easily. Right?
I don't consider it necessary. It is a pretty big PR, I agree, but we will create a new release (hopefully v22.0) once PKCS#11 status is stable and this TPM1.2 is included.
@sergio-correia : any thoughts?
Ok, thanks. Please do not hesitate to tell me if you wish to split it or do anything else, it is Git after all, so anything can be done 😊
Just a quick confirmation this works great also with a Thinkpad X230 and Fedora 40. Haven’t been able to make it work on ublue/bluefin yet but they have an unusual Dracut generation process, so I’ll dig more on that.
Just a quick confirmation this works great also with a Thinkpad X230 and Fedora 40. Haven’t been able to make it work on ublue/bluefin yet but they have an unusual Dracut generation process, so I’ll dig more on that.
Great, thanks for testing. I have never heard of Bluefin, but it looks like a Fedora clone. If I am able to make a VM from the installation media, count on me 😊 I will check it later this week.
@natterangell Which release of Bluefin are you most interested in? GTS (Fedora 39) or stable (Fedora 40)?
Edit: I have tested Clevis TPM 1.2 on Fedora 40 actually, not on Fedora 39, so the version could be relevant.
I think I got it. Fedora is using hostonly=yes Dracut config, while Ublue-OS has hostonly=no. The Fedora's RPM unfortunately does not contain required trouser's file system.data.auth, so I will probably need to provide a fallback copy in Clevis.
For hostonly=yes I simply take /var/lib/tpm as usable, while for hostonly=no I need to make one - this is why I use system.data.auth file from trousers distribution - if it exists.
I probably need to provide that file for those using such broken RPMs (I would call it broken - because the files are usually part of distributions like Debian and OpenSuse, but not RedHat-based) and also improve error message.
I’m building a Bluefin Stable (40) image over here: https://github.com/natterangell/bluefin-dx-thinkpad
I’m basically force replacing clevis and clevis-luks, then adding clevis-dracut and clevis-systemd (all from your fork).
Yes, I’ve noticed the system.data.auth missing. Can that just be dropped in?
When I run lsinitramfs on the locally generated one (which must be manually done with ‘rpm-ostree initramfs —enable’ it seems to include clevis and everything needed for tpm2, but not tpm1 (let me know if want grep-files).
is system.data.auth enough?
Vanilla Fedora 40 works great with your fork! The problem is Bluefin is container based, its downstream of Fedora Silverblue, so it ships initramfs prebuilt, so to speak.
I’m building a Bluefin Stable (40) image over here: https://github.com/natterangell/bluefin-dx-thinkpad
I’m basically force replacing clevis and clevis-luks, then adding clevis-dracut and clevis-systemd (all from your fork).
I used rpm-ostree install as an alternative to dnf install as written in Fedora 40 steps on my TPM 1.2 release page. I first ran dnf install, this failed, second run with rpm-ostree install succeeded. Then I rebooted. In this way I had clevis from RPMs installed.
Yes, I’ve noticed the system.data.auth missing. Can that just be dropped in?
When I run lsinitramfs on the locally generated one (which must be manually done with ‘rpm-ostree initramfs —enable’ it seems to include clevis and everything needed for tpm2, but not tpm1 (let me know if want grep-files).
Here I need to provide an error message, it just checks for file existence and returns 1 to skip it - Dracut itself does not print anything unfortunately. I will fix this particular case by a fallback system.data.auth file, but other checks need to print something.
is system.data.auth enough?
Yes, just put it as /usr/share/trousers/system.data.auth or /var/lib/tpm/system.data.auth and re-run rpm-ostree initramfs --enable.
Vanilla Fedora 40 works great with your fork! The problem is Bluefin is container based, its downstream of Fedora Silverblue, so it ships initramfs prebuilt, so to speak.
@natterangell Fixed in update 3 at https://github.com/oldium/clevis/releases/tag/v21_tpm1u3. rpm-ostree is weird. No more 😅
Basically, you should see something like the following when running journalctl -t rpm-ostree after clevis update:
If you do not see it there, play more with rpm-ostree to get the update into the image. 🙈
Ha! It is possible to reinstall clevis in single run.
Install:
sudo rpm-ostree install clevis-pin-tpm2 ./clevis-21-1.tpm1u3.fc40.x86_64.rpm ./clevis-dracut-21-1.tpm1u3.fc40.x86_64.rpm ./clevis-luks-21-1.tpm1u3.fc40.x86_64.rpm ./clevis-systemd-21-1.tpm1u3.fc40.x86_64.rpm
Update (without clevis-pin-tpm2):
sudo rpm-ostree install ./clevis-21-1.tpm1u3.fc40.x86_64.rpm ./clevis-dracut-21-1.tpm1u3.fc40.x86_64.rpm ./clevis-luks-21-1.tpm1u3.fc40.x86_64.rpm ./clevis-systemd-21-1.tpm1u3.fc40.x86_64.rpm --uninstall clevis --uninstall clevis-dracut --uninstall clevis-luks --uninstall clevis-systemd
But the package management in this way is painfully slow... Anyway, I think I am finished with this OS 😅