From 27d7406d00edcb61525ceaf332aaed851b1a79ac 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. [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..ca7634b --- /dev/null +++ b/examples/list.rs @@ -0,0 +1,5 @@ +fn main() { + for device in ctap::get_devices().unwrap() { + println!("{device:?}"); + } +} diff --git a/src/hid_linux.rs b/src/hid_linux.rs index 0612cbd..81bca52 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 7be3529..854712e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -77,7 +77,7 @@ pub fn get_devices() -> FidoResult> { hid::enumerate() .context(FidoErrorKind::Io) .map(|devices| { - devices.filter(|dev| dev.usage_page == 0xf1d0 && dev.usage == 0x21) + devices.filter(|dev| dev.usage_page == 0xf1d0 && dev.usage == 0x01) }) .map_err(From::from) }