Skip to content

Add YubiKey HMAC-SHA1 challenge-response via usb4java - #4

Open
kwsantiago wants to merge 1 commit into
sparrowwallet:masterfrom
privkeyio:yubikey-hmac-challenge-response
Open

kwsantiago wants to merge 1 commit into
sparrowwallet:masterfrom
privkeyio:yubikey-hmac-challenge-response

Conversation

@kwsantiago

@kwsantiago kwsantiago commented Mar 11, 2026 •

Copy link
Copy Markdown

Summary

Adds YubiKeyHmacProvider, implementing drongo's ChallengeResponseProvider with HMAC-SHA1 challenge-response over the YubiKey OTP HID interface (slot 2).

  • Raw USB control transfers via usb4java, already a lark dependency, so nothing new is added
  • HID OTP frame protocol: 70-byte challenge frames, chunked 8-byte feature reports with all-zero chunks skipped, CRC-16
  • Response CRC validated against the device residual before use
  • Waits for a button press where the slot requires one, reporting progress via setOnWaitingForTouch / setOnComplete for UI prompting
  • cancel() interrupts a pending touch wait
  • Buffers zeroed, USB interface claimed and released, detached kernel driver reattached
  • Exports com.sparrowwallet.lark.yubikey in module-info

Tests

YubiKeyHmacProviderTest covers the protocol logic without hardware: crc16 against the CRC-16/X-25 check value, the device CRC residual and rejection of a corrupted response, and the challenge frame layout including padding, slot byte, CRC placement, filler and truncation of an oversized challenge.

The USB transport needs a device and is not covered.

Challenge padding

The challenge is padded to the full 64-byte block with a byte differing from the last challenge byte (0x00, or 0x01 where the challenge already ends in 0x00), matching ykman. A slot programmed for variable-length challenges (HMAC_LT64, which ykman sets unconditionally) locates the end of the challenge by stripping the trailing padding, so padding with a byte that could be part of the challenge would make the boundary ambiguous.

Note this differs from KeePassXC, which uses PKCS7 padding, so responses for the same secret and challenge are not comparable between the two.

Dependents

Implements ChallengeResponseProvider for YubiKey slot 2 HMAC-SHA1 using
raw USB control transfers, the same protocol ykpers and KeePassXC use.
Validates the response CRC, zeroes intermediate buffers, waits for a
button press where the slot requires one, and can be cancelled while
waiting.
@kwsantiago
kwsantiago force-pushed the yubikey-hmac-challenge-response branch from c6e4901 to 0ec86fd Compare September 8, 2026 14:01
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.

1 participant