[systemd-devel] Issues supporting systems with and without TPM and firmware TPM (was Re: Handle device node timeout?)

Mikko Rapeli mikko.rapeli at linaro.org
Fri Feb 16 09:28:31 UTC 2024


Hi,

Following up to my previous question which worked around with
Wants: and After: to dev-tpmrm0.device and tee-supplicant at teepriv0.service,
which don't seem to work fully.

In short, I want to support devices with and without TPM. The TPM device
can also be a firmware fTPM device which depends on tee-supplicant in userspace
for RPMB storage.

If TPM device is found, systemd repart in initramfs will create an encrypted rootfs
and if not a plaintext ext4 partition.

Support for TPM devices is ok and drivers are built into kernel. systemd repart config
for rootfs is:

[Partition]
Type=root
Weight=100
Format=ext4
Encrypt=tpm2
FactoryReset=yes
MakeDirectories=/boot /usr /home /home/root
# copying etc from build time /usr image
CopyFiles=/usr/etc:/etc

/usr partition generated at build time is dm-verity protected and contains
/etc which is copied over to newly created rootfs.

Support for fTPM devices is problematic. First, the kernel support must be modules
but loading needs to be specially handled after starting tee-supplicant. For normal
boot udev handles optee detection and triggers tee-supplicant at teepriv0.service
startup which unloads tpm_ftpm_tee kernel module, starts tee-supplicant and then
loads the kernel module again. After this RPMB works. To do the same in initramfs, I added
Wants: and After: dependencies from systemd-repart.service, systemd-cryptsetup at .service,
systemd-pcrmachine.service and systemd-pcrphase-initrd.service:

After=dev-tpmrm0.device tee-supplicant at teepriv0.service
Wants=dev-tpmrm0.device tee-supplicant at teepriv0.service

The base tee-supplicant at .service is:

[Unit]
Description=TEE Supplicant on %i
# Needs to be started earlier
DefaultDependencies=no
Conflicts=shutdown.target initrd-switch-root.target
Before=local-fs-pre.target cryptsetup-pre.target cryptsetup.target shutdown.target initrd-switch-root.target systemd-sysext.service
Before=systemd-pcrphase-initrd.service systemd-pcrphase.service systemd-pcrmachine.service

[Service]
User=root
EnvironmentFile=- at sysconfdir@/default/tee-supplicant
ExecStartPre=- at sbindir@/modprobe -r tpm_ftpm_tee
ExecStartPre=@sbindir@/create-tee-supplicant-env @localstatedir@/run/tee-supplicant.env
ExecStart=/bin/sh -c "if [ -c /dev/teepriv0 ]; then @sbindir@/tee-supplicant $RPMB_CID $OPTARGS; fi"
ExecStartPost=-/bin/sh -c "while [ ! $(pgrep tee-supplicant) ]; do sleep 0.1; done; /sbin/modprobe tpm_ftpm_tee"
ExecStop=-/sbin/modprobe -r tpm_ftpm_tee

[Install]
# fTPM encrypted filesystems, needs to start in initrd stage
WantedBy=local-fs-pre.target

These seem to work for devices with and without TPM, but on devices with missing optee
and /dev/teepriv0 not. The missing TPM device is detected after timeout, which is ok,
and the fallback to unencrypted ext4 happens since systemd-repart.service has:

ExecStart=/bin/sh -c "/usr/bin/test -c /dev/tpmrm0 && /usr/bin/systemd-repart --dry-run=no --definitions=${nonarch_libdir}/repart.d/ || /usr/bin/systemd-repart --dry-run=no --definitions=${nonarch_libdir}/repart.d_notpm/"

But the missing optee and /dev/teepriv0 causes issues where tee-supplicant at teepriv0.service gets
started in initramfs stage but since optee is not found from firmware tee-supplicant exits with error.

So what could be done better or correctly?

The problematic part is to run these tee-supplicant and tpm_ftpm_tee loading steps
only when /dev/teepriv0 is available and early enough for TPM2 dependencies to work
for systemd.

Should I rather setup a dedicated service for initramfs which emulates
Wants: and After: for dev-tpmrm0.device and tee-supplicant at teepriv0.service? 

Thanks in advance,

-Mikko


More information about the systemd-devel mailing list