GitHub - mjec/fido2-hmac-secret: A simple way to generate password-proteceted se...
source link: https://github.com/mjec/fido2-hmac-secret
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
README.md
fido2-hmac-secret
A system for using a FIDO2 authenticator with hmac-secret extension support to generate passphrase-protected secrets.
Installation
make release && sudo make install
The DESTDIR
and PREFIX
variables are respected (so you can do sudo make install PREFIX=/usr
, for example, to install to /usr/bin
instead of /usr/local/bin
).
Note that by default make install
requires root privileges, because the binary runs as setuid root; see the setuid section below.
If you want to install the mkinitcpio hooks, you have to build those specifically too: make release initcpio && sudo make install
.
Before building or running this tool, you'll need the following dependencies installed:
At the moment I believe this tool is linux-only; issue reports or pull requests to improve portability are gratefully accepted.
setuid
By default, fido2-hmac-secret
will be installed as setuid and owned by root. This is done to ensure it has the CAP_IPC_LOCK
capability and no hard RLIMIT_MEMLOCK
limit. fido2-hmac-secret
will disable core dumps and increase RLIMIT_MEMLOCK
to 512MiB before dropping privileges to those of the real user ID. If privileges cannot be dropped, fido2-hmac-secret
will terminate with exit code 67. The aim of this is to ensure memory is never swapped or dumped to disk, potentially revealing secrets.
If you are not worried about secrets being swapped out or revealed in core dumps, you can safely run this application without setuid as any user. By default this will print warnings about not running as setuid root. You can disable those warnings by setting the FIDO2_HMAC_SECRET_SILENCE_MEMLOCK_ERRORS
environment variable to any value.
You can also compile this application not to warn about running as a lower-privileged user (or without setuid root) by running make release -DALWAYS_SILENCE_MEMORY_LOCK_ERRORS=1
.
How this works
The authenticator has a credential-scoped secret which is used to calculate the HMAC-SHA256 over some data they call a salt.
During the enrol
step, we create a file containing a randomly-generated salt, a credential ID (specified by the authenticator), and a randomly generated relying party ID (a credential on the authenticator is scoped to a relying party ID, which is specified when creating the credential). This data is encrypted with the passphrase you specify, and saved to disk.
The generate
command decrypts this data, sends it to the authenticator, and prints the result. This results in the same value being returned every time; but that value cannot be obtained without both the decrypted keyfile (which requires your passphrase) and the authenticator device.
Encrypted keyfile
This is a CBOR-encoded array with the following elements:
Field
Name
Type
Notes
0
version
unsigned 8 bit integer
Schama version; always 1
1
device AAGUID
definite bytestring
Device make & model, or empty
2
passphrase salt
definite bytestring
See crypto_pwhash
3
opslimit
unsigned 64 bit integer
See crypto_pwhash
4
memlimit
unsigned 64 bit integer
See crypto_pwhash
5
algorithm
unsigned 16 bit integer
See crypto_pwhash
6
nonce
definite bytestring
See crypto_secretbox_easy
7
encrypted data
definite bytestring
Device AAGUID will be empty if and only if the enrol
step is done with --obfuscate-device-info
. If it's empty, every hmac-secret-supporting device will be tried during the generate
step. If it's not empty, only devices with a matching AAGUID are returned.
Any modification of any of the fields (except version, device vendor and device product) will irrecoverably render the key unusable.
The user will be prompted for a passphrase, which is run through libsodium's crypto_pwhash
, with parameters from fields 3, 4, 5 and 6 to give a key.
That key, combined with the nonce in field 7, is used to decrypt the encrypted data in field 8 with libsodium's crypto_secretbox_easy
.
Once the encrypted data section is decrypted, it contains a CBOR-encoded array with the following elements:
Field
Name
Type
Notes
0
version
unsigned 8 bit integer
Schama version; always 1
1
relying party ID
definite UTF-8 string
random subdomain of .v1.fido2-hmac-secret.localhost
2
credential ID
definite bytestring
3 HMAC salt definite bytestring
These parameters (other than version) are then passed to the FIDO2 authenticator, which returns an HMAC-SHA-256 over the salt. The key for that HMAC is available only to the authenticator, and is associated with the credential ID and relying party ID. This means that all three fields are essential, as is they physical authenticator device.
In fact it would be sufficient for cryptographic security of the key material to store hide the HMAC salt, which provides at least 32 bytes (and normally 64 bytes or 512 bits), of entropy. Hiding the relying party ID and credential ID however costs us nothing, and adds some additional protection.
At the very least, the credential ID offers an additional 100 bits of entropy. Although the credential ID is opaque, it may contain the key material enrypted in a manner that only the FIDO2 authenticator can decrypt. In this case, even advanced tampering with that device would not reveal enough information to even begin an offline attack, absent the cleartext credential ID.
The relying party ID contained in this data is in fact only used as part of that ID, and it is always a 32 character string composed of characters in the range [a-z0-7], for a total of 160 bits of entropy. The aim here is to ensure that any protections in the authenticator against cross-origin key use detection are available. I doubt any key has such protection, but again it costs us nothing.
Risks
The number one risk is that by playing around with encryption like this you will lose your data. Keep good, offline backups of your data. Test your backups regularly, to ensure files can be recovered without access to any of your usual hardware or software.
Backup your LUKS header and data before using this for disk encryption keys. Seriously.
The security of this sytem depends on the security of your authenticator device, libsodium, libfido2, and the quality of your passphrase. It's also possible -- and indeed more likely than any of the former issues -- that there's a bug in the code for this application which compromises its security somehow. Pull requests and issues are very welcome.
Warrant canary (but not a warranty)
At the time of writing, I have not received or complied with any government or non-government requests for information or services relating to this software.
Output format
The usual output format is a series of 128 characters ASCII, being the hex-encoded (lowercase) form of the key, with no whitespace (plus a new line character). This avoids potential problems with interfaces that are not 8-bit clean (including the risk of a NUL byte or newline causing key material truncation). You can also type in such a key by hand with any keyboard, if that is important.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK