Posted 16 April 2010 - 01:22 PM
I know it's possible to write a HID blacklist/whitelist but since I don't know enough about it I'm finding it a little tricky.
It may be possible (eg, udev rules on modern linux), but that won't be very effective.
Everything the host (PC, Mac, etc) can know about the USB device is under the device's control. In Teensy (and virtually all microcontrollers with USB), code produces all that data. For example, if you use Arduino/Teensyduino, this code is automatically built into the executable image:
CODE
#define VENDOR_ID 0x16C0
#define PRODUCT_ID 0x0482
static uint8_t PROGMEM device_descriptor[] = {
18, // bLength
1, // bDescriptorType
0x00, 0x02, // bcdUSB
0, // bDeviceClass
0, // bDeviceSubClass
0, // bDeviceProtocol
ENDPOINT0_SIZE, // bMaxPacketSize0
LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
0x00, 0x01, // bcdDevice
It's pretty trivial, even if you have no programming skill, to just find these files, named "usb.c" and "usb_private.h" and edit the USB descriptor data to anything you want.
Less trivial, but not very difficult if you know C, would be changing the code which transmits this data. Instead of reading it from a static array in memory, certain numbers like vendor id, product id, bcdDevice could be created at random, or tried from a list of known common keyboards, or any other algorithm you can craft.
Also possible, but definitely not trivial, would be making use of the detach capability. Most USB devices have a resistor soldered to one of the data lines, which is how the PC knows the device is present. There isn't a physical switch in the connector, it's that resistor which signals a device is plugged in. In the AVR USB chip on Teensy, that resistor is under software control. In fact, every time you reprogram Teensy, that resistor is disconnected and then reconnected, which is to your PC looks like the old device was physically unplugged, and then moments later a completely new device (implementing the ability to download your new code) gets connected. After your code cownload, the same thing happens again. That's how you can so easily try new USB devices with Teensy.... every time you reboot your code, your machine believes the device was physically unplugged and then a new device gets plugged in.
With the detach capability under your code's control, if you don't get the desired results, you could just detach and try again (maybe much later... the PC can't tell you're still physically present), perhaps with new randomly generated ID numbers or some other strategy.
A whitelist/blacklist defense just doesn't have any trustable data available.
Ultimately, blind trust in HID keyboards is the weakness. Perhaps a solution would might involve a one-time authorization process for a new keyboard? But who do you trust for user input to authorize a new keyboard? The USB HID mouse?!?
And if an attacker has physical access, what's to stop them from momentarily unplugging the trusted keyboard and using another machine to capture all its USB descriptors? For example, my "ID 05AC:0220 Apple, Inc. Aluminum Keyboard" returns an empty field for the optional USB serial number. Even if it did have a serial number, it's right there to read and copy.
USB HID doesn't have any challenge/response authentication, so all trusted data could be easily captured. Perhaps public key signature capability to prove a device's unique identity would give you something useful to trust the device hasn't been copied. It seems pretty unlikely keyboards will get that class of hardware anyday soon!
Security is difficult.... much harder than just designing working USB devices.
Edited by Paul Stoffregen, 16 April 2010 - 01:27 PM.