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>
63 lines
2.1 KiB
Python
63 lines
2.1 KiB
Python
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
|