From 29f684c88b6247b3fabaaa8bb75da45d48a92c69 Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Tue, 14 Feb 2023 19:02:24 +0100 Subject: [PATCH] Fix usage check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes the usage check in the device detection: - Instead of usage 0x21, we now check for usage 0x01 as mandated by the FIDO2 spec, ยง 11.2.8.1 [0]. - Instead of using the last usage value in the USB descriptor, which belongs to an endpoint and not to the device, we now use the first (non-zero) value. The descriptor parsing could still be improved, but this should fix compatibility with all compliant FIDO2 devices. This patch also adds a simple list example for listing the detected devices. [0] https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#usb-discovery --- examples/list.rs | 5 +++++ src/hid_linux.rs | 10 ++++++---- src/lib.rs | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 examples/list.rs diff --git a/examples/list.rs b/examples/list.rs new file mode 100644 index 0000000..56944d0 --- /dev/null +++ b/examples/list.rs @@ -0,0 +1,5 @@ +fn main() { + for device in ctap_hmac::get_devices().unwrap() { + println!("{device:?}"); + } +} diff --git a/src/hid_linux.rs b/src/hid_linux.rs index ee819df..a8f8202 100644 --- a/src/hid_linux.rs +++ b/src/hid_linux.rs @@ -58,10 +58,12 @@ fn path_to_device(path: &PathBuf) -> io::Result { } if key & REPORT_DESCRIPTOR_KEY_MASK == USAGE { - if size != 2 { - usage = u16::from(rd[pos + 1]) - } else { - usage = LittleEndian::read_u16(&rd[(pos + 1)..(pos + 1 + (size as usize))]); + if usage == 0 { + if size != 2 { + usage = u16::from(rd[pos + 1]) + } else { + usage = LittleEndian::read_u16(&rd[(pos + 1)..(pos + 1 + (size as usize))]); + } } } diff --git a/src/lib.rs b/src/lib.rs index c823e69..009ffd6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,7 +86,7 @@ static BROADCAST_CID: [u8; 4] = [0xff, 0xff, 0xff, 0xff]; pub fn get_devices() -> FidoResult> { hid::enumerate() .context(FidoErrorKind::Io) - .map(|devices| devices.filter(|dev| dev.usage_page == 0xf1d0 && dev.usage == 0x21)) + .map(|devices| devices.filter(|dev| dev.usage_page == 0xf1d0 && dev.usage == 0x01)) .map_err(From::from) }