OpenSK icon indicating copy to clipboard operation
OpenSK copied to clipboard

Implementing OpenSK-based FIDO2 emulator for QEMU

Open egor-duda opened this issue 2 years ago • 10 comments

I've made a quick-and-dirty prototype of virtual FIDO2 authenticator for QEMU using OpenSK application. The purpose is similar to #288, but instead of creating a CTAP library and linking it into QEMU, I've patched QEMU to add a fido2 device, which uses socket-connected chardev. Then I've modified main OpenSK application to listen on a unix socket and, after connection from QEMU, to process all CTAP requests/responses via that socket connection.

To go beyond prototype, I suppose I have to:

  1. Create separate NonEmbeddedEnv (naming suggestions are welcome) for running on non-embedded OS
  2. Implement file-based storage for persistent authenticator data. Currently I've used TestEnv with its BufferStorage, which means that master key is being lost after OpenSK application restart, making all previously created credentials invalid
  3. Move main protocol I/O function from loop in src/main.rs to Env, and implement socket- or stdio- based I/O in NonEmbeddedEnv
  4. Implement user-presence checking in new NonEmbeddedEnv

Obviously, all this new NonEmbeddedEnv stuff should not be compiled in when building token-targeted version of an application.

Is this a viable plan?

egor-duda avatar May 29 '22 15:05 egor-duda

May I ask if you have a specific goal in mind? Is QEMU the purpose like in #288, or do you want a desktop OpenSK?

Let me elaborate a bit on our current work in progress. We noticed that OpenSK is more testable and more broadly usable if its logic was separate from the platform it runs on. With that in mind, we started splitting everything TockOS-related into TockEnv. (It looks like you found that, and noticed that it's infinished.) Some functions in TockEnv still contain CTAP logic, that needs a cleaner sparation. Generally, we haven't converged on the best API and Env trait yet. All of this is tracked under a project.

Once that is finished, you will be able to support a new platform by adding a new Env, i.e. what you call NonEmbeddedEnv (I agree we'd need a different name ^^). That would hopefully be easier than it is right now. So your plan is pretty viable!

Since you were asking for "beyond prototype", I assume you mean that you want to create a PR that we would eventually merge. Cleanest and easiest would be for us to first finish the CTAP library, and then merging your new NonEmbeddedEnv. Else we'd have to port yet another platform to the new API. Afterwards, you could use that desktop version of OpenSK for whatever you want, for example QEMU. Is this a helpful answer for what you have in mind?

kaczmarczyck avatar May 31 '22 18:05 kaczmarczyck

May I ask if you have a specific goal in mind? Is QEMU the purpose like in #288, or do you want a desktop OpenSK?

QEMU, mostly.

I've experimented with running desktop version of OpenSK (on Linux, using /dev/uhid), but I don't see the point, security-wise, of running authenticator on the same host system with user agent. Maybe only for testing/development?

[...]

All of this is tracked under a project.

Great!

I've implemented storage which stores its contents in host-OS-based file: https://github.com/egor-duda/OpenSK/tree/hostenv-file-storage This change is independent of Env-related changes -- shall I make a PR from it?

[...]

Since you were asking for "beyond prototype", I assume you mean that you want to create a PR that we would eventually merge. Cleanest and easiest would be for us to first finish the CTAP library, and then merging your new NonEmbeddedEnv. Else we'd have to port yet another platform to the new API. Afterwards, you could use that desktop version of OpenSK for whatever you want, for example QEMU. Is this a helpful answer for what you have in mind?

Absolutely, thanks for detailed response!

egor-duda avatar Jun 01 '22 17:06 egor-duda

I've experimented with running desktop version of OpenSK (on Linux, using /dev/uhid), but I don't see the point, security-wise, of running authenticator on the same host system with user agent. Maybe only for testing/development?

Testing is definitely a plus. One real world example (that doesn't necessairly require file storage) of desktop security key implementations might be Chrome's WebAuthn debugger. Outside of testing, I'll leave it to the community to decide what use cases they have in mind. Security keys as a file at least make backups a lot easier :) It's a bit like a password manager - with different cryptographic properties.

This change is independent of Env-related changes -- shall I make a PR from it?

The maintenance question still applies. Changing the storage API would be a bit harder. But I agree this is something we will find useful eventually. Maybe @ia0 wants to jump in here wrt storage?

kaczmarczyck avatar Jun 01 '22 17:06 kaczmarczyck

Regarding storage, the proposed implementation is a valid idea (adding a file-based Storage implementation). I'm not sure why the BufferStorage is used though, since the file is probably going to be in RAM anyway, so it's not even more performant. Then there are a few technical aspects too. But overall it's a PR that could be merged.

ia0 avatar Jun 01 '22 17:06 ia0

I'm not sure if it's possible to make pure file-based storage without memory buffer using current API?

read_slice returns a reference, which means, as far as I understand, than underlying storage object must own all those slices' data, and keep it while application is running.

egor-duda avatar Jun 01 '22 19:06 egor-duda

I see. That's actually a good reason to change the API then. I was considering it for other reasons (in particular make it compatible with embedded-storage), but this one adds to it. Might be worth checking whether it's easy to do and if it changing the binary size in any way.

ia0 avatar Jun 01 '22 19:06 ia0

Although for test/debug purposes I don't see objections to a storage serialized on drive, for a "normal" usage, I'd prefer to see the file at least encrypted and if possible using a key derived from hardware unique IDs for security reasons. Otherwise the storage end up being nothing more than a cookie jar that could be stolen by a malware while the promise of FIDO is to resist a remote attacker.

jmichelp avatar Jun 01 '22 20:06 jmichelp

Otherwise the storage end up being nothing more than a cookie jar that could be stolen by a malware while the promise of FIDO is to resist a remote attacker.

The idea is to have file-backed storage residing on the host OS, on which QEMU is running, whereas user agent runs on the guest, accessing authenticator via virtual QEMU device. Presumably, malware shouldn't be able to escape from guest VM and access any data on host OS.

If malware somehow succeeds in reaching host OS, then I don't think file encryption would be of much help. If malware gets non-root access to host OS, then normal OS permission protection should be enough. If malware escapes from guest and gets root-level access to host OS, then it would be able to get decrypted storage from memory of running authenticator application.

egor-duda avatar Jun 02 '22 19:06 egor-duda

@ia0 is looking into solutions to enable file storage (#486, #487). Outside of that, any other plans regarding implementation for this issue? Feel free to reach out to discuss if you are interested!

kaczmarczyck avatar Jun 03 '22 14:06 kaczmarczyck

Some thoughts on transports in FIDO. Generally, the WebAuthn transport we would use is this internal. However, CTAP only mentions HID, NFC and BLE. Since WebAuthn allows it, I believe we should be okay to use it regardless. The intention I read into the specification is: If you don't use special hardware, implement it any way you like.

If you want the security key to look like a HID (or other) device, we might have to approach that differently. The question is at what level you want to exchange data.

kaczmarczyck avatar Jun 07 '22 09:06 kaczmarczyck

Closing this as a duplicate of #288 .

kaczmarczyck avatar Nov 07 '23 09:11 kaczmarczyck