darconeous / CCIDU2F

SmartCard U2F Adapter for macOS
Apache License 2.0
13 stars 3 forks source link

Migrate to HIDDriverKit #2

Open darconeous opened 4 years ago

darconeous commented 4 years ago

In the next version of macOS (10.16, or Catalina+1), all kexts that use deprecated APIs will likely not load by default. The solution is to migrate to HIDDriverKit.

From Apple developer support:

All KPIs in IOHIDFamily are deprecated. Clients should use HIDDriverKit instead.

Instead of relying on SoftU2F's kext as we are currently, ideally we would be able to use HIDDriverKit directly.

For reference, the issue tracking this for SoftU2F is github/SoftU2F#75.

jaredvacanti commented 4 years ago

I'd like to help with this development, although I admit this would be my first attempt at an Apple driver.

I use the project to register secondary devices (javacards) on accounts that are secured with U2F. Yubikeys are registered as the primary hardware device and, as of today, they work across platforms. So CCIDU2F is a great tool for disaster recovery on those yubikey accounts.

But the disasters will probably come when future macOS versions are available, so I'd like to help prep for that :)

I've read through some Apple pages on HIDDriverKit. Do you know what parts of SoftU2F need to be re-interfaced to HIDDriverKit? Or what parts of CCIDU2F rely on it so SoftU2F installation can be avoided entirely?

darconeous commented 4 years ago

To be honest, I don't yet have a good idea of what all would be involved. I haven't really looked closely at the source to either the SoftU2F driver kext or the associated client library (other than to make a few minor changes to allow it to be torn down and brought back up more easily).

All that being said, it seems like most of the U2F HID logic (the stuff described here) is in the SoftU2F driver library (the part of SoftU2F source code that I included in this project). The path of least resistance likely involves retrofitting that library to use HIDDriverKit instead of their custom SoftU2F Kext.

On the other side, I can't even find a decent example project using DriverKit, much less an example project using HIDDriverKit.

I really lucked out that GitHub had written SoftU2F. Without their driver and library, I likely wouldn't have bothered writing CCIDU2F.

jaredvacanti commented 4 years ago

Thanks again for all your input across projects - I would be making little to no progress otherwise!

I've tracked down some additional resources from Apple on making the kext to system extension transition:

From the article, it looks like system extensions are now bundled with the app directly. I'm looking into the new entitlement grant process with Apple for development & production use, as well. Some chatter on the developer forums says it could be a bit of a pain.

Either way, I'll attempt the replacement of SoftU2F's kexts with HIDDriverKit calls (the retrofitting recommendation). It looks like these are the source files that need adjustment:


Bigger picture -- and I may just need to keep researching -- is the current kext from SoftU2F to allow HID devices to communicate with the browser (the FIDO U2F HID Protocol)? And in the SoftU2F case, the HID device is emulated by software? (Are Bluetooth, NFC, and HID devices all considered CTAP2 communication devices now?)

Does the HID Driver not satisfy NFC connections? There do seem to be some slight differences. From the FIDO U2F NFC Protocol document:

  1. Framing The NFC protocol shall not use any additional framing (unlike the USB HID protocol, for example). Instead, messages sent to an NFC authenticator shall follow the U2F raw message format as defined in [U2FRawMsgs] in the bibliography. In the NFC protocol, either short or extended length APDU encoding is allowed.

I think I have enough direction to keep going, but please let me know if you think a different route would be more fruitful!

darconeous commented 4 years ago

is the current kext from SoftU2F to allow HID devices to communicate with the browser (the FIDO U2F HID Protocol)?

Not exactly. USB-based FIDO tokens are already HIDs—the browsers can communicate with them just fine. SoftU2F works by creating a virtual HID that is controlled by software instead of hardware.

And in the SoftU2F case, the HID device is emulated by software?

Yes.

Are Bluetooth, NFC, and HID devices all considered CTAP2 communication devices now?

Whether a FIDO device uses CTAP1 or CTAP2 is independent of the transport protocol. There are defined protocols for how to use CTAP1 and/or CTAP2 over Bluetooth, NFC, and USB-HID.

As far as the authenticator device is concerned, all FIDO U2F tokens support only CTAP1. Most FIDO2 tokens support CTAP1 in addition to CTAP2, but this is not required.

Does the HID Driver not satisfy NFC connections?

It's not entirely clear to me what you are asking.

NFC devices themselves are not HIDs. CCIDU2F enables a FIDO authenticator that supports CTAP1 over NFC (or anything that looks like a smart-card to the OS, really) to appear as a virtual HID CTAP1 authenticator, allowing it to be used transparently with supported web browsers.

It would be straightforward to also add support for CTAP2 to CCIDU2F, I just haven't had the motivation to implement that yet.

CTAP1 uses APDU framing, so CTAP1 messages can be sent natively over NFC. CTAP2 messages use a custom framing, and so they must be put inside of a special APDU before being sent over NFC. But we aren't concerned with CTAP2 at this point, so I'll stop making things confusing. 😊

There do seem to be some slight differences. From the FIDO U2F NFC Protocol document:

  1. Framing The NFC protocol shall not use any additional framing (unlike the USB HID protocol, for example). Instead, messages sent to an NFC authenticator shall follow the U2F raw message format as defined in [U2FRawMsgs] in the bibliography. In the NFC protocol, either short or extended length APDU encoding is allowed.

Yeah, USB doesn't use APDUs, so you can't send CTAP1 frames (or CTAP2 frames) natively over USB. FIDO could have used the CCID protocol, but that was really meant for a different use case (reading smart cards, where only a single process can access the card at a time). So FIDO came up with their own USB transport for U2F/CTAP1. For FIDO2, they extended it slightly to support CTAP2.

darconeous commented 4 years ago

Either way, I'll attempt the replacement of SoftU2F's kexts with HIDDriverKit calls (the retrofitting recommendation). It looks like these are the source files that need adjustment:

...

Sounds great!

jaredvacanti commented 4 years ago

CCIDU2F enables a FIDO authenticator that supports CTAP1 over NFC (or anything that looks like a smart-card to the OS, really) to appear as a virtual HID CTAP1 authenticator, allowing it to be used transparently with supported web browsers.

I think I have a better idea of what role this project plays in the FIDO flow:

SoftU2F has the benefit of being code-signed by GitHub. Putting the code from SoftU2FLib in this project would currently require disabling system integrity, although I'm this seems less relevant in the world of System Extensions. Then, CCIDU2F translates the CCID interface (contact or contactless smartcard or NFC Tag) to the Virtual HID Device, which can communicate with Chrome.

I've looked at this FIDO specs a bit more. Is this project needed for u2f-javacard on an NFC-capable JavaCard if the OS (whether macOS or Linux) is configured with an NFC Reader? Can modern versions of Chrome use the NFC directly instead of using the CCIDU2F -> Virtual HID method? From the specs it looks like HID, NFC, and Bluetooth are supported, with HID and NFC with the most browser support.

It would be straightforward to also add support for CTAP2 to CCIDU2F, I just haven't had the motivation to implement that yet.

Would you expect a Yubikey 5 NFC, which I suspect is a FIDO2 CTAP2 device, to not work over NFC with CCIDU2F? Should it fall back appropriately? Or should the browser be able to communicate with the Yubikey over NFC natively?

It does appear to me that this driver will need updated in any scenario in order to support a contact card running u2f-javacard, which could only connect via contact reader USB CCID.

darconeous commented 4 years ago

Can modern versions of Chrome use the NFC directly instead of using the CCIDU2F -> Virtual HID method?

NFC is not (yet?) supported by Chrome on a Mac. It is supported by Chrome on Android. I have not tested NFC support in Chrome on Windows or Linux.

From the specs it looks like HID, NFC, and Bluetooth are supported, with HID and NFC with the most browser support.

I have not come across any browser on a Mac that supports NFC/CCID. They all seem to only support HID.

Would you expect a Yubikey 5 NFC, which I suspect is a FIDO2 CTAP2 device, to not work over NFC with CCIDU2F?

A Yubikey 5 NFC will work with CCIDU2F with CTAP1/U2F flows only. This means you could potentially use it with your Google Account, but not your Microsoft account (which requires features that CTAP1 cannot satisfy).

It does appear to me that this driver will need updated in any scenario in order to support a contact card running u2f-javacard, which could only connect via contact reader USB CCID.

I think it's worth pointing out that there is no official Apple NFC API on macOS. If a browser ends up adding their own support for "NFC" authenticators, that support would likely apply to all CCID devices. They would basically be doing something similar to what I'm doing in CCID, except without the drivers and HID stuff.

I have been told that Windows 10 already does what CCIDU2F does for macOS, but I haven't experimentally verified this.