Skip to content

Instantly share code, notes, and snippets.

@Agnoctopus
Last active November 22, 2023 01:45
Show Gist options
  • Select an option

  • Save Agnoctopus/745099bda01a8abacb9f3d0344e16762 to your computer and use it in GitHub Desktop.

Select an option

Save Agnoctopus/745099bda01a8abacb9f3d0344e16762 to your computer and use it in GitHub Desktop.
GSoC 2020 | Virtual U2F security key

GSoC 2020 | Virtual U2F security key

This summer, I had the opportunity to participate in the GSoC 2020 program within the QEMU organization on a project that interested me a lot.

The subject was 'Virtual U2F security key', and now that the GSoC is almost finished, it's time for me to summarize this project I worked on.

This GIST aims to provide a general description of the project, as well as the work that has been done to carry it out.

U2F rapid overview

U2F is an open authentication standard. It enables relying parties exposed to the internet to offer a strong second factor option for end user authentication.

The standard brings many advantages to both parties, client and server, allowing to reduce over-reliance on passwords, it increases authentication security and simplifies passwords.

The second factor is materialized by a device implementing the U2F protocol. Although there are different types of U2F devices depending on the transport used, in the project context, the USB transport was the one targeted, which give in case of a U2F security key, a USB HID device that implements the U2F protocol.

Project overview

The project idea came from Gerd Hoffmann who mentored me afterwards, and its realization follows the proposal I made few months ago.

The title of the project is 'Virtual U2F security key' and its goal is to provide dedicated support of U2F to qemu.

As a second factor token is materialized by a device, and that we were interested in the USB variant, integrating U2F support for qemu therefore involved writing a USB virtual device which presents a U2F security key to the guest.

Given this, we wanted two possible modes of operation for the U2F device:

  • emulated
  • passthrough

Passthrough mode

The passthrough mode consists of passing all requests made from the guest virtual U2F device to the physical security key connected to the host machine and vice versa.

However, this is already possible with host device assignment, but this type of passthrough detaches the device from the host system and give it to the guest. Thus, for a U2F device, this limits the possibilities of sharing the same security key on several guests.

The advantage of a dedicated passthrough is that we can do better, this allows us to have a U2F security key shared on several guests which is not possible with a simple host device assignment passthrough, and also, accessible from the host.

The passthrough mode also includes an autoscan which lets the device take the first U2F security key it finds on the host machine. Allowing to enjoy the passthrough mode very simply without configuration.

Emulated mode

The emulated mode consists in completely emulating the behavior of a U2F device through a software part. As some requests are sent from the guest virtual U2F device, the software part aims to respond to the guest as a real physical security key would. Libu2f-emu is used for this.

The advantage of emulated mode is that it allows anyone who does not have a security key, to enjoy the benefits of U2F just as a real device.

Libu2f-emu

The creation of libu2F-emu was also part of the project, as no existing library met our needs.

The purpose of libu2f-emu is to receive U2FHID packets and respond to them, in the same way a physical security key would.

The library is available here:

Project Features summary

The project allows guest U2F USB security keys that can operate in one of the two possible modes: either passthrough or emulated.

Given that, we can add U2F devices to the guest like this:

# Passthrough mode
$ ./qemu -usb -device u2f-passthru

# Emulated mode
$ ./qemu -usb -device u2f-emulated

In both modes, several ways of configuration are possible, each having their subtleties. This is summarized in docs/u2f.txt.

In the case of the example:

  • u2f-passthru: the device autoscans, and takes the first U2F device found on the host.
  • u2f-emulated: the device generates all the elements it needs for a single use of the lifetime of the device.

Note: Make sure to have a working libu2f-emu installed on the host in order to use u2f-emulated.

Project status

Qemu

All qemu patches have been merged after being reviewed and tested. They provide all the functionalities expected for the project.

You can see the first version of the patch series that introduces the U2F support to qemu:

With the change of build system to meson, the patch series had to be rebased on this arrival, as you can see here:

To have these features on a stable version of qemu, it will probably be necessary to wait for the next release, i.e. the 5.2 of qemu, which will be released in the coming months.

However, testing and viewing the project sources is now possible, as the patches have merged. Everything is available on the main branch of the project, just clone the qemu official repository.

Libu2f-emu

The u2f-emu library is fully functional for U2F emulation with USB transport, which is used as part of u2f support in qemu.

How it works

As said above, integrating U2F support for qemu involve writing a USB virtual device which presents a U2F security key to the guest.

However, given the two different operating modes, it is more correct to assign to each of these two modes its device that can be added to the guest.

This gives this correspondence:

  • emulated: u2f-emulated
  • passthrough: u2f-passthrough

Knowing that despite the differences between these two modes in their internal functioning, there is still a large common part which is found in particular in the interfacing with the guest.

That's why common characteristics between u2f-emulated and u2f-passthru are grouped in an abstract base device: u2f-key that is inherited by its two variants corresponding to the two modes u2f-emulated and u2f-passthrough.

Given this, we can divide the project into several parts:

  • Qemu:
    • u2f-key
    • u2f-passthrough
    • u2f-emulated
  • Libu2f-emu

Qemu

u2f-key

The u2f-key is the base device, it mainly takes care of the HID interfacing with guest.

On the one hand, it retrieves the guest U2FHID packets and transmits them to the variant associated according to the mode: u2f-passthru or u2f-emulated.

On the other hand, it provides the public API used by its variants to send U2FHID packets to the guest.

It plays the role of a messenger and does not pay attention to the implementation behind the mode it is dealing with.

u2f-passthru

The u2f-passthru inherits from u2f-key.

dTo work, it needs to be associated with a U2F hidraw that can be obtained in two different ways: either from the qemu command line or from the autoscan that it can perform.

The autoscan is performed using libudev with an enumeration of all the hidraw devices present on the host. The first device which happens to be a U2F device is taken to do the pass-through.

To ensure that a hidraw device is really corresponding to a U2F device, a check is performed. It consists to ensure the first values of the report descriptor (USAGE PAGE and USAGE) correspond to those of a U2F device.

u2f-emulated

The u2f-emulated inherits from u2f-key.

To work, an emulated U2F device must have different elements which can be given in different ways.

The different elements are:

  • one ec x509 certificate
  • the associated ec private key
  • the counter value
  • 48 bytes of entropy (random bits)

All this and the different configuration methods are detailed in docs/u2f.txt.

Libu2f-emu

As said before, the purpose of libu2f-emu is to receive U2FHID packets and respond to them, in the same way a physical security key would.

It works by implementing the U2F standard described by the specifications provided by the FIDO Alliance which describes the format of the U2FHID packets, the behavior that a U2F device must have and all that follows.

What remains to be done

As a whole, the project has been completed, everything is there and working properly. However, some points can be improved and others can be added to go further.

  • The u2f-passthru device could be brought to Windows. However, after a little study, it would take some effort. Indeed, Windows has a dedicated system API for U2F while Linux and its variants rely solely on HID. This would require parsing the HID packets as they arrive from the guest and then fetching U2F requests, extracting the information from them and call the right Windows API function. The reverse path consists in forging the U2F HID packets with the information returned by the function call and send them to the guest.

  • Different transports to U2F like NFC or BLUETOOTH are missing from libu2f-emu, and could be implemented.

Final notes

It all started a few months ago, following the proposal I made for the 'Virtual U2F security key' subject, suggested and mentored by Gerd Hoffmann.

The GSoC has been for me a great experience, during which I had the opportunity to participate in the incredible world of open source within Qemu, which is a project that I particularly like. All this on a very interesting subject.

This program has given me a lot of positive and I am happy to have been able to participate.

I would like to thank Google for the organization, Qemu for allowing me to work on this subject and more particularly Gerd Hoffmann for his mentoring.

This Gest is also available identically in the form of a post on my blog: https://agno.fr/2020/08/27/gsoc-2020-virtual-U2F-security-key.html (IPv6 only).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment