-
-
Notifications
You must be signed in to change notification settings - Fork 789
[RFC] Introduce support for FIDO2 to protect keys #8995
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Thanks for the PR! Yes, guess this would be a good new feature, we even have a related ticket #4549. I only had a quick glance at the code:
|
Enable reading of a new passphrase not only from BORG_NEW_PASSPHRASE environement variable but also from a passcommandoor a file descriptor. If Passphrase.new() is called from FlexiKey.change_passphrase(), do not read a passphrase from regular sources (i.e. BORG_PASSPHRASE et al.) if it is available via one of the "new" ones (BORG_NEW_PASSPHRASE et al.). This makes it possible to change passphrases in fully non-interactive manner.
Done.
TL;DR — only device that created I believe I can explain a little bit more how FIDO2 hmac-secret and it may ease your mind. Upon the creation of FIDO2 backed KEK three values are created
We store the first two as an "encrypted key". They, together with the particular device, are needed to retrieve the secret in the future. Only the device used to create the Also — in the current setup (at least mine and this may need more investigation) a device asks for user presence confirmation (up in FIDO2 docs) which means pushing/touching a button on the device for it to return the
OK, I don't have strong opinions about the UI (personally I like it to be as user controllable as possible). However, do keep in mind that as I explained above it is crucial to manually specify the device only when calling encrypt_key_file() (and thus encrypt_key_file_fido2()). And even in that case the device would perform user-presence check i.e. wait for the user to touch the device. Therefore, with most users having a single FIDO2 token using the first one returned by
Done.
Done. I also extended the changes to EDIT: One thing I haven't touched is key export/backup. Unlike in case of passphrase based keys where only the encrypted key needs to be backed up and the passphrase is supposed to be remembered, the recovery scenario for hardware backed encryption needs to consider hardware failure. In systemd-cryptenroll(1) there is an option to enroll a recovery key. Technically it is just a very long random passphrase which in case of LUKS is enough because LUKS works like borg repokey that is an encrypted key is stored in volume's header. Unlike in borg (AFAIK), there may be up to 8 key slots in which a volume key may be encrypted with different passphrases (systemd-cryptenroll encodes the output of FIDO2 hmac-secret with base64 and passes it as a passphrase to cryptsetup). In borg (AFAIK) there is no way to have a master repository key encrypted with several different KEKs except of manual (as of now) fiddling with keyfiles. In this case the easiest way to enable a user to recover from a hardware failure is to show them a secret value as returned by FIDO2 device and later accept it typed in should user's token fail (base64 or otherwise encoded for convenience). This method might also complement current paperkey export of passphrase based KEKs. |
Use FIDO2 devices with hmac-secret extension to generate key encryption key (KEK) instead of passphrase processed with argon2.
Quite a lot of tests are failing. This is because fido2 related code gets used even if it was not explicitly requested (and there usually is no fido2 device while testing anyway). While this could be fixed/adapted, it also proves my point about that things can go wrong and that fido2 functionality should not be used if not explicitly requested. My point is mainly about hw, driver and OS-level malfunctioning (which we can't fix nor foresee). Just as an unrelated example: I use a yubikey for misc. purposes and sometimes I have to physically disconnect/reconnect it to resolve it being unresponsive in some application (while it worked flawlessly shortly before in another application). We must avoid that such malfunctions block borg from working. There could be an env var BORG_FIDO2_DEVICE (or so), default value "none". The env variable could be queried at the relevant places and if it is "none", no fido2 code gets executed (behaves as before this PR). Other values could be a device spec or "auto" to automatically find a device. |
I'll am back at work so I will fix it not as soon as I would like to, but I will.
IMHO requesting to work with a repository encrypted with fido2 backed key qualifies as an explicit request to use fido2 functionality. The only exception from such notion would be a request to manually enter a KEK in case of disaster recovery (broken/lost device).
That sounds like a good idea. How about supporting also "auto" value triggering |
Tested with repo-info only. More code paths need to be covered. To be continued.
Use FIDO2 devices with hmac-secret extension to generate key encryption key (KEK) instead of passphrase processed with argon2 algorithm.
To use such device a user needs to point to one with
--fido2-device
option for eitherrepo-create
orkey change-passphrase
. For reading, borg tries to find which of plugged in devices can be used to decrypt KEK (seefido2.Fido2Operations.find_device()
).fido2
module that wraps around Yubico's module. I haven't updated the requirements because I believe this should remain optional. I've made the wrapper to be loadable without Yubico's module and defer reporting errors until an attempt to use it.find_device()
function with more devices because I have just one.