systemd / systemd

The systemd System and Service Manager
https://systemd.io
GNU General Public License v2.0
13.34k stars 3.82k forks source link

Unreliable behaviour when using a TPM PIN causes unlocking and boot failure. #29660

Open IPlayZed opened 1 year ago

IPlayZed commented 1 year ago

systemd version the issue has been seen with

systemd 254.5-1

Used distribution

Arch Linux

Linux kernel version used

6.1.56-1-lts

CPU architectures issue was seen on

x86_64

Component

systemd-cryptsetup

Expected behaviour you didn't see

System should ask for the TPM PIN if policy is correct, otherwise try using a corresponding FIDO2 security key plugged into the system. If multiple volumes are enrolled that are using the same TPM PIN, only ask it for once.

Unexpected behaviour you saw

When using --tpm2-with-pin=BOOL to enroll a key to a LUKS header file, during the boot it asks for a FIDO2 security key, if it was enrolled instead of asking for the PIN for TPM unlocking.

However this behavior is not consistent, as sometimes it asks for the TPM PIN for certain volumes and for others the FIDO2 pin.

There were also cases, where even tough I gave the correct TPM/LUKS2 PIN, certain volumes are not decrypted and it either times out or the boot process fails for volumes not marked as nofail.

Also, there were cases where it asked for the TPM PIN for each device, but in other cases it was enough to input it once, even tough I used the same PIN for each volume.

When not using a TPM PIN, no such issues arise.

Steps to reproduce the problem

Create /etc/crypttab.initramfs:

root    UUID=79b63d98-d912-43a9-8fd6-3d7df356f77a   none    tpm2-device=auto,fido2-device=auto
home    UUID=94365f72-7469-4157-bdac-b8fbaae7a909   none    nofail,tpm2-device=auto,fido2-device=auto
swap    UUID=203aacbb-cdee-4926-8616-f1eacddd74e3   none    nofail,tpm2-device=auto,fido2-device=auto

Create /etc/fstab:

   6   │ # Disk model: Samsung SSD 970 EVO Plus 500GB, Disk identifier: CFC935C3-0BE8-5946-9AC6-6FB928E2225C, /dev/mapper/root, LABEL=ROOT
   7   │ /dev/mapper/root    /           btrfs       rw,relatime,ssd,space_cache=v2,subvolid=5,subvol=/  0 0
   8   │ 
   9   │ # Disk model: Samsung SSD 970 EVO Plus 500GB, Disk identifier: CFC935C3-0BE8-5946-9AC6-6FB928E2225C, LABEL=EFI
  10   │ UUID=E45B-E805          /efi        vfat        rw,relatime,fmask=0137,dmask=0027,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro,nodev,nosuid,noexec   0 2
  11   │ 
  12   │ # Disk model: ADATA SX8200PNP, Disk identifier: D7FC80F5-0593-E24E-8AA2-BB4FEB8938DC, /dev/mapper/home, LABEL=HOME
  13   │ /dev/mapper/home    /home       btrfs       rw,auto,nofail,relatime,ssd,space_cache=v2,subvolid=5,subvol=/  0 0
  14   │ 
  15   │ # Disk model: Samsung SSD 970 EVO Plus 500GB, Disk identifier: CFC935C3-0BE8-5946-9AC6-6FB928E2225C, LABEL=XBOOTLDR
  16   │ UUID=7d24452a-d242-40ff-87c4-e3dccbfa74c5   /boot       ext4        rw,relatime,nodev,nosuid,noexec 0 2
  17   │ 
  18   │ # Disk model: LITEON CV3-DE256, Disk identifier: FFAFBE7D-A5D8-42B9-87EC-6D3C7A3E4992
  19   │ /dev/mapper/swap    none    swap    defaults,auto,nofail    0 0
  20   │ 
  21   │ # Disk model: WDC WD30EFRX-68E, Disk identifier: BE216705-2E5E-4F6B-9546-91B3D171F113, LABEL=system-backup
  22   │ UUID=71aafde9-6f3a-41d3-91b1-294023f88b83   /run/media/system/system-backup btrfs   nosuid,nodev,rw,auto,nofail,relatime,subvolid=5,subvol=/    0 0

Additional program output to the terminal or log subsystem illustrating the issue

No response

IPlayZed commented 11 months ago

What I realized is that it actually asks for the TPM2 PIN if set, but it displays to enter the FIDO2 PIN. (If I enter the TPM PIN, it accepts it, but it still prompts for the FIDO key's password.) Maybe there is some bad logic in code which determines the message to be displayed to the user?

dev-uhuru commented 3 months ago

Hi, I may have a variation on this issue. This is tested on an Arch VM with my main OS being Fedora.

My hope is to have:

SLOT TYPE    
   0 password
   1 tpm2
   2 fido2

With PINs set on both the TPM and my Yubikey. So, my root fs will usually unlock with TPM and when PCRs change (eg. kernel update, kernel cmdline, etc.), it can fall back to a Yubikey and only onto a recovery key if I lost my Yubikey. I have tried inverting the slots, eg 1 fido2 and 2 tpm2 without any change.

Currently, when I trip the TPM through adding option to the kernel cmdline or whatever, it will display:

Please enter LUKS2 token PIN # I enter the TPM PIN
Please enter LUKS2 token PIN # I enter the TPM PIN
Please enter LUKS2 token PIN # I enter the Yubikey PIN
Please enter TPM2 PIN # I enter the TPM PIN
Please enter security token PIN # I enter the Yubikey PIN

After initial investigations, it seems that the first 3 prompts are following this path:

  1. Try to unlock the TPM, there's a policy mismatch since the PCRs are different and this errors out
  2. Try to pass on the password to the FIDO2 key, which also fails since the PINs are different Errors are:
    systemd-tty-ask-password-agent[466]: Password query on /dev/tty1 finished successfully.
    systemd-cryptsetup[458]: Failed to unseal secret using TPM2: Operation not permitted
    systemd-cryptsetup[458]: Asking FIDO2 token for authentication.
    systemd-cryptsetup[458]: Please confirm presence on security token to unlock.
    systemd-cryptsetup[458]: PIN of security token incorrect.

    On the third attempt, systemd-cryptsetup cannot check the policies since the PIN given is that of the FIDO2 and it increments the DA counter in the TPM:

    systemd-tty-ask-password-agent[466]: Password query on /dev/tty1 finished successfully.
    systemd-cryptsetup[458]: WARNING:esys:src/tss2-esys/api/Esys_StartAuthSession.c:391:Esys_StartAuthSession_Finish() Received TPM Error
    systemd-cryptsetup[458]: ERROR:esys:src/tss2-esys/api/Esys_StartAuthSession.c:136:Esys_StartAuthSession() Esys Finish ErrorCode (0x0000098e)
    systemd-cryptsetup[458]: Failed to unseal secret using TPM2: State not recoverable

Then the prompts change to being more informative and the logic seems to try each token in turn instead of reusing the same PIN across tokens. This may be due to this RFE and first trying out cryptsetup plugins? I'll try to desactivate this to see if that makes any difference. Failing the first prompt while giving a bogus PIN gets to the result somewhat quicker.

There's a danger to lock out the Yubikey key as well (possibly other FIDO2 keys) since someone repeatedly entering the TPM PIN at the first prompt will always get the FIDO2 key tried with the same PIN. Yubikeys need to be unplugged after 3 wrong PINs, so in the test above, systemd fell back to asking for my password. However, with only 8 PIN failures allowed before being locked out of a Yubikey, this may be a more significant issue if I'm not missing anything.

That is seen with systemd 256 (256.4-1-arch)

Edit: It seems that inverting the slots does matter? I'm sure that systemd-cryptsetup was checking TPM/token 1 before FIDO/token 0 before but now I cannot reproduce this though I have wiped all slots and rebooted in between to be sure to have a clean slate. Perhaps I got mixed up between token ordering and keyslots...

This said, part of the issue above seems to be due to the fact that if the right PIN is given to the TPM with a policy mismatch, it gets prompted again after trying the Yubikey and if a wrong PIN is given to the TPM (the FIDO PIN), it does not get passed over to the Yubikey when the TPM errors out.

So two possible solutions for now: