Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for systemd-cryptenroll style pins (FIDO2, TPM) #96

Closed
AidanGG opened this issue Aug 7, 2021 · 30 comments
Closed

Support for systemd-cryptenroll style pins (FIDO2, TPM) #96

AidanGG opened this issue Aug 7, 2021 · 30 comments

Comments

@AidanGG
Copy link

AidanGG commented Aug 7, 2021

The kernel parameter rd.luks.options=fido2-device=auto used for unlocking a disk through a keyslot enrolled in by systemd-cryptenroll with its FIDO2 functionality does not seem to be supported, but I have confirmed that it works with mkinitcpio and the sd-encrypt hook.

@AidanGG AidanGG changed the title Support for systemd-cryptenroll Support for systemd-cryptenroll (FIDO2, TPM) Aug 7, 2021
@anatol anatol changed the title Support for systemd-cryptenroll (FIDO2, TPM) Support for systemd-cryptenroll style pins (FIDO2, TPM) Aug 8, 2021
@anatol
Copy link
Owner

anatol commented Aug 8, 2021

It sounds like a good idea to support metadata generated by systemd-cryptenroll.

I have a Yubikey4 token and it looks like it does not support FIDO2 protocol. What would be a good token with FIDO2 support? Yubikey5? Or there are other options? Is there any good software emulator for FIDO2 token device?

@AidanGG
Copy link
Author

AidanGG commented Aug 8, 2021

I am using the Yubikey 5 with FIDO2 for my mkinitcpio-based setup. I believe the open solutions such as the SoloKeys should also work but I have not used it. I am not aware of any software emulators, unfortunately.

@anatol
Copy link
Owner

anatol commented Aug 11, 2021

Also note that TPM2 binding is supported via clevis mechanism e.g. clevis luks bind -d /dev/nvme0n1p2 tpm2 '{}'

@anatol
Copy link
Owner

anatol commented Sep 8, 2021

I finally got a YubiKey5 with FIDO2 support and checked how systemd-cryptenroll uses it for partition encryption.

Got an initial version of systemd-cryptenroll FIDO2 support. Integration tests for systemd-cryptenroll pass. Pushed the implementation into wip branch. @AidanGG if you interested in FIDO2 support please give it a try and let me know if it works for you.

Booster does not require any extra steps on enrollment stage. It will automatically detect partitions enrolled with systemd and try to unlock it using a FIDO2 device.

@AidanGG
Copy link
Author

AidanGG commented Sep 8, 2021

Sorry to be a pain, I happened to use blake2b-512 as the digest hash for pbkdf2 and it appears that booster does not support it. So unfortunately I can't test whether the FIDO2 part works right now.

Here is my luksDump (keyslot 0 is a recovery text key enrolled by systemd-cryptenroll, keyslot 1 is the FIDO2 key enrolled by systemd-cryptenroll):

LUKS header information
Version:       	2
Epoch:         	23
Metadata area: 	16384 [bytes]
Keyslots area: 	16744448 [bytes]
UUID:          	xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Label:         	(no label)
Subsystem:     	(no subsystem)
Flags:       	allow-discards no-read-workqueue no-write-workqueue

Data segments:
  0: crypt
	offset: 16777216 [bytes]
	length: (whole device)
	cipher: aes-xts-plain64
	sector: 4096 [bytes]

Keyslots:
  0: luks2
	Key:        512 bits
	Priority:   normal
	Cipher:     aes-xts-plain64
	Cipher key: 512 bits
	PBKDF:      pbkdf2
	Hash:       sha512
	Iterations: 1000
	Salt:       xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
	            xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
	AF stripes: 4000
	AF hash:    sha512
	Area offset:32768 [bytes]
	Area length:258048 [bytes]
	Digest ID:  0
  1: luks2
	Key:        512 bits
	Priority:   normal
	Cipher:     aes-xts-plain64
	Cipher key: 512 bits
	PBKDF:      pbkdf2
	Hash:       sha512
	Iterations: 1000
	Salt:       xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
	            xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
	AF stripes: 4000
	AF hash:    sha512
	Area offset:290816 [bytes]
	Area length:258048 [bytes]
	Digest ID:  0
Tokens:
  0: systemd-recovery
	Keyslot:    0
  1: systemd-fido2
	Keyslot:    1
Digests:
  0: pbkdf2
	Hash:       blake2b-512
	Iterations: 1000
	Salt:       xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
	            xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
	Digest:     xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
	            xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
                    xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
	            xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx

@anatol
Copy link
Owner

anatol commented Sep 8, 2021

Thanks for discovering it! The problem probably comes from luks.go and I'll be glad to fix it. Could you please give me the exact error message you've got from booster?

@AidanGG
Copy link
Author

AidanGG commented Sep 8, 2021

The message says:

Enter passphrase for cryptroot:   Unlocking...
Unknown digest hash algorithm: blake2b-512

Thanks!

Edit: It appears that blake2b support is included in go/crypto but I don't know enough about Go to know how much this helps: https://pkg.go.dev/golang.org/x/[email protected]/blake2b

anatol added a commit that referenced this issue Sep 8, 2021
This update brings support for blake2b/blake2s digests.

Issue #96
@anatol
Copy link
Owner

anatol commented Sep 8, 2021

Thank you for the information. It was indeed a limitation of luks.go library. It turns out that cryptsetup 2.4.0 added support for blake2b/blake2s hash functions. Though at my system cryptsetup uses openssl backend that limits support to blake2b-512 and blake2s-256 only.

Also golang crypto library does not support blake2s-160 blake2b-256 blake2b-384.

But in your case you need blake2b-512 and it should be fixed now. Please pull updates fromwip branch and give it a try one more time.

Thank you for your time!

@AidanGG
Copy link
Author

AidanGG commented Sep 8, 2021

It appears that dealing with the systemd-fido2 token is failing somehow, and that Booster falls back to asking for a password (for which only my slot 0 with a recovery key could conceivably work). Are there some modifications I can make to the PKGBUILD to enable debug logs?

Edit: the blake2b-512 issue seems fixed, my error message now is Incorrect passphrase, please try again which appears to be during the fallback to password entry after tokens have been tried.

@anatol
Copy link
Owner

anatol commented Sep 8, 2021

Are there some modifications I can make to the PKGBUILD to enable debug logs?

No need to rebuild the package. To enable debug log please add booster.debug to the kernel boot params. The debug log will be printed to screen and to dmesg.

@AidanGG
Copy link
Author

AidanGG commented Sep 9, 2021

I think the most relevant output is
[ 3.216305] booster: recovering systemd-fido2 token #1 failed: open /sys/class/hidraw/: no such file or directory

Is there anything I need to add to extra-files in my booster.yaml? Or any other sort of configuration?

@anatol
Copy link
Owner

anatol commented Sep 10, 2021

open /sys/class/hidraw/: no such file or directory means that hidraw driver is not loaded.

  • Do you have your Yubikey inserted at the time you boot your system?
  • Do you see any hid events or log entries before and after the error? dmesg | grep hid would help to answer this question.

@AidanGG
Copy link
Author

AidanGG commented Sep 10, 2021

I have tried with the Yubikey inserted since before boot (though the mkinitcpio-based setup works even after the key is inserted later).

It appears that the hid module is loaded after:

[ 3.170078] booster: recovering systemd-fido2 token #1 failed: open /sys/class/hidraw/: no such file or directory
[ 3.369885] booster: modalias usb:xxx matched module usbhid
...
[ 3.403495] booster: loading module hid
[ 3.403495] hid: raw HID events driver (C) Jiri Kosina

@anatol
Copy link
Owner

anatol commented Sep 10, 2021

Indeed, LUKS partition detected and parsed faster than Yubikey initialized by kernel. I just added a quick workaround to handle this situation (2 seconds wait time before checking for Yubikeys) and pushed it to wip branch. It will help you to test systemd-fido2 unlocking functionality.

Meanwhile I am thinking about implementing better synchronization mechanism that is tracked here #100 . It will help to avoid such wait time and perform operations with greater parallelism which will make unlocking even faster.

@AidanGG
Copy link
Author

AidanGG commented Sep 10, 2021

Thanks, seems to be some progress. After adding fido2-assert to extra_files, I now get

HID hidraw1 supports FIDO, trying it to recover the password

then a pause. I have a PIN set for my key which systemd-cryptenroll required through its --fido2-with-client-pin=yes default setting, but it appears that PIN input hasn't been implemented? Anything I type is non-obfuscated and appears in plaintext on screen. If I type my PIN and tap the Yubikey button I then get:

recovered password from systemd-fido2 token #1
password from systemd-fido2 token #1 does not match

and then it falls back to normal password entry.

anatol added a commit that referenced this issue Sep 11, 2021
This update brings support for blake2b/blake2s digests.

Issue #96
@anatol
Copy link
Owner

anatol commented Sep 12, 2021

I tried enabling PIN with my Yubikey 5 NFC but it says my unit does not support it :(

sudo systemd-cryptenroll --fido2-device=auto --fido2-with-client-pin=yes --fido2-with-user-presence=yes --fido2-with-user-verification=yes /dev/loop2
🔐 Please enter current passphrase for disk /dev/loop2: ***                     
Requested to lock with PIN, but FIDO2 device /dev/hidraw6 does not support it, disabling.
Locking with user verification test requested, but FIDO2 device /dev/hidraw6 does not support it, disabling.
Initializing FIDO2 credential on security token.
👆 (Hint: This might require confirmation of user presence on security token.)

@AidanGG
Copy link
Author

AidanGG commented Sep 13, 2021

I believe that you have to set the Yubikey's PIN for FIDO2 before enrolling with systemd-cryptenroll. You can use yubikey-manager-qt from Arch repos and set it in the FIDO2 application.

Edit: also some extra docs on Yubikey FIDO2 PINs: https://support.yubico.com/hc/en-us/articles/4402836718866-Understanding-YubiKey-PINs

@anatol
Copy link
Owner

anatol commented Sep 13, 2021

Thanks @AidanGG for the tip. I use Yubikey Personalization tool and it did not allow to configure FIDO2 options. But yubikey-manager-qt does allow.

I was able to enroll systemd-fido2 token and now I am trying to assert (compute the key) using fido2-assert tool from yubikey. But it is not clear if it supports PIN. Looking at the sources https://github.com/Yubico/libfido2/blob/master/tools/assert_verify.c I do not see where it handles PIN requirement. I guess I need to file an issue to libfido2 or find another tool for FIDO2 assertion.

@AidanGG
Copy link
Author

AidanGG commented Sep 13, 2021

No problem. So I guess systemd uses the libfido2 library directly to handle PIN entry in the sd-encrypt hook of mkinitcpio, rather than using the fido2-assert executable? In that case I wonder if there are any Go bindings to libfido2 that could be used to implement this part in Booster.

@anatol
Copy link
Owner

anatol commented Sep 13, 2021

It turns out fido2-assert has a way to deal with PINs though not in very obvious way.

Added a commit to wip branch that implements Yubikey FIDO2/PIN support. It also adds an integration test-case for this feature. Please take a look.

@AidanGG
Copy link
Author

AidanGG commented Sep 14, 2021

It now appears that Booster is not loading the hidraw driver. I get

[    5.219847] booster: recovering systemd-fido2 token #1 failed: open /sys/class/hidraw/: no such file or directory

and then there is no longer the message booster: loading module hid. It is only after I unlock the LUKS volume after Booster falls back to my recovery key slot that the hid driver is loaded ([ 30.679836] hid: raw HID events driver (C) Jiri Kosina).

@anatol
Copy link
Owner

anatol commented Sep 14, 2021

hmm, luks opening runs in a separate goroutine and should not block device enumeration...

@anatol
Copy link
Owner

anatol commented Sep 21, 2021

@AidanGG I would like to return back to it and debug the HID driver loading issue.

Could you please pull the latest wip branch and check if you still see this issue?

@AidanGG
Copy link
Author

AidanGG commented Sep 21, 2021

Thanks @anatol, latest wip build (commit deb6745) does work as expected, but I had to add modules: hid to my Booster config. Otherwise it fails in the same way as build e825838 (which I did not think to test with modules: hid in the config, apologies). Perhaps the hid module should be included by default?

In my mkinitcpio-based setup, I use the kernel parameter rd.luks.options=fido2-device=auto to target the LUKS key slot for the FIDO2 token, which causes the prompt to wait until a FIDO2 device appears, whereas Booster will fallback to password input. Would it be possible to add some parameters for Booster such as rd.luks.keyslot and rd.luks.token to target a particular keyslot or token without falling back to a different slot/token?

@anatol
Copy link
Owner

anatol commented Sep 21, 2021

Thank you @AidanGG for confirming it. It is really great to hear that the systemd-fido2 functionality works for you.

modules: hid

It is totally valid workaround for your hid driver issue. But I think that booster should detect hid devices (like Yubikey) automatically without any extra user configuration. And then wait till hid drivers start enumerating. I am going to look at this hid device enumeration issue as a part of #100 refactoring.

Would it be possible to add some parameters for Booster such as rd.luks.keyslot and rd.luks.token to target a particular keyslot or token without falling back to a different slot/token?

The request sounds reasonable and it might help in case if there multiple slots/tokens at a LUKS device. Could you please file a separate ticket to track it independently?

@anatol
Copy link
Owner

anatol commented Sep 24, 2021

The systemd-fido2 and systemd-tpm handling is implemented. So I am closing this issue.

The 'missing hid driver' will be resolved as a part of #100 refactoring.

@anatol anatol closed this as completed Sep 24, 2021
@AidanGG
Copy link
Author

AidanGG commented Sep 25, 2021

Thank you @anatol, I just realised that systemd-cryptenroll can also enrol a PKCS#11 token with --pkcs11-token-uri=URI which might also be good to have support for, but I personally don't have a use for it. A Yubikey can be used as a PKCS#11 token through the Yubikey's PIV applet (for development purposes, since end users with a Yubikey should probably opt for FIDO2 here instead).

@anatol
Copy link
Owner

anatol commented Oct 5, 2021

Does anybody have an experience with Yubikey+PKCS11? I would like to implement it at booster and I need some here here.

Booster needs a way to communicate with the pkcs11 device using some command-line tool and perform the same operation as systemd's code does.

Here is what I have

➜  ~ sudo pkcs11-tool --module /usr/lib/libykcs11.so --show-info                                                        
[sudo] password for anatol: 
Cryptoki version 2.40
Manufacturer     Yubico (www.yubico.com)
Library          PKCS#11 PIV Library (SP-800-73) (ver 2.20)
Using slot 0 with a present token (0x0)

Now I am trying to use systemd-cryptsetup and it fails:

sudo systemd-cryptenroll --pkcs11-token-uri=auto /dev/loop0
No suitable PKCS#11 tokens found.

So it is not clear for me what is going on here. Is there some pkcs11 specific configuration need to be done upfront?

@AidanGG
Copy link
Author

AidanGG commented Oct 6, 2021

Do you have to generate PKCS#11 RSA keys on the Yubikey with yubico-piv-tool (available on AUR) first? Sorry I can't be of much help here since I don't make use of the PKCS#11 app.

anatol added a commit that referenced this issue Oct 25, 2021
This helps to discover Yubikeys when they are inserted *after* boot
process started. In such case the system gets udev "add" event that been
proccesed by the listener. It helps to fix issue mentioned in #96.
@anatol
Copy link
Owner

anatol commented Oct 25, 2021

@AidanGG I added a way to list & enumerate HID devices concurrently. It means that Yubikeys should be detected even if they are inserted after the boot process has started.

It should also help you with your issue mentioned earlier when hid module requires some time to load and Yubikeys are not initially listed. You do not need hid module workaround in your config anymore.

I pushed the change to wip branch. @AidanGG please try it and let me know if you still see the issue.

anatol added a commit that referenced this issue Nov 2, 2021
This helps to discover Yubikeys when they are inserted *after* boot
process started. In such case the system gets udev "add" event that been
proccesed by the listener. It helps to fix issue mentioned in #96.
anatol added a commit that referenced this issue Nov 2, 2021
This helps to discover Yubikeys when they are inserted *after* boot
process started. In such case the system gets udev "add" event that been
proccesed by the listener. It helps to fix issue mentioned in #96.
anatol added a commit that referenced this issue Nov 3, 2021
This helps to discover Yubikeys when they are inserted *after* boot
process started. In such case the system gets udev "add" event that been
proccesed by the listener. It helps to fix issue mentioned in #96.
anatol added a commit that referenced this issue Nov 3, 2021
This helps to discover Yubikeys when they are inserted *after* boot
process started. In such case the system gets udev "add" event that been
proccesed by the listener. It helps to fix issue mentioned in #96.
anatol added a commit that referenced this issue Nov 13, 2021
This helps to discover Yubikeys when they are inserted *after* boot
process started. In such case the system gets udev "add" event that been
proccesed by the listener. It helps to fix issue mentioned in #96.
anatol added a commit that referenced this issue Nov 14, 2021
This helps to discover Yubikeys when they are inserted *after* boot
process started. In such case the system gets udev "add" event that been
proccesed by the listener. It helps to fix issue mentioned in #96.
anatol added a commit that referenced this issue Nov 30, 2021
This helps to discover Yubikeys when they are inserted *after* boot
process started. In such case the system gets udev "add" event that been
proccesed by the listener. It helps to fix issue mentioned in #96.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants