gary-rowe / hid4java

A cross-platform Java Native Access (JNA) wrapper for the libusb/hidapi library. Works out of the box on Windows/Mac/Linux.
MIT License
229 stars 71 forks source link

Support for Yubico (and other devices showing up as keyboard or mouse) #18

Closed Toporin closed 9 years ago

Toporin commented 9 years ago

Hello,

I am trying to use the hid4java library with a Yubikey dongle (VID 0x1050, PID 0x0114). Among others, the Yubikey supports a HmacSha1 challenge-response mechanism via feature reports.

I tested the hid4java library using the 'UsbHidTrezorV1Example' examples, but replacing the trezor VID and PID with the Yubikey one.

The hid4java library find two devices with the given VID and PID (it's actually the same device): HidDevice [path=\?\hid#vid_1050&pid_0114&mi_00#8&a6f8690&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}, vendorId=0x1050, productId=0x114, serialNumber=null, releaseNumber=0x340, manufacturer=Yubico, product=Yubikey NEO OTP+U2F, usagePage=0x1, usage=0x6, interfaceNumber=0] & HidDevice [path=\?\hid#vid_1050&pid_0114&mi_01#8&2e46c452&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}, vendorId=0x1050, productId=0x114, serialNumber=null, releaseNumber=0x340, manufacturer=Yubico, product=Yubikey NEO OTP+U2F, usagePage=0xfffff1d0, usage=0x1, interfaceNumber=1]

However, it cannot attach to the Yubikey device apparently: HidDevice trezor = hidServices.getHidDevice(VID, PID, null) returns null => "Waiting for Trezor attach..."

Any idea why it fails to attach to the device? I am working on Windows 8, intel64 (x64) processor

Using the SimpleHIDwrite utility (http://janaxelson.com/files/SimpleHIDWrite3.zip), I can confirm that I am able to send feature reports to the Yubikey and receive response...

Best regards,

Toporin

gary-rowe commented 9 years ago

Thanks for the feedback. I don't currently have access to a Yubikey so I'm not able to verify your findings locally.

I'm inclined to think that hid4java is getting confused because the device is presenting two endpoints and this may not be getting included correctly into the HidDeviceInfoStructure. Can you debug into it (see HidDeviceManager.getAttachedHidDevices()) and verify that the device structure creates a suitably unique path?

Toporin commented 9 years ago

Hello,

I went into HidServices.getHidDevice(int vendorId, int productId, String serialNumber) and observed the iteration on deviceManager.getAttachedHidDevices(). By default, the method ignores the device interface number, so I forced it to select interface 0 then interface 1 (for the yubikey device). Each time, the device.open() method returns false, hence the attach fails...

Depending on interface number, device.getPath() is \?\hid#vid_1050&pid_0114&mi_00#8&a6f8690&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030} \?\hid#vid_1050&pid_0114&mi_01#8&2e46c452&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}

gary-rowe commented 9 years ago

I think there may be an issue with Windows and its hidapi support for keyboards and mice. From the OP the Yubikey is identifying as a keyboard (page 0x06). This could be triggering restrictive behaviour in Windows preventing it from being opened through HID.

The workaround would be to go direct to libusb and not to use the hidapi wrapper. That would explain why the utility program is able to work with the device - it probably goes direct.

More information from Microsoft on keyboard and mice behaviour - note that "The system opens all keyboard and mouse collections for its exclusive use". This strongly implies that a custom (or at least non-HID) driver would be required.

If you agree with this reasoning, please feel free to close this issue.