Notebook entry
Reverse engineering a Windows Hello fingerprint reader
The problem
My laptop has a fingerprint reader that works beautifully in Windows Hello and not at all in Linux.
There’s no driver, no libfprint support, and no documentation. I wanted to know what it would take
to change that — which mostly meant finding out what the device actually does when Windows talks to it.
Looking at the hardware
The sensor shows up as a USB device, but internally it bridges to an I²C part. That split matters: the interesting traffic is I²C wrapped inside USB control transfers, so a naive USB capture shows framing, not payloads.
$ lsusb -d 27c6: Bus 003 Device 006: ID 27c6:5395 Fingerprint Sensor bInterfaceClass 255 Vendor Specific bNumEndpoints 2 (1 bulk-in, 1 interrupt-in)
Capturing I²C traffic
With the sensor initialised, the first exchange looks like this — a short init packet, then a status reply. Hover a byte to line it up with its ASCII:
The 53 46 3A prefix (SF:) shows up on every frame, so it’s almost certainly a magic header rather
than data. That gave me a frame boundary to work from.
What I got wrong
Once I stopped trusting the timing and started trusting the frame header, the protocol fell out quickly.
Where it stands
There’s a small Rust program that can initialise the sensor, request a scan, and pull back a raw image.
Enrollment and matching aren’t done, and I haven’t touched libfprint integration yet.
What’s next
- Wire the raw image path into
libfprintso the desktop actually uses it. - Work out enrollment, which needs multiple captures stitched together.
- Figure out what the last four bytes of each frame are. I think it’s a checksum. I’ve been wrong before.