Παρασκευή 10 Ιουλίου 2015

Writing a new USB interface

As I've stated elsewhere, my GSoC project involves getting the Nitrokey, which is a USB device made for secure, cryptographic operations, to work with the U2F second-factor authentication protocol. The FIDO Alliance, which is the organization behind the U2F Standard, has published the specifications of how the host recognizes a U2F device and how these two communicate with each other. In this post I'm going to explain some basic things I learned about the USB implementation, just enough to be able to follow what changes I have made to the device to be able to work with U2F.

Each USB device has some basic structures, called descriptors, which identify the device at the host during device discovery. At the most basic level, there is the Device Descriptor, which holds some basic information about the device itself. It starts with a byte indicating the length of the descriptor - for the device descriptor it's a a fixed number, but it will come to play for other types of descriptors - and some of the most useful information in the device descriptor would be the Vendor ID and Product ID. Given these two, the host can apply device-specific rules, for example custom rules in /etc/udev/rules.d/ on a Linux machine. Some other information would be the location of some strings indicating the name of the device or the manufacturer. All this talking between the host and the device is made using the Control Endpoint 0. An endpoint is more or less like an assigned buffered by which either the host puts data to transmit (OUT request), or the device sends data to the host (IN request). When it comes to control purposes (and getting the descriptors are in this category), all transactions are made through the Endpoint 0 and have a standard format and vocabulary which is detailed in the USB specification documents.

When the host has sent a GET DEVICE DESCRIPTOR request and has successfully got a GET DEVICE DESCRIPTOR response, then it has to learn about the configuration of the device. To be able to explain what a configuration is, I think I have to talk about interfaces first. A USB interface is a set of device characteristics that constitute a functionality by itself. For example, let's suppose we have a USB wireless desktop on our computer, that includes a mouse and a keyboard. The use of the keyboard is completely separated by the use of the mouse, in fact we can move the pointer as we type with no problem. But the keyboard and mouse are communicating with the host using one USB port, so how can the host tell that some things are keyboard data and others mouse data? That's where the interfaces come to play. We have two different interfaces in this example, one a keyboard interface and one as a mouse interface. You can actually tell that in your hardware options, for example in Windows you will see a different icon for the mouse and a different one for the keyboard. These are two different logical entities and of course we can expect that somehow the host has some information about how each interface is reporting or consuming data.

I think I'll leave the rest for another blog post. Have in mind what a USB interface is though, cause it will be important when I'll describe the configuration of a USB device.

Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου