Virtual U2F Passthrough freeze

30 views
Skip to first unread message

Adriano Di Luzio

unread,
Jul 29, 2025, 1:03:20 PMJul 29
to crosvm-dev
Hi all!

I am playing with Virtual U2F Passthrough with a Yubikey on a Chromebook, through Crostini/termina.

Here is the setup:

0. plug the yubikey in
1. vmc key-attach termina /dev/hidraw10
2. vmc start termina (to SH into termina)
3. add the hidraw device to the lxc container 

Now in the container I can correctly list credentials, e.g. ssh-keygen -K.

Unfortunately, I can't produce any attestation. When I try, I insert the PIN, the yubikey blinks, and then the process freezes.

I have been doing some experiments through go-libfido2 and it seems that it freezes at different points of the protocol. In a run it got to asking the device to generate credentials, in another it blocked when trying to open the device, etc etc.

Anybody knows what's going on? I _think_ it's a bug in crosvm, but haven't had a chance to try with another VM type, only with termina.

Here are logs of a run where it hangs, in case they are useful:

[I] aldur@lxc-nixos ~/go-libfido2 (master)> FIDO_DEBUG=1 FIDO2_EXAMPLES=1 go test -v -run ExampleDevice_MakeCredential
=== RUN   ExampleDevice_MakeCredential
2025/07/29 18:21:42 [DEBG] Finding devices...
run_manifest: found 1 hid device
run_manifest: found 0 nfc devices
list_readers: SCardListReaders 0x8010002e
fido_pcsc_manifest: list_readers 0x8010002e
run_manifest: found 0 pcsc devices
2025/07/29 18:21:42 Using device: &{Path:/dev/hidraw0 ProductID:-3632 VendorID:6353 Manufacturer: Product:HID 18d1:f1d0}
before opening device
fido_tx: dev=0x3c6687a0, cmd=0x06
fido_tx: buf=0x3c6687a0, len=8
0000: da e1 21 c3 98 38 32 eb
fido_rx: dev=0x3c6687a0, cmd=0x06, ms=-1
rx_preamble: buf=0x7ffb088838, len=64
0000: ff ff ff ff 86 00 11 da e1 21 c3 98 38 32 eb 0b
0016: ed 10 9b 02 05 04 03 05 00 00 00 00 00 00 00 00
0032: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
rx: payload_len=17
fido_rx: buf=0x3c6687a8, len=17
0000: da e1 21 c3 98 38 32 eb 0b ed 10 9b 02 05 04 03
0016: 05
fido_dev_get_cbor_info_tx: dev=0x3c6687a0
fido_tx: dev=0x3c6687a0, cmd=0x10
fido_tx: buf=0x7ffb088890, len=1
0000: 04
fido_dev_get_cbor_info_rx: dev=0x3c6687a0, ci=0x3c677f30, ms=-1
fido_rx: dev=0x3c6687a0, cmd=0x10, ms=-1

Adriano Di Luzio

unread,
Aug 3, 2025, 11:39:15 PMAug 3
to Federico (Morg) Pareschi, crosvm-dev
Hey Morg, thanks for the quick answer!

The workflow I am trying is very simple: SSH to a remote host through an SSH key stored on a Yubikey. The next thing would be to use `age` and its Fido2 plugin to decrypt blobs encrypted with a Fido2 key.

I went through your same line of thinking and tried figuring out whether the bug could be due to the `termina` kernel and/or the container:

- As for the kernel, it _seems_ that it was compiled with all flags required in the documentation (I checked `cat /proc/config.gz`). It is also possible to boot termina with a custom kernel, if you have other suggestions on how to try that.
- As for the container, I modified the `lxc` config to enable privileged, unrestricted access to the underlying VM devices. The result was exactly the same.

To try outside of ChromeOS I'll need to figure out how to get a Linux desktop, unless there's a way to enable passthrough from macOS (which doesn't seem to expose /dev/hidraw).

---

The use case I have in mind is to leverage Chromebooks to build a trustworthy computing base through ChromeOS + Crostini, which provide good defense in depth and mitigate some of the most obvious attack vectors I see these days -- where attackers target devs not through phishing but through RCE in code libraries, samples, etc.

To implement this, the idea is to ship Crostini containers (I am using NixOS, but could really be anything) that provide a pre-configured environment _without_ any secrets. Yubikeys or other hardware tokens do the rest.

So far, I can use Yubikeys through `vmc usb-attach` and the PIV applet. It works OK-ish, but acquires an exclusive lock on the key that prevents it from working in the ChromeOS browser (e.g. for passkeys). The UX is not that great.

As you pointed out, the industry has moved to Fido2 -- which would allow sharing the key between ChromeOS and Linux. It would also remove a bunch of moving parts on the Linux side because of the built-in support in SSH clients for Fido2 keys (instead of going through something like pcscd.

I discovered support for U2F while poking around in `vmc` and decided to give it a try. I suspected it was not really supported given the lack of documentation and code samples around. I wonder _why_ vmc exposes it and what was the intended use case.

---

Long story short: it would be great to add Fido2 support, maybe more people would find it useful as well. I am not sure how big of a lift that would be. I'll take a look and poke around at the source code as it might make for a nice side project, but I don't  have my hopes up that I'll manage to find enough time to make it happen myself :)

Best,
A

On Wed, Jul 30, 2025 at 2:02 AM Federico (Morg) Pareschi <mo...@google.com> wrote:
Hey, it's nice to see there is some interest in trying out this feature. I originally implemented it but it hasn't been fully tested or deployed for actual production work so it is entirely possible that there are bugs and issues. Also it should only cover the usage for fido1/u2f and does not (yet? ever?) support the fido2 protocol. (Un)fortunately most of the industry has moved on to fido2 but I currently do not have plans to continue work on implementing fido2 support in the near future at least (but someone else might want to take a look at it, I don't mind reviewing code in crosvm about it) as I have been working on other things. 

As a note, most of my tests when implementing the virtual security key feature were done on crosvm itself in a standalone debian VM, and not directly on crostini/termina. It is entirely possible that some of these failures are due to specific kernel versions or because of how the container works, I am not 100% sure. If you have a specific workflow you want to use and test, I'd recommend trying on a standalone crosvm instance (possibly on your desktop PC, not a chromebook) and see if that works. If it does, then we can more easily figure out where the failures are.

Cheers,
Morg.

--
You received this message because you are subscribed to the Google Groups "crosvm-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to crosvm-dev+...@chromium.org.
To view this discussion visit https://groups.google.com/a/chromium.org/d/msgid/crosvm-dev/86175cd1-f26e-4299-a1e9-a7c5beee674dn%40chromium.org.


--
Google Logo
Morg
Software Engineer - ChromeOS
mo...@google.com
Just call me Morg, it's fine :)
Leave anonymous feedback at go/morg-anon-feedback

Federico (Morg) Pareschi

unread,
Aug 3, 2025, 11:39:16 PMAug 3
to Adriano Di Luzio, crosvm-dev
Hey, it's nice to see there is some interest in trying out this feature. I originally implemented it but it hasn't been fully tested or deployed for actual production work so it is entirely possible that there are bugs and issues. Also it should only cover the usage for fido1/u2f and does not (yet? ever?) support the fido2 protocol. (Un)fortunately most of the industry has moved on to fido2 but I currently do not have plans to continue work on implementing fido2 support in the near future at least (but someone else might want to take a look at it, I don't mind reviewing code in crosvm about it) as I have been working on other things. 

As a note, most of my tests when implementing the virtual security key feature were done on crosvm itself in a standalone debian VM, and not directly on crostini/termina. It is entirely possible that some of these failures are due to specific kernel versions or because of how the container works, I am not 100% sure. If you have a specific workflow you want to use and test, I'd recommend trying on a standalone crosvm instance (possibly on your desktop PC, not a chromebook) and see if that works. If it does, then we can more easily figure out where the failures are.

Cheers,
Morg.

On Wed, 30 Jul 2025 at 02:03, Adriano Di Luzio <adrian...@gmail.com> wrote:
--
You received this message because you are subscribed to the Google Groups "crosvm-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to crosvm-dev+...@chromium.org.
To view this discussion visit https://groups.google.com/a/chromium.org/d/msgid/crosvm-dev/86175cd1-f26e-4299-a1e9-a7c5beee674dn%40chromium.org.

Adriano Di Luzio

unread,
Aug 4, 2025, 12:04:34 PMAug 4
to crosvm-dev, Federico (Morg) Pareschi
Hey all! 

Just following up on this. 
It is likely due to being FIDO2 (as in, not U2F). 
I played around with libu2f-{server,host} (https://github.com/Yubico/libu2f-server) in the same setup (Crostini + Yubikey) and I could correctly register and authenticate.

I still haven't gotten around to a Linux box to try outside of Crostini.

Best,
A

Federico (Morg) Pareschi

unread,
Aug 4, 2025, 7:56:24 PMAug 4
to Adriano Di Luzio, crosvm-dev
Thank you for the follow up, really great investigation and it's good to know what the issue is. As suspected, FIDO2 is not supported so it's unfortunate that it manages to crash the protocol/VM when used. 

I don't have time to work on this as lately I've been working on other projects, but I wouldn't mind reviewing code changes or fixes or anything if you want to take a stab at it. I think theoretically it would be possible to implement something similar to u2f via HIDraw but for FIDO2, however I haven't looked too deep in the protocol. There are a few things that might be tricky as the behavior seems to be a bit more complicated (u2f is relatively simple). 
Reply all
Reply to author
Forward
0 new messages