Add support for hmac-secret FIDO2 extension
FIDO2 standard (the superset of the older U2F standard) includes hmac-secret extension introducing behaviour similar to older Yubikey HMAC-SHA1 Challenge-Response merged in https://github.com/keepassxreboot/keepassxc/pull/127 but much more universal as FIDO2 is an open standard.
We could try to expand the current Challenge-Response implementation in KeePassXC to cover this too (using libfido2) which will make KeePassXC compatible with any FIDO2 dongle.
This will satisfy https://github.com/keepassxreboot/keepassxc/issues/3450 and any other vendor-specific requests in the future.
I would love that, I have a Solo that supports HMAC-SHA1 and I would love to be able to use it to unlock KeePassXC. If you need a tester at some point just ping me here, I would be more than happy to help.
Do you think about adding this in terms of a second factor or "passwordless"?
With Trezor both use cases are possible, because the device contains touchscreen where you can enter your PIN (which is the second factor, the other one is having the device).
But I think starting with 2factor might be a good start.
It would be really cool to have this.
Currently Trezor cannot be used with KeePassXC, which is unfortunate, as it is the most secure 2FA hardware key on the market, simply because it was originally designed for storing huge amounts of Bitcoin. In practice this comes down to super reliable backups and secure PIN with exponential escape and keypad scrambling.
Just like OnlyKey, Trezor is more than welcome to use the new Yubikey API that allow us to specify a vendor hardware id. @prusnak please let me know if you need more information on this.
@droidmonkey Yes, please give me more info on this - point me to the new Yubikey API. Is this using libfido2?
No it's hmac-sha1. Take a look at Yubikey.cpp init function
@droidmonkey I know about this, of course, but this is not relevant to this issue. The old hmac-sha1 method by Yubikey is obsoleted by FIDO2 hmac-secret extension and that's what new tokens will use. This issue is about implementing this via libfido2. Trezor will not use the obsolete and proprietary Yubikey API.
Ah I see, I was confused by the conversation above a little. We do not have plans (yet) to implement libfido2.
I am interessed in FIDO U2F / FIDO2 support for the Nitrokey FIDO2 and would add $150 as a bounty if it would be implemented.
I would love to use it as a second factor if possible. It would be nice be able to add multiple keys to one database for backup reasons.
What do I need to do to make the bounty added to the topic of this like on the other issues with bounty?
Here is a implementation for LUKS using libfido: https://github.com/mjec/fido2-hmac-secret/blob/fd19bf40a94f177818bce5d2c50cc5eb57136478/src/authenticator.c#L315 that could be build upon
I actually managed to do a very dirty quick POC : d63e7371120b7ec203e356d2ceb8b70fdc9d982e . It seems only diligence work if someone wants to grab that bounty ;)
To get it to work you first need to create a resident hmac token with the hostname 'keepassxc.org' See https://developers.yubico.com/libfido2/Manuals/fido2-cred.html
I doubt that I fully understood how the whole thing is supposed to work though ;)
Just one more comment: I guess it makes sense to support multiple drivers by passing not only the slot, but also the driver to the challenge function and add an intermediate proxy class.
Currently only one device with multiple slots is supported by design (getSerial, getVendor), that IMHO could be fixed in any case.
Currently credential management is only supported by Yubikey, so on my Solo Key I also cannot search any slots but only define the assertion to hopefully match.
I haven't quite got if you need the resident key. I am happy now with the challenge that I got something mysteriously working.
As this is a security product, I would ask someone with much better C++ / QT skills take on the task though :)
Actually on my solo key now the credman extension is working (FIDO_2_1_PRE) . So listing the rk (slots) would be possible. However this might require a PIN, which would probably break the UX a bit.
With Trezor both use cases are possible, because the device contains touchscreen where you can enter your PIN (which is the second factor, the other one is having the device).
But I think starting with 2factor might be a good start.
even normally when you enter the PIN on the computer instead of the fido device you have 2 factors, although it's not perfect security-wise
To get it to work you first need to create a resident hmac token with the hostname 'keepassxc.org' See https://developers.yubico.com/libfido2/Manuals/fido2-cred.html
resident credentials only? if yes then sad.
couldnt keepass just keep the credentialID in the db file but not encrypted so it can be used to poll a "normal" credential?
Actually on my solo key now the credman extension is working (FIDO_2_1_PRE) . So listing the rk (slots) would be possible. However this might require a PIN, which would probably break the UX a bit.
you can iirc poll RKs for a specific RP without having the credential management. like I have had a few devices which dont have credential management but when getting asked to log in they just listed all RKs nicely. (it did require PIN though as browsers as far as I am aware always force PIN for RK stuff)
resident credentials only? if yes then sad.
couldnt keepass just keep the credentialID in the db file but not encrypted so it can be used to poll a "normal" credential?
don't rks make sense in the case of HMAC? Why is is this sad? You do not need a credentialID if its not resident don't you? I can try if it generates a HMAC also from the builtin key. It might however be a security risk, because some other "service" might just do the same and then your secret is exposed. IMHO this breaks security a bit.
you can iirc poll RKs for a specific RP without having the credential management. like I have had a >few devices which dont have credential management but when getting asked to log in they just >listed all RKs nicely. (it did require PIN though as browsers as far as I am aware always force PIN for >RK stuff)
Yes you can simply do try and error with assertions, so that is polling. So you suggest to simply have also 2 "slots" and poll them like for yubikey. Or poll the maximum (in my case) of 50 ?
don't rks make sense in the case of HMAC? Why is is this sad? You do not need a credentialID if its not resident don't you? I can try if it generates a HMAC also from the builtin key. It might however be a security risk, because some other "service" might just do the same and then your secret is exposed. IMHO this breaks security a bit.
isnt hmac same as with normal credential based on the keys it generates instead of the master secret? would be pretty bonkers if not.
also big problem is that
- 90% of all FIDO2 devices I know of have no credential management so grilling RKs is kinda impossible without resetting the whole device which is just crazy
- the credential management extension is still not fully released (the Fido2.1 pointer on options isnt called FIDO2_1_PRE without reason.
also considering the fact that there is a "salt" as the CTAP2 spec calls it needed, which obviously would be random on database creation, it would be the same as with file based secrets that there certainly is a small chance you can just hit the same, but probably negligible
Yes you can simply do try and error with assertions, so that is polling. So you suggest to simply have also 2 "slots" and poll them like for yubikey. Or poll the maximum (in my case) of 50 ?

no random try and error involved, the user just enters PIN and gets a list and selects the one needed.
isnt hmac same as with normal credential based on the keys it generates instead of the master secret? would be pretty bonkers if not.
This is (ab-)using the HMAC as symmetric key so things are a bit more difficult I guess. "Normal" credential work in an asymmetric way so there is no risk in replaying.
I don't have much time to experiment at the moment. I tested the interface with the commandline libfido2 tools, so if you can also easily try the workflow there without programming.
Yes you can simply do try and error with assertions, so that is polling. So you suggest to simply have also 2 "slots" and poll them like for yubikey. Or poll the maximum (in my case) of 50 ?
no random try and error involved, the user just enters PIN and gets a list and selects the one needed.
Can you explain the screenshot and may make a reference to the FIDO2 CTAP spec? A command line version would also help!
sure. in chrome and Windows 10 implementations (which are the most widespread webauthn implementations I have seen so far) when multiple RKs exist for any RP (relying party, generally meaning domain of a website in webauthn contexts) after entering the pin is spawns a selection of the Resident Keys for that RP.
linking to CTAP2.0 for obvious reasons here: https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#authenticatorGetAssertion
step 9 and 10 say:
If more than one credential was located in step 1 and allowList is present and not empty, select any applicable credential and proceed to step 12. Otherwise, order the credentials by the time when they were created in reverse order. The first credential is the most recent credential that was created.
If authenticator does not have a display:
Remember the authenticatorGetAssertion parameters.
Create a credential counter(credentialCounter) and set it 1. This counter signifies how many credentials are sent to the platform by the authenticator.
Start a timer. This is used during authenticatorGetNextAssertion command. This step is optional if transport is done over NFC.
Update the response to include the first credential’s publicKeyCredentialUserEntity information and numberOfCredentials. User identifiable information (name, DisplayName, icon) inside publicKeyCredentialUserEntity MUST not be returned if user verification is not done by the authenticator.
basically you can use this and authenticatorGetNextAssertion to pull all the assertions for all RKs concerining that RP and go, in web contexts you have to select one to actually use and send, a local software could theoretically try them all but obviously that is not efficient.
obviously no matter whether an RK is used or not, if you keep the credentialID around, you dont have to do any ambiguity steps
@My1 You seem to be very knowledgeable in FIDO subject. Are you also a programmer? Maybe you can pick up what @riedel has done and develop it further. I'd gladly provide assistance with the testing if needed.
I am a big fan of fido stuff and I am more using it in context of webauthn and just gained experience by also testing quite a few fido devices both U2F and Fido2, I have played around with U2F for about 4 years already.
probably cant help with programming though as I have borderline no experience in desktop programming, I mostly do webstuff in PHP, CSS and HTML, although I could give a look over the code and hack though a bit
the part about how this stuff works just now was not something I knew prior to the last response, I just gave the spec a quick read at the places where I would think they would have to be, lol.
the biggest piece of fun though will be multi-OS support as W10 >= 1903 does Fido stuff from the OS side, but all others do not do this so keepass needs to run all the fido requests by itself on all other OSes and needs to either a) pipe through windows b) run as admin (not desirable usually) on later w10
the biggest piece of fun though will be multi-OS support
https://github.com/Yubico/libfido2 should provide sufficient abstraction so applications such as keepassxc do not have to deal with this
the biggest piece of fun though will be multi-OS support
https://github.com/Yubico/libfido2 should provide sufficient abstraction so applications such as keepassxc do not have to deal with this
except you do have to do for the specific point I noted. as libfido2's readme states:
On Windows 1903 and newer versions, access to FIDO devices has been restricted to applications using the operating system’s native API. Use of libfido2 is still possible in privileged applications.
I am pretty confident libfido2 will become a wrapper for the operating system’s native API on Windows (same as libhidapi which just wraps OS native API for HID on Windows). https://github.com/Yubico/libfido2/issues/153
that would be nice indeed
okay I think the issue sounds like it isnt likely to be done any soon, considering the thing the reply links to
@riedel Have you taken another look at this? I went through your proof of concept code and tried to extract the changes into their own files classes and functions (See here). I was hoping to be able to get something working by doing a search and replace of sorts, but with the latest release of 2.6.0, I am not sure that my initial plan is going to work anymore. Did you have any thoughts on rebasing your POC to the latest master?
Full disclaimer: I am a dabbler, not a programmer. I just figured that I could clean up after @riedel and get things working in a clean way without overwriting the Yubikey stuff.
no I did not try. You are at the point why I gave up :) Particularly because I felt that I probably get it wrong without investing more thought and understanding larger parts of the code base. The code first felt extensible, but then I realized too many gotchas/dependencies/undocumented expected behaviour to make it easily portable by adding just a driver.