HID Transport Layer - FeitianTech/postquantum-webauthn-platform GitHub Wiki
- Introduction
- Architecture Overview
- Abstract Base Classes
- Platform-Specific Implementations
- Packet Framing and Protocol
- Channel Management
- Error Handling Mechanisms
- Large Message Fragmentation
- Device Enumeration and Discovery
- Platform-Specific Challenges
- Extensibility and Future Enhancements
- Testing and Validation
The HID (Human Interface Device) transport layer in the Post-Quantum WebAuthn Platform provides a unified interface for communicating with FIDO2 authenticators across multiple operating systems. This transport layer implements the CTAP2 (Client to Authenticator Protocol) specification, enabling secure authentication and cryptographic operations through USB, NFC, and Bluetooth Low Energy (BLE) transports.
The architecture follows a platform-abstraction pattern where a common interface is defined in Python, while platform-specific implementations leverage native APIs and drivers. This design ensures compatibility across Linux, macOS, Windows, and various BSD variants while maintaining consistent behavior and protocol adherence.
The HID transport layer consists of several interconnected components that work together to provide seamless authenticator communication:
graph TB
subgraph "Application Layer"
A[WebAuthn Client]
B[CTAP2 Commands]
end
subgraph "Transport Layer"
C[CtapHidDevice]
D[Protocol Handler]
E[Packet Manager]
end
subgraph "Platform Abstraction"
F[CtapHidConnection]
G[HidDescriptor]
end
subgraph "Platform Implementations"
H[Linux - hidraw]
I[macOS - IOKit]
J[Windows - hid.dll]
K[BSD Variants]
end
subgraph "Hardware Layer"
L[USB Devices]
M[NFC Transports]
N[BLE Devices]
end
A --> B
B --> C
C --> D
D --> E
E --> F
F --> G
G --> H
G --> I
G --> J
G --> K
H --> L
I --> L
J --> L
K --> L
L --> M
L --> N
Diagram sources
- fido2/hid/init.py
- fido2/hid/base.py
Section sources
- fido2/hid/init.py
- fido2/hid/base.py
The CtapHidConnection class defines the fundamental interface that all platform-specific implementations must provide:
classDiagram
class CtapHidConnection {
<<abstract>>
+read_packet() bytes
+write_packet(data : bytes) None
+close() None
}
class FileCtapHidConnection {
+handle : int
+descriptor : HidDescriptor
+__init__(descriptor)
+read_packet() bytes
+write_packet(data : bytes) None
+close() None
}
class LinuxCtapHidConnection {
+write_packet(data : bytes) None
}
class MacCtapHidConnection {
+handle : IOHIDDeviceRef
+read_queue : Queue
+run_loop_ref : CFRunLoopRef
+in_report_buffer : array
+__init__(descriptor)
+read_packet() bytes
+write_packet(data : bytes) None
+close() None
}
class WinCtapHidConnection {
+handle : HANDLE
+descriptor : HidDescriptor
+__init__(descriptor)
+read_packet() bytes
+write_packet(data : bytes) None
+close() None
}
CtapHidConnection <|-- FileCtapHidConnection
FileCtapHidConnection <|-- LinuxCtapHidConnection
CtapHidConnection <|-- MacCtapHidConnection
CtapHidConnection <|-- WinCtapHidConnection
Diagram sources
- fido2/hid/base.py
- fido2/hid/linux.py
- fido2/hid/macos.py
- fido2/hid/windows.py
The HidDescriptor class encapsulates device identification and capability information:
| Field | Type | Description |
|---|---|---|
path |
str | bytes | Device path or identifier |
vid |
int | Vendor ID (USB) |
pid |
int | Product ID (USB) |
report_size_in |
int | Maximum input report size |
report_size_out |
int | Maximum output report size |
product_name |
str | None | Human-readable product name |
serial_number |
str | None | Device serial number |
Section sources
- fido2/hid/base.py
The Linux implementation leverages the hidraw subsystem for direct hardware access:
sequenceDiagram
participant App as Application
participant Linux as Linux Backend
participant Hidraw as hidraw Driver
participant Device as Hardware
App->>Linux : list_descriptors()
Linux->>Hidraw : Read /dev/hidraw*
Hidraw-->>Linux : Device descriptors
Linux-->>App : HidDescriptor[]
App->>Linux : open_connection(descriptor)
Linux->>Hidraw : os.open(descriptor.path)
Hidraw-->>Linux : File descriptor
Linux-->>App : LinuxCtapHidConnection
App->>Linux : write_packet(data)
Linux->>Hidraw : Write with report ID prepended
Hidraw->>Device : USB transfer
Device-->>Hidraw : Response
Hidraw-->>Linux : Raw data
Linux-->>App : Response bytes
Diagram sources
- fido2/hid/linux.py
- fido2/hid/linux.py
Key features:
- Uses
hidrawcharacter device interface - Implements report ID prepending for compatibility
- Handles device caching and error recovery
- Supports hot-plugging detection
Section sources
- fido2/hid/linux.py
The macOS implementation utilizes the IOKit framework for comprehensive device management:
sequenceDiagram
participant App as Application
participant MacOS as macOS Backend
participant IOKit as IOKit Framework
participant Device as Hardware
App->>MacOS : list_descriptors()
MacOS->>IOKit : IOHIDManagerCreate()
IOKit->>IOKit : Scan for HID devices
IOKit-->>MacOS : Device list
MacOS-->>App : HidDescriptor[]
App->>MacOS : open_connection(descriptor)
MacOS->>IOKit : IOHIDDeviceCreate()
IOKit->>Device : Open device
Device-->>IOKit : Ready
IOKit-->>MacOS : Device handle
Note over MacOS,Device : Background thread with CFRunLoop
MacOS->>IOKit : Register input callback
MacOS->>IOKit : Schedule with run loop
App->>MacOS : write_packet(data)
MacOS->>IOKit : IOHIDDeviceSetReport()
IOKit->>Device : Output report
Device-->>IOKit : Input report
IOKit-->>MacOS : Callback with data
MacOS-->>App : Response bytes
Diagram sources
- fido2/hid/macos.py
- fido2/hid/macos.py
Key features:
- Uses IOKit's HID Manager for device discovery
- Implements asynchronous I/O with Core Foundation run loops
- Provides robust error handling and device lifecycle management
- Supports device removal callbacks
Section sources
- fido2/hid/macos.py
The Windows implementation accesses HID functionality through the Windows HID API:
sequenceDiagram
participant App as Application
participant Win as Windows Backend
participant SetupAPI as SetupAPI
participant HidDLL as hid.dll
participant Device as Hardware
App->>Win : list_descriptors()
Win->>SetupAPI : SetupDiGetClassDevsA()
SetupAPI->>SetupAPI : Enumerate HID devices
SetupAPI-->>Win : Device collection
Win->>SetupAPI : Get device interface details
SetupAPI-->>Win : Device paths
Win-->>App : HidDescriptor[]
App->>Win : open_connection(descriptor)
Win->>Win : CreateFileA()
Win->>HidDLL : HidD_GetPreparsedData()
HidDLL-->>Win : Report descriptor
Win-->>App : WinCtapHidConnection
App->>Win : write_packet(data)
Win->>Win : WriteFile() with report ID
Win->>Device : USB transfer
Device-->>Win : Response
Win->>Win : ReadFile()
Win-->>App : Response bytes
Diagram sources
- fido2/hid/windows.py
- fido2/hid/windows.py
Key features:
- Uses SetupAPI for device enumeration
- Leverages hid.dll for HID-specific operations
- Implements comprehensive error handling with WinError()
- Supports device caching for performance optimization
Section sources
- fido2/hid/windows.py
The BSD implementations share common patterns while adapting to platform-specific APIs:
- Supports both
uhid(legacy) andhidraw(modern) interfaces - Uses sysctl for device property retrieval
- Implements fallback mechanisms for different device types
- Utilizes
uhiddevice interface - Implements raw HID mode for direct communication
- Provides ping mechanism for device verification
- Uses
/dev/fidodevice nodes - Implements simplified device discovery
- Focuses on compatibility with OpenBSD's security model
Section sources
- fido2/hid/freebsd.py
- fido2/hid/netbsd.py
- fido2/hid/openbsd.py
The HID transport implements the CTAP2 protocol with specific packet formatting:
graph LR
subgraph "Initialization Packet"
A[Channel ID: 4 bytes]
B[Command: 1 byte]
C[Length: 2 bytes]
D[Payload: Variable]
end
subgraph "Continuation Packet"
E[Channel ID: 4 bytes]
F[Sequence: 1 byte]
G[Payload: Variable]
end
A --> B
B --> C
C --> D
E --> F
F --> G
Diagram sources
- fido2/hid/init.py
The transport layer supports the following CTAP2 commands:
| Command | Value | Description |
|---|---|---|
PING |
0x01 | Echo data back to client |
MSG |
0x03 | General message exchange |
LOCK |
0x04 | Lock channel temporarily |
INIT |
0x06 | Initialize channel |
WINK |
0x08 | Blink authenticator LED |
CBOR |
0x10 | CBOR-encoded data |
CANCEL |
0x11 | Cancel pending operation |
ERROR |
0x3F | Error response |
KEEPALIVE |
0x3B | Progress indication |
Section sources
- fido2/hid/init.py
Each HID connection begins with a channel initialization handshake:
sequenceDiagram
participant Client as CtapHidDevice
participant Transport as HID Transport
participant Device as Authenticator
Client->>Transport : call(INIT, nonce)
Transport->>Device : INIT packet with 8-byte nonce
Device->>Device : Verify nonce
Device-->>Transport : Response with nonce, channel ID, capabilities
Transport->>Transport : Extract channel ID and capabilities
Transport-->>Client : Initialization successful
Note over Client,Device : Channel ready for subsequent commands
Diagram sources
- fido2/hid/init.py
The channel management system handles:
- Unique channel ID assignment (0xFFFFFFFF initially)
- Capability negotiation (WINK, CBOR, NMSG support)
- Device version reporting (major.minor.patch)
- Automatic retry logic for channel busy errors
Section sources
- fido2/hid/init.py
The transport layer implements comprehensive error handling:
flowchart TD
A[Command Execution] --> B{Success?}
B --> |Yes| C[Return Response]
B --> |No| D[Check Error Type]
D --> E{Channel Busy?}
E --> |Yes| F[Retry with Backoff]
E --> |No| G[Other Error]
F --> H{Retry Limit?}
H --> |Within Limit| I[Wait 0.1s]
H --> |Exceeded| J[Raise Exception]
I --> A
G --> K[Raise CtapError]
K --> L[Log Error Details]
L --> M[Cleanup Resources]
Diagram sources
- fido2/hid/init.py
| Error Code | Description | Handling Strategy |
|---|---|---|
CHANNEL_BUSY |
Device temporarily unavailable | Automatic retry with exponential backoff |
INVALID_COMMAND |
Unsupported command | Log and fail fast |
TIMEOUT |
Operation timeout | Retry with increased timeout |
INVALID_LENGTH |
Packet size violation | Validate before transmission |
INVALID_SEQ |
Sequence number mismatch | Reset channel and retry |
Section sources
- fido2/hid/init.py
- fido2/ctap.py
For messages exceeding the maximum packet size, the transport implements automatic fragmentation:
flowchart TD
A[Large Message] --> B{Message Size > Max Packet?}
B --> |No| C[Send Single Packet]
B --> |Yes| D[Calculate Fragments]
D --> E[Send Initialization Packet]
E --> F[Send Continuation Packets]
F --> G{More Fragments?}
G --> |Yes| H[Increment Sequence]
G --> |No| I[Complete Transfer]
H --> F
C --> J[Receive Response]
I --> J
J --> K[Reassemble Fragments]
K --> L[Return Complete Response]
Diagram sources
- fido2/hid/init.py
The fragmentation process handles:
- Automatic packet size calculation based on report sizes
- Sequence number validation for fragment ordering
- Reassembly of fragmented responses
- Error recovery for lost fragments
- Timeout handling for incomplete transfers
Section sources
- fido2/hid/init.py
Each platform implements device discovery according to its native APIs:
graph TB
subgraph "Linux Discovery"
A1[Scan /dev/hidraw*]
A2[Parse report descriptors]
A3[Filter FIDO devices]
end
subgraph "macOS Discovery"
A4[IOHIDManager enumeration]
A5[Property extraction]
A6[Usage page validation]
end
subgraph "Windows Discovery"
A7[SetupAPI device enumeration]
A8[GUID matching]
A9[Report descriptor parsing]
end
subgraph "BSD Discovery"
A10[Device node scanning]
A11[sysctl property access]
A12[Usage validation]
end
A1 --> B[Unified Descriptor List]
A4 --> B
A7 --> B
A10 --> B
Diagram sources
- fido2/hid/linux.py
- fido2/hid/macos.py
- fido2/hid/windows.py
- fido2/hid/freebsd.py
All implementations apply the same filtering criteria:
- FIDO Usage Page (0xF1D0) validation
- FIDO Usage (0x1) validation
- Report descriptor parsing for size determination
- Vendor/Product ID extraction
- Serial number and product name retrieval
Section sources
- fido2/hid/linux.py
- fido2/hid/macos.py
- fido2/hid/windows.py
- fido2/hid/freebsd.py
Device Permissions: Requires appropriate udev rules for non-root access
- Solution: Standard hidraw permissions (664) with group membership
- Hot-plugging support through device monitoring
Driver Dependencies: Relies on kernel hidraw driver
- Solution: Automatic loading of hid-generic when needed
- Compatibility with various USB controller drivers
IOKit Complexity: Requires deep integration with Apple's frameworks
- Solution: Comprehensive error handling and resource cleanup
- Background thread management with Core Foundation run loops
Code Signing Requirements: Applications must be properly signed
- Solution: Framework integration handles signing transparently
- Provisioning profile requirements for development
Driver Model: Must work with Windows HID infrastructure
- Solution: SetupAPI integration for device enumeration
- Compatibility with various USB stack versions
Architecture Differences: 32-bit vs 64-bit packing requirements
- Solution: Dynamic structure packing based on architecture
- Cross-platform compatibility testing
API Differences: Each BSD variant has distinct APIs
- Solution: Unified abstraction layer with platform detection
- Feature parity maintenance across variants
Device Naming: Different device node conventions
- Solution: Flexible path resolution and validation
- Hot-plugging support adaptation
Section sources
- fido2/hid/linux.py
- fido2/hid/macos.py
- fido2/hid/windows.py
- fido2/hid/freebsd.py
The architecture supports easy addition of new platform backends:
classDiagram
class CtapHidConnection {
<<abstract>>
+read_packet() bytes
+write_packet(data : bytes) None
+close() None
}
class NewPlatformBackend {
+list_descriptors() Iterator~HidDescriptor~
+get_descriptor(path) HidDescriptor
+open_connection(descriptor) CtapHidConnection
}
class NewPlatformConnection {
+handle : NativeHandle
+descriptor : HidDescriptor
+read_packet() bytes
+write_packet(data : bytes) None
+close() None
}
CtapHidConnection <|-- NewPlatformConnection
NewPlatformBackend --> NewPlatformConnection
Diagram sources
- fido2/hid/base.py
The transport layer provides several extension points:
- Custom connection implementations for specialized hardware
- Alternative device discovery mechanisms
- Enhanced error handling for specific platforms
- Performance optimizations for particular use cases
The architecture is designed to accommodate:
- NFC transport protocols
- Bluetooth Low Energy (BLE) communication
- Virtual authenticator interfaces
- Cloud-based authenticator connections
Section sources
- fido2/hid/base.py
The HID transport layer includes comprehensive testing:
graph TB
subgraph "Test Categories"
A[Packet Parsing Tests]
B[Device Discovery Tests]
C[Protocol Compliance Tests]
D[Error Handling Tests]
end
subgraph "Test Scenarios"
E[Report Descriptor Parsing]
F[Fragmentation Logic]
G[Cross-Platform Compatibility]
H[Error Recovery Paths]
end
A --> E
B --> F
C --> G
D --> H
Diagram sources
- tests/test_hid.py
Testing approaches include:
- Report descriptor parsing validation
- Protocol compliance verification
- Cross-platform behavior consistency
- Error condition simulation
- Performance benchmarking
Section sources
- tests/test_hid.py