From 527943fbba3b0b99cd24dc96035af45645905287 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Fri, 26 Dec 2025 19:53:46 +0100 Subject: [PATCH 01/13] Releaser is available up to 6.7.0 Signed-off-by: Pol Henarejos --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index d8f5dd8..d06636c 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -34,7 +34,7 @@ jobs: - name: Delete private key run: rm private.pem - name: Update nightly release - uses: pyTooling/Actions/releaser@main + uses: pyTooling/Actions/releaser@v6.7.0 with: tag: nightly-${{ matrix.refs }} rm: true From ceb54d9a08b48606559ff5ecd7d36df8d7a351f9 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sat, 27 Dec 2025 16:03:07 +0100 Subject: [PATCH 02/13] Move pointer Signed-off-by: Pol Henarejos --- pico-keys-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-keys-sdk b/pico-keys-sdk index 05fe059..7dc7be0 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 05fe0596ef004313e166b1e2f900e9af351dd26c +Subproject commit 7dc7be090919e7638616e93f21ff4c10c1373dec From 42b8b0af5f5eff121367715a81370dddb49bfa3c Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sat, 27 Dec 2025 22:04:03 +0100 Subject: [PATCH 03/13] Fix pimoroni led Signed-off-by: Pol Henarejos --- pico-keys-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-keys-sdk b/pico-keys-sdk index 7dc7be0..4df6160 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 7dc7be090919e7638616e93f21ff4c10c1373dec +Subproject commit 4df616082ece2683d0a55745e2f69727072b6385 From 2331dcb3ec2791eb3cae7ff796b5ce707ea15585 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 29 Dec 2025 20:16:22 +0100 Subject: [PATCH 04/13] Blink led three times to acknowledge proper commissioning. Signed-off-by: Pol Henarejos --- pico-keys-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-keys-sdk b/pico-keys-sdk index 4df6160..6305ea1 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 4df616082ece2683d0a55745e2f69727072b6385 +Subproject commit 6305ea11abe6f6e2c42b72c4305bd14af6855ba9 From 70dec5596a7c0e977ea1bcaf3622fdd367ec8d7a Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 29 Dec 2025 20:36:37 +0100 Subject: [PATCH 05/13] Fix build. Signed-off-by: Pol Henarejos --- pico-keys-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-keys-sdk b/pico-keys-sdk index 6305ea1..7e6e3c8 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 6305ea11abe6f6e2c42b72c4305bd14af6855ba9 +Subproject commit 7e6e3c8f3c7d4f7e9aa5f7f94de4a3560fbf59cb From ac7e34522a4f1847d280250b230400008eebc87d Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 5 Jan 2026 12:33:35 +0100 Subject: [PATCH 06/13] Fixed resident credential storage when two userId have the same prefix. Added a specific test for this case. Fixes #241. Signed-off-by: Pol Henarejos --- src/fido/credential.c | 2 +- tests/pico-fido/test_022_discoverable.py | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/fido/credential.c b/src/fido/credential.c index 6bc479a..645417d 100644 --- a/src/fido/credential.c +++ b/src/fido/credential.c @@ -319,7 +319,7 @@ int credential_store(const uint8_t *cred_id, size_t cred_id_len, const uint8_t * credential_free(&rcred); continue; } - if (memcmp(rcred.userId.data, cred.userId.data, MIN(rcred.userId.len, cred.userId.len)) == 0) { + if (rcred.userId.len == cred.userId.len && memcmp(rcred.userId.data, cred.userId.data, rcred.userId.len) == 0) { sloti = i; credential_free(&rcred); new_record = false; diff --git a/tests/pico-fido/test_022_discoverable.py b/tests/pico-fido/test_022_discoverable.py index 36b7055..92596de 100644 --- a/tests/pico-fido/test_022_discoverable.py +++ b/tests/pico-fido/test_022_discoverable.py @@ -202,10 +202,29 @@ def test_rk_with_allowlist_of_different_rp(resetdevice): assert e.value.code == CtapError.ERR.NO_CREDENTIALS +def test_same_prefix_userId(device): + """ + A make credential request with two different UserIds that share the same prefix should NOT overwrite. + """ + rp = {"id": "sameprefix.org", "name": "Example"} + user1 = {"id": b"user_12", "name": "A fixed name", "displayName": "A fixed display name"} + user2 = {"id": b"user_123", "name": "A fixed name", "displayName": "A fixed display name"} + + mc_res1 = device.MC(rp = rp, options={"rk":True}, user = user1) + + # Should not overwrite the first credential. + mc_res2 = device.MC(rp = rp, options={"rk":True}, user = user2) + + ga_res = device.GA(rp_id=rp['id'])['res'] + + assert ga_res.number_of_credentials == 2 + + def test_same_userId_overwrites_rk(resetdevice): """ A make credential request with a UserId & Rp that is the same as an existing one should overwrite. """ + resetdevice.reset() rp = {"id": "overwrite.org", "name": "Example"} user = generate_random_user() @@ -249,6 +268,7 @@ def test_returned_credential(device): ga_res = device.GA(allow_list=allow_list,options={'up':False})['res'] + print(ga_res) # No other credentials should be returned with pytest.raises(CtapError) as e: From 5fc84d70978347875a6f95dc53d1305694956fda Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 5 Jan 2026 12:36:44 +0100 Subject: [PATCH 07/13] Reset internal state of GA to avoid phantom requests on GNA. When a previous GA had more than 1 credential, it stored the full list in the internal state. Later, if a GA had only 1 credential, subsequent GNA returned older state of previous non-related GA. Signed-off-by: Pol Henarejos --- src/fido/cbor.c | 4 ++++ src/fido/cbor_get_assertion.c | 30 +++++++++++++++++------------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/fido/cbor.c b/src/fido/cbor.c index fec4d2f..f9ca3ed 100644 --- a/src/fido/cbor.c +++ b/src/fido/cbor.c @@ -41,6 +41,7 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len); int cbor_config(const uint8_t *data, size_t len); int cbor_vendor(const uint8_t *data, size_t len); int cbor_large_blobs(const uint8_t *data, size_t len); +extern void reset_gna_state(); extern int cmd_read_config(); @@ -59,6 +60,9 @@ int cbor_parse(uint8_t cmd, const uint8_t *data, size_t len) { } if (cap_supported(CAP_FIDO2)) { if (cmd == CTAPHID_CBOR) { + if (data[0] != CTAP_GET_NEXT_ASSERTION) { + reset_gna_state(); + } if (data[0] == CTAP_MAKE_CREDENTIAL) { return cbor_make_credential(data + 1, len - 1); } diff --git a/src/fido/cbor_get_assertion.c b/src/fido/cbor_get_assertion.c index ee25e79..fac8e01 100644 --- a/src/fido/cbor_get_assertion.c +++ b/src/fido/cbor_get_assertion.c @@ -42,6 +42,22 @@ uint32_t timerx = 0; uint8_t *datax = NULL; size_t lenx = 0; +void reset_gna_state() { + for (int i = 0; i < MAX_CREDENTIAL_COUNT_IN_LIST; i++) { + credential_free(&credsx[i]); + } + if (datax) { + free(datax); + datax = NULL; + } + lenx = 0; + residentx = false; + timerx = 0; + flagsx = 0; + credentialCounter = 0; + numberOfCredentialsx = 0; +} + int cbor_get_next_assertion(const uint8_t *data, size_t len) { (void) data; (void) len; @@ -57,19 +73,7 @@ int cbor_get_next_assertion(const uint8_t *data, size_t len) { credentialCounter++; err: if (error != CborNoError || credentialCounter == numberOfCredentialsx) { - for (int i = 0; i < MAX_CREDENTIAL_COUNT_IN_LIST; i++) { - credential_free(&credsx[i]); - } - if (datax) { - free(datax); - datax = NULL; - } - lenx = 0; - residentx = false; - timerx = 0; - flagsx = 0; - credentialCounter = 0; - numberOfCredentialsx = 0; + reset_gna_state(); if (error == CborErrorImproperValue) { return CTAP2_ERR_CBOR_UNEXPECTED_TYPE; } From bd499ae1d44c89c6d8302b599ba3a555de17c3ff Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 5 Jan 2026 19:37:27 +0100 Subject: [PATCH 08/13] Remove print Signed-off-by: Pol Henarejos --- tests/pico-fido/test_022_discoverable.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/pico-fido/test_022_discoverable.py b/tests/pico-fido/test_022_discoverable.py index 92596de..2faa2ed 100644 --- a/tests/pico-fido/test_022_discoverable.py +++ b/tests/pico-fido/test_022_discoverable.py @@ -268,7 +268,6 @@ def test_returned_credential(device): ga_res = device.GA(allow_list=allow_list,options={'up':False})['res'] - print(ga_res) # No other credentials should be returned with pytest.raises(CtapError) as e: From becdc943399067f1b09825e9e151f286e0000691 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 5 Jan 2026 19:37:30 +0100 Subject: [PATCH 09/13] Disable button press by default since LED may not be properly configured until it is commissioned. Signed-off-by: Pol Henarejos --- pico-keys-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-keys-sdk b/pico-keys-sdk index 7e6e3c8..08dc94a 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 7e6e3c8f3c7d4f7e9aa5f7f94de4a3560fbf59cb +Subproject commit 08dc94a144b4a7a4f1207052df26b28b0399c8c9 From 2e0333677b9a5b528000b3b1986e216379469c7b Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 5 Jan 2026 19:39:46 +0100 Subject: [PATCH 10/13] Fix button logic. Signed-off-by: Pol Henarejos --- pico-keys-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-keys-sdk b/pico-keys-sdk index 08dc94a..7de9855 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 08dc94a144b4a7a4f1207052df26b28b0399c8c9 +Subproject commit 7de98552d1003de077fde1e644cd610c0b95b614 From d16016cf1ee318090ed4d56adc216db993516856 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 5 Jan 2026 19:51:11 +0100 Subject: [PATCH 11/13] Upgrade Pico Keys SDK to v8.2 Signed-off-by: Pol Henarejos --- pico-keys-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-keys-sdk b/pico-keys-sdk index 7de9855..263e554 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 7de98552d1003de077fde1e644cd610c0b95b614 +Subproject commit 263e554cc6c59a5f168f8589c4bdabe6e1e64c25 From 81d97f1a18856f73b0ffed50afeaf735cc2c1a54 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 5 Jan 2026 19:56:09 +0100 Subject: [PATCH 12/13] Upgrade to v7.2 Signed-off-by: Pol Henarejos --- build_pico_fido.sh | 2 +- src/fido/version.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build_pico_fido.sh b/build_pico_fido.sh index ab83499..497d70d 100755 --- a/build_pico_fido.sh +++ b/build_pico_fido.sh @@ -1,7 +1,7 @@ #!/bin/bash VERSION_MAJOR="7" -VERSION_MINOR="0" +VERSION_MINOR="2" SUFFIX="${VERSION_MAJOR}.${VERSION_MINOR}" #if ! [[ -z "${GITHUB_SHA}" ]]; then # SUFFIX="${SUFFIX}.${GITHUB_SHA}" diff --git a/src/fido/version.h b/src/fido/version.h index 7417630..f8625ce 100644 --- a/src/fido/version.h +++ b/src/fido/version.h @@ -18,7 +18,7 @@ #ifndef __VERSION_H_ #define __VERSION_H_ -#define PICO_FIDO_VERSION 0x0700 +#define PICO_FIDO_VERSION 0x0702 #define PICO_FIDO_VERSION_MAJOR ((PICO_FIDO_VERSION >> 8) & 0xff) #define PICO_FIDO_VERSION_MINOR (PICO_FIDO_VERSION & 0xff) From fe49149d86aeb05695d30b2cfe5015c8b19cd12d Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 6 Jan 2026 21:20:04 +0100 Subject: [PATCH 13/13] Update README with up-to-date info. Signed-off-by: Pol Henarejos --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 77f34ce..e12f571 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Pico FIDO This project transforms your Raspberry Pi Pico or ESP32 microcontroller into an integrated FIDO Passkey, functioning like a standard USB Passkey for authentication. -If you are looking for a Fido + OpenPGP, see: https://github.com/polhenarejos/pico-fido2 +If you are looking for a OpenPGP + Fido, see: https://github.com/polhenarejos/pico-fido2. Available through [PicoKey App](https://www.picokeys.com/picokeyapp/ "PicoKey App"). ## Features Pico FIDO includes the following features: @@ -36,12 +36,13 @@ Pico FIDO includes the following features: - Challenge-response generation - Emulated keyboard interface - Button press generates an OTP that is directly typed +- Yubico Authenticator app compatible - Yubico YKMAN compatible - Nitrokey nitropy and nitroapp compatible - Secure Boot and Secure Lock in RP2350 and ESP32-S3 MCUs - One Time Programming to store the master key that encrypts all resident keys and seeds. - Rescue interface to allow recovery of the device if it becomes unresponsive or undetectable. -- LED customization with Pico Commissioner. +- LED customization with PicoKey App. All features comply with the specifications. If you encounter unexpected behavior or deviations from the specifications, please open an issue. @@ -55,11 +56,11 @@ Microcontrollers RP2350 and ESP32-S3 are designed to support secure environments If you own a Raspberry Pico (RP2040 or RP2350), go to [Download page](https://www.picokeys.com/getting-started/), select your vendor and model and download the proper firmware; or go to [Release page](https://www.github.com/polhenarejos/pico-fido/releases/) and download the UF2 file for your board. -Note that UF2 files are shiped with a dummy VID/PID to avoid license issues (FEFF:FCFD). If you plan to use it with other proprietary tools, you should modify Info.plist of CCID driver to add these VID/PID or use the [Pico Commissioner](https://www.picokeys.com/pico-commissioner/ "Pico Commissioner"). +Note that UF2 files are shiped with a dummy VID/PID to avoid license issues (FEFF:FCFD). If you plan to use it with OpenSC or similar tools, you should modify Info.plist of CCID driver to add these VID/PID or use the [PicoKey App](https://www.picokeys.com/picokeyapp/ "PicoKey App"). You can use whatever VID/PID (i.e., 234b:0000 from FISJ), but remember that you are not authorized to distribute the binary with a VID/PID that you do not own. -Note that the pure-browser option [Pico Commissioner](https://www.picokeys.com/pico-commissioner/ "Pico Commissioner") is the most recommended. +Note that the [PicoKey App](https://www.picokeys.com/picokeyapp/ "PicoKey App") is the most recommended. ## Build for Raspberry Pico Before building, ensure you have installed the toolchain for the Pico and that the Pico SDK is properly located on your drive.