Skey: a FIDO2 security key on the Raspberry Pi Pico

Firmware for the Pico / Pico 2 that acts as a USB FIDO2 authenticator:
CTAP2 and U2F, passkeys, BOOTSEL as the touch button, and clientPIN with
PIN/UV auth protocols 1 and 2. A host simulator runs the same core so the
python-fido2 test suite exercises it without hardware.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ckochandClaude Opus 5.5 committed 2026-10-14 15:07:38 -04:00
commit 6c7e6ab5f5
41 files changed
+4218

No files matched your search

+62
View File
@@ -0,0 +1,62 @@
import os
import struct
import pytest
from fido2.ctap import CtapError
from fido2.hid import CAPABILITY, CTAPHID
def test_init_assigns_channel(device):
assert device._channel_id not in (0, 0xFFFFFFFF)
assert device.capabilities & CAPABILITY.CBOR
assert device.capabilities & CAPABILITY.WINK
def test_ping_single_packet(device):
assert device.ping(b"hello") == b"hello"
def test_ping_multi_packet(device):
# 57 bytes in the first packet, then 59 per continuation packet.
payload = os.urandom(3000)
assert device.ping(payload) == payload
def test_ping_largest_message(device):
payload = os.urandom(57 + 128 * 59)
assert device.ping(payload) == payload
def test_wink(device):
device.wink()
def test_unknown_command(device):
with pytest.raises(CtapError) as e:
device.call(0x40)
assert e.value.code == CtapError.ERR.INVALID_COMMAND
def test_out_of_order_continuation(device):
conn = device._connection
cid = device._channel_id
conn.write_packet(struct.pack(">IBH", cid, 0x80 | CTAPHID.PING, 100).ljust(64, b"\0"))
conn.write_packet(struct.pack(">IB", cid, 1).ljust(64, b"\0")) # expected seq 0
response = conn.read_packet()
assert response[:7] == struct.pack(">IBH", cid, 0x80 | CTAPHID.ERROR, 1)
assert response[7] == CtapError.ERR.INVALID_SEQ
assert device.ping(b"still alive") == b"still alive"
def test_other_channel_busy_while_receiving(device):
conn = device._connection
cid = device._channel_id
conn.write_packet(struct.pack(">IBH", cid, 0x80 | CTAPHID.PING, 100).ljust(64, b"\0"))
conn.write_packet(struct.pack(">IBH", cid + 1, 0x80 | CTAPHID.PING, 1).ljust(64, b"\0"))
response = conn.read_packet()
assert response[:8] == struct.pack(">IBHB", cid + 1, 0x80 | CTAPHID.ERROR, 1, CtapError.ERR.CHANNEL_BUSY)
# Finish the original message.
conn.write_packet(struct.pack(">IB", cid, 0).ljust(64, b"\0"))
response = conn.read_packet()
assert response[:7] == struct.pack(">IBH", cid, 0x80 | CTAPHID.PING, 100)
conn.read_packet() # continuation packet with the rest of the echo