Monthly Archives: January 2006

Breaking encryption the easy way

Yesterday, I successfully obtained images my Microsoft fingerprint reader. After cleaning up the driver a little, I decided to try my other device.

A little background:

There are 3 ranges of devices which we believe are all very similar:

  1. Digital Persona UareU 4000
  2. Digital Persona UareU 4000B
  3. Microsoft fingerprint reader (and products containing them)

The 4000B is basically a USB2 version of the 4000, and we think the Microsoft devices include ‘repackaged’ 4000B devices. My driver will hopefully support all 3. I own #1 and #3 and have sniffed logs from all 3 device types in my posession.

I plugged in my UareU 4000, and it sprang into life with my driver. I scanned a fingerprint and it gave me this:

Hmm. The data is very jumbled and is probably encrypted. I checked my logs, and sure enough – the data that comes from the 4000 and 4000B devices is jumbled and doesn’t show the same neat structure in comparison to the MS device.

A while ago, I had compared the 4000B firmware with the firmware for the MS devices. There is just one single bit difference between the two, suggesting that the devices are actually identical, yet the 4000B is sending encrypted data and the MS device is not?

I uploaded the 4000B firmware to my MS device, and sure enough, it then started sending encrypted images too. In other words, we have found the single bit in the firmware which turns encryption on and off.

This still leaves the problem that my 4000 device is still sending encrypted images. The firmware is quite different from the 4000B, but by looking at patterns in the byte data, I made an educated guess where the “encryption bit” would be in the UareU 4000 firmware. I uploaded the modified version to my device, and sure enough, it now sends unencrypted images.

I’m glad it turned out to be so easy.


Over the last couple of days, I found the time to finish off the dpfp kernel-side driver so that it exports fingerprint data into userspace, to make it easier to investigate the image format.

I had it working relatively easily. Running a small program on /dev/dpfp0 produces 7 data files, one of which is the fingerprint data, the others are interrupt data and other blocks of data that are probably interesting but we don’t know the purpose of.

I was going to leave it at that (others seem to be very interested in the image format), but I thought I might as well have a quick look at the fingerprint data and see if I can find anything interesting. I had glanced at some data previously, but had not done anything with my findings – it’s awkward to work with until you reach the stage where you can obtain data with just a single command.

I noticed the strange structure that I saw before: the data appears to be separated into chunks, each chunk being separated by 26 zero bytes. Each chunk is about 358 bytes long, so I decided that one chunk may be equivalent to one row of pixels in an image.

I noticed that the final part of the transfer ends right in the middle of the zeroes. I also noticed that the number of zeroes between chunks varies a little here and there.

Unusual, but not totally out of the question. Maybe each chunk starts and ends with zeroes, which would mean each chunk starts halfway through these series of zeroes I was seeing. That would explain why the transfer ends halfway through a block of zeroes.

Picturing that in an image scenario (where 0 = black), I realised that this would result in two black columns down the left and right side of the image. I then recalled an image that Jose M Robles sent me recently: a raw image from a fingerprint scanner (not really sure which one) which had black columns down either side. Jose has been doing a fantastic job throwing around theories about the image format, sending me histograms, pixel averages, sample images like that one, etc. Jose’s experiments also seemed to indicate that the encryption was weak, and at this point, things were starting to fall together.

After a few more calculations I decided that the image data starts after a 64-byte header. I also deduced the width (358 + 26 zeroes = 384 pixels) and height (exactly 259 ‘rows’ of pixels are included in the transfer). I cut out the header and replaced it with a PGM header.

I was both happy and amazed to see the result:

No encryption whatsoever, despite DigitalPersona’s claims (PDF).
Update: Those claims may be true. The UareU 4000 isn’t advertised to be included in the MS devices, we just put 2 and 2 together and saw all the simlarities. Now that I have looked closer at the UareU 4000 behaviour, it looks like encryption may be in place on those devices (but not the MS ones).
Another update: I discovered that the devices do support encryption but the Microsoft devices ship with encryption turned off.

This isn’t a real fingerprint scan – I actually scanned one of my toes, to protect the identity of my innocent fingers. Proper scans look more fingerprint-like.

3 imagemagick commands later (invert colours, increase brightness, decrease gamma) and it is perfect for processing:

Fancy stuff. It is lucky that those solid black columns are there, otherwise this wouldn’t have been anything like as obvious. I’ll be rewriting the driver soon, to be more simplistic and to export PGM images straight from the /dev node.

Using git-bisect to find buggy kernel patches

A keen Gentoo user (Ronald) recently came onto IRC, with a strange kernel problem: 2.6.15 only using one of his CPU’s although it sees both, 2.6.14 works fine.

He was keen to investigate the problem himself so I thought now would be a good time to try the git bisect feature for the first time. There were approximately 5500 patches merged between 2.6.14 and 2.6.15, and this method found the offending patch in only 13 reboots (OK – still a high number, I said this guy was keen though!).

This feature is very effective and very easy to use, so I’m going to demonstrate it here. Linus also wrote a nice HOWTO on the topic.

You first have to clone the Linux kernel git repository. This is the same concept checking out a repository from CVS.

# git clone git:// linux-git
# cd linux-git

This directory looks like an ordinary kernel source distribution as you might expect in /usr/src/linux. It also has a hidden .git subdirectory which is where git stores its magical data. Tell git that we want to find a buggy patch through bisection:

# git bisect start

Next, tell git which kernel was the last known-working kernel, and which kernel is known to be not working. To identify these kernels, you can either use the long hexadecimal commit numbers, or you can abbreviate those numbers, or you can refer to tags directly. Linus tags every release with the version number, so the next step is as simple as:

# git bisect bad v2.6.15
# git bisect good v2.6.14

git now runs off and locates the commit exactly halfway between 2.6.14 and 2.6.15. It then “checks out” this tree, so the kernel infront of you is effectively a snapshot from halfway inbetween 2.6.14 and 2.6.15.

Bisecting: 2705 revisions left to test after this
[dd0314f7bb407bc4bdb3ea769b9c8a3a5d39ffd7] fbcon: Initialize new driver when old driver is released

Build that kernel in the normal way, and reboot into it. It works, so we know the bug was introduced after this point. We inform git of this:

# git bisect good

git now discards the whole first half of commits between 2.6.14 and 2.6.15 and bisects the remaining half (the changes after the point we just tested, but before 2.6.15). This is just a simple binary search. git now presents us with a new kernel snapshot (in this case, 3 quarters of the way between 2.6.14 and 2.6.15) and we have to test this.

A couple of kernels later, the search gives us a kernel which exhibits the bug. Telling git about this isn’t any harder:

# git bisect bad

The search continues, with the user telling git if the kernel was “good” or “bad” each time, and several reboots later we end up with the exact patch that introduced the bug:

# git bisect bad
cd8e2b48daee891011a4f21e2c62b210d24dcc9e is first bad commit
diff-tree cd8e2b48daee891011a4f21e2c62b210d24dcc9e (from d2149b542382bfc206cb28485108f6470c979566)
Author: Venkatesh Pallipadi <venkatesh>
Date:   Fri Oct 21 19:22:00 2005 -0400
    [ACPI] fix 2.6.13 boot hang regression on HT box w/ broken BIOS

Ronald filed kernel bug 5930 about this. Usually this stuff is a nightmare to debug, and even though this did require many reboots to locate, it’s definately a step in the right direction. The number of bisections you need to do is obviously less if you have a smaller range to test (e.g. if he’d known that 2.6.15-rc1 was OK and 2.6.15-rc4 was bad, some time would have been saved).

Alauda driver merged

Just a quick entry to point out that my Alauda driver project (a driver for certain XD and SmartMedia card readers) has been merged upstream into Linux 2.6.16-rc1, and will be included and supported in all future releases. That’s one driver out of the way!

Digital Persona Fingerprint driver site launched

I’ve been receiving plenty of emails about the dpfp driver, so I set up a site and mailing list where interested people can keep track of things.

I’ve also recieved a donation of two Digital Persona fingerprint scanners from Gerrie Mansur of Security Database B.V. My keyboard was originally donated by Tony Vroon from Gentoo. Thanks!

I just sent a Status update to the list to get things going. Things are progressing nicely, it won’t be long before we can easily dump fingerprint data to userspace and start a big investigation into the image format.