Skip to content

Add FIDO U2F protocol as a Scapy contrib layer#37

Draft
Copilot wants to merge 2 commits into
masterfrom
copilot/implement-u2f-contrib-layer
Draft

Add FIDO U2F protocol as a Scapy contrib layer#37
Copilot wants to merge 2 commits into
masterfrom
copilot/implement-u2f-contrib-layer

Conversation

Copy link
Copy Markdown

Copilot AI commented May 25, 2026

Implements the FIDO U2F (Universal 2nd Factor) protocol stack as scapy/contrib/u2f.py, covering both the HID transport framing and the application-layer APDU messages.

HID Transport (U2FHID)

  • U2FHIDInitializationPacketCID(4) | CMD(1) | BCNT(2) | payload; auto-computes bcnt on build, strips HID frame zero-padding on dissect, dispatches payload class via guess_payload_class based on cmd and bcnt
  • U2FHIDContinuationPacketCID(4) | SEQ(1) | payload for multi-packet messages
  • U2FHIDINITRequest / U2FHIDINITResponse — INIT command nonce exchange + channel allocation with capability flags (WINK, CBOR, NMSG)
  • U2FHIDError — single-byte error payload

APDU Layer

  • U2FCommandAPDU — ISO 7816-4 extended-length encoding: CLA | INS | P1 | P2 | 0x00 | Lc(2) | data | Le(2); lc auto-computed from data
  • U2FResponseAPDUdata(var) | SW1 | SW2; uses a custom field that peels the trailing 2-byte status word before handing remaining bytes to SW1/SW2 fields

Application Messages

  • U2FRegisterRequestchallenge_parameter(32) | application_parameter(32)
  • U2FRegisterResponsereserved | user_public_key(65) | key_handle_length | key_handle; DER attestation cert + signature remain as Raw payload
  • U2FAuthenticateRequestchallenge_parameter(32) | application_parameter(32) | key_handle_length | key_handle
  • U2FAuthenticateResponseuser_presence | counter(4); ECDSA signature as Raw payload

Usage

from scapy.contrib.u2f import *

# Build a U2F register transaction over HID MSG
challenge = bytes(range(32))
app_id    = bytes(range(32, 64))
apdu_data = raw(U2FRegisterRequest(challenge_parameter=challenge,
                                   application_parameter=app_id))
pkt = (U2FHIDInitializationPacket(cid=0xFFFFFFFF, cmd=0x83)
       / U2FCommandAPDU(ins=0x01, p1=0x03, data=apdu_data))

# Dissect
hid = U2FHIDInitializationPacket(raw(pkt))
req = U2FRegisterRequest(hid[U2FCommandAPDU].data)

# Parse a response APDU
resp = U2FResponseAPDU(b'U2F_V2\x90\x00')
assert resp.data == b'U2F_V2' and resp.sw1 == 0x90

Layer binding U2FHIDInitializationPacket(cmd=0x83) → U2FCommandAPDU is registered via bind_layers.

Copilot AI and others added 2 commits May 25, 2026 19:57
Agent-Logs-Url: https://github.com/polybassa/scapy-1/sessions/9e30e1f3-386e-48d2-b4b7-edad0d79a1fb

Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
Agent-Logs-Url: https://github.com/polybassa/scapy-1/sessions/9e30e1f3-386e-48d2-b4b7-edad0d79a1fb

Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants