Universal FIDO2/U2F key using Raspberry Pi Pico (rp2040) and wolfCrypt. Works with any raspberry-pi pico device with only one component added (pushbutton on GPIO15).
Fidelio implements a FIDO2 authenticator (CTAP2/WebAuthn) with CTAP1/U2F compatibility, generally used as second factor in 2FA services, or in some specific cases for password-less authentication.
Associating a 2FA authentication service to a hardware key as second factor will require the user to provide the key to prove that they are still in possess of the hardware key that was initially registered.
The holder of the key can only prove the physical presence of the key during an authentication procedure. This is done by connecting it via USB and pushing a button.
Through this mechanism, the authenticator is given a proof that the request has been processed (signed) by the same key initially registered, so the user can be trusted as the authenticator assumes that the user is still holding the key.
Two-factor authentication based on FIDO mechanisms is generally considered more secure than time-based OTP services, like mobile apps or other devices that require clock synchronization with the authenticating party.
The device creates a unique private key, which is then used to derive the keys for the authenticating services requesting a FIDO authentication. This means that Fidelio does not pose any storage limitation on the number of authentication services that can be registered, as the same key is derived again whenever needed and it's never stored on the device. CTAP1/U2F remains supported for legacy services; CTAP2/WebAuthn is the primary protocol.
The codebase is simple and rather small, allowing for an easy full audit of the security model and the related implementations.
The security of Fidelio depends entirely on the physical presence of the hardware. If Fidelio is lost or stolen, the second factor of all the registered services must be considered compromised, and the keys associated to the device should be revoked from all the associated services. This usually does not represent an important security risk in itself, as long as a first factor is in use (commonly, password authentication).
A rp2040 board running Fidelio will not store any credentials or traces that can be associated with any running server. The only two pieces of information stored in the target's FLASH memory are the device's master key, generated on first use, and counters keeping track of crypto operations, as mandated by the FIDO protocols.
FIDO/U2F mandates the use of a single button to indicate that the user is actually present when the key is used. Without this button the authenticator will never assert user presence.
For this purpose, Fidelio requires a normally-open push-button between GPIO15 and GND.
On the Raspberry-pi pico board, this button can normally be soldered in place:
If you are using a different model and/or you want to change the pin for the
presence button and LED, just edit pins.h and change the pin number
defined by the macro PRESENCE_BUTTON and U2F_LED, respectively.
- Clone this repository, create and populate build directory
git clone https://github.com/danielinux/fidelio.git
cd fidelio
git submodule update --init --single-branch pico-sdk lib/wolfssl
cd pico-sdk
git submodule update --init --single-branch lib/tinyusb
cd ..
- Create your own attestation certificate. This is required only once. The certificate generate will univocally identify your device.
You may change/customize the details in the certificate by editing the mkcert.sh
script.
./mkcert.sh
- Configure CMake (pass the full absolute path to pico-sdk):
cmake -B build -DPICO_COPY_TO_RAM=1 -DFAMILY=rp2040 -DPICO_SDK_PATH=/path/to/fidelio/pico-sdk
- Compile:
cmake --build build
- Flash to the Pico (hold BOOTSEL when plugging in, then copy):
cp build/fidelio.uf2 /path/to/RPI-RP2
The first time the device is plugged in into the computer, it will randomly generate its master key. The master key will be then used, for the entire lifetime of the device, to generate keys for single FIDO services.
Updating the Fidelio firmware to a newer version will not overwrite the master key, so the key will keep working with services that had been registered with the old firmware as well.
On first boot the LED will stay on while the master key is generated; press the presence button once to acknowledge, then the device will reboot automatically.
After flashing, set the authenticator PIN:
fido2-token -S /dev/hidrawX # enter your chosen PIN when prompted
Replace /dev/hidrawX with the device path listed by fido2-token -L. Press the
presence button when prompted during this flow.
To ensure that your device is correctly working, connect Fidelio to your PC and visit the WebAuthn.io demo: https://webauthn.io/
Use “Register” to create a credential (press the presence button when asked, and enter the PIN you set above), then “Login” to exercise getAssertion.
Go to your profile settings. Select "Password and authentication" from the Access menu.
Find the "Two factor authentication" configuration at the bottom of the page. Check the "Security Keys" option:
The button "Register new security key" will associate the device running fidelio as a second factor to access your github account. Give it a unique name of your choice.
It is a good idea to configure more than one 2FA mechanism to your account to avoid the risk of being locked out of your account. This of course includes the possibility to use more than one fidelio hardware keys, stored in different places.
To test on a linux machine install libpam-u2f and pamu2fcfg. Run
pamu2fcfg -u $USER > ~/.config/Yubico/u2f_keys (create the directory if needed)
and press the presence button when prompted. Add a line such as
auth sufficient pam_u2f.so authfile=/home/%u/.config/Yubico/u2f_keys cue
to the relevant file in /etc/pam.d (e.g. sudo, login) to allow U2F
assertions as password-less auth or as a second factor; see man pamu2fcfg
and man pam_u2f for options and multiple-key setups.
For CTAP2/FIDO2 flows install fido2-tools and libpam-fido2. Confirm detection
with fido2-token -L, then create a resident PAM credential with
fido2-cred -M -h pam://$(hostname) -i $USER > ~/.fido2-cred. Add
auth sufficient pam_fido2.so authfile=/home/%u/.fido2-cred rp_id=$(hostname)
to the same /etc/pam.d service to use the key for FIDO2 password-less login;
see man pam_fido2 for tuning user verification, PIN prompts, and per-service
rp_id values (e.g. matching SSH TrustedUserCAKeys hostnames).
Ensure you always keep a root console open when changing pam.d configuration, and test your changes properly after each change to avoid locking yourself out of your machine


