From cb067bd14c57445430fbaa4da8c77badf0d1f772 Mon Sep 17 00:00:00 2001 From: Karel Bilek Date: Sun, 17 Dec 2017 04:28:13 +0100 Subject: [PATCH] Switch from HID to WebUSB Also renaming varions functions from hid_ to webusb_ to actually reflect what they are doing --- firmware/usb.c | 241 +++++++++++++++++++------------------------------ 1 file changed, 95 insertions(+), 146 deletions(-) diff --git a/firmware/usb.c b/firmware/usb.c index 7a59b6fa0..ee8e3406c 100644 --- a/firmware/usb.c +++ b/firmware/usb.c @@ -29,18 +29,27 @@ #include "util.h" #include "timer.h" +#include "usb21_standard.h" +#include "webusb.h" +#include "winusb.h" + + #define USB_INTERFACE_INDEX_MAIN 0 #if DEBUG_LINK #define USB_INTERFACE_INDEX_DEBUG 1 #define USB_INTERFACE_INDEX_U2F 2 +#define USB_INTERFACE_COUNT 3 #else #define USB_INTERFACE_INDEX_U2F 1 +#define USB_INTERFACE_COUNT 2 #endif -#define ENDPOINT_ADDRESS_IN (0x81) -#define ENDPOINT_ADDRESS_OUT (0x01) +#define ENDPOINT_ADDRESS_MAIN_IN (0x81) +#define ENDPOINT_ADDRESS_MAIN_OUT (0x01) +#if DEBUG_LINK #define ENDPOINT_ADDRESS_DEBUG_IN (0x82) #define ENDPOINT_ADDRESS_DEBUG_OUT (0x02) +#endif #define ENDPOINT_ADDRESS_U2F_IN (0x83) #define ENDPOINT_ADDRESS_U2F_OUT (0x03) @@ -50,7 +59,7 @@ X(SERIAL_NUMBER, storage_uuid_str) \ X(INTERFACE_MAIN, "TREZOR Interface") \ X(INTERFACE_DEBUG, "TREZOR Debug Link Interface") \ - X(INTERFACE_U2F, "U2F Interface") + X(INTERFACE_U2F, "TREZOR U2F Interface") \ #define X(name, value) USB_STRING_##name, enum { @@ -68,60 +77,20 @@ static const char *usb_strings[] = { static const struct usb_device_descriptor dev_descr = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = 0x0200, + .bcdUSB = 0x0210, .bDeviceClass = 0, .bDeviceSubClass = 0, .bDeviceProtocol = 0, .bMaxPacketSize0 = 64, .idVendor = 0x534c, .idProduct = 0x0001, - .bcdDevice = 0x0100, + .bcdDevice = 0x0200, .iManufacturer = USB_STRING_MANUFACTURER, .iProduct = USB_STRING_PRODUCT, .iSerialNumber = USB_STRING_SERIAL_NUMBER, .bNumConfigurations = 1, }; -static const uint8_t hid_report_descriptor[] = { - 0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined) - 0x09, 0x01, // USAGE (1) - 0xa1, 0x01, // COLLECTION (Application) - 0x09, 0x20, // USAGE (Input Report Data) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x40, // REPORT_COUNT (64) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0x09, 0x21, // USAGE (Output Report Data) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x40, // REPORT_COUNT (64) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - 0xc0 // END_COLLECTION -}; - -#if DEBUG_LINK -static const uint8_t hid_report_descriptor_debug[] = { - 0x06, 0x01, 0xff, // USAGE_PAGE (Vendor Defined) - 0x09, 0x01, // USAGE (1) - 0xa1, 0x01, // COLLECTION (Application) - 0x09, 0x20, // USAGE (Input Report Data) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x40, // REPORT_COUNT (64) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0x09, 0x21, // USAGE (Output Report Data) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x40, // REPORT_COUNT (64) - 0x91, 0x02, // OUTPUT (Data,Var,Abs) - 0xc0 // END_COLLECTION -}; -#endif - static const uint8_t hid_report_descriptor_u2f[] = { 0x06, 0xd0, 0xf1, // USAGE_PAGE (FIDO Alliance) 0x09, 0x01, // USAGE (U2F HID Authenticator Device) @@ -141,26 +110,6 @@ static const uint8_t hid_report_descriptor_u2f[] = { 0xc0 // END_COLLECTION }; -static const struct { - struct usb_hid_descriptor hid_descriptor; - struct { - uint8_t bReportDescriptorType; - uint16_t wDescriptorLength; - } __attribute__((packed)) hid_report; -} __attribute__((packed)) hid_function = { - .hid_descriptor = { - .bLength = sizeof(hid_function), - .bDescriptorType = USB_DT_HID, - .bcdHID = 0x0111, - .bCountryCode = 0, - .bNumDescriptors = 1, - }, - .hid_report = { - .bReportDescriptorType = USB_DT_REPORT, - .wDescriptorLength = sizeof(hid_report_descriptor), - } -}; - static const struct { struct usb_hid_descriptor hid_descriptor_u2f; struct { @@ -181,38 +130,6 @@ static const struct { } }; - -static const struct usb_endpoint_descriptor hid_endpoints[2] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = ENDPOINT_ADDRESS_IN, - .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, - .wMaxPacketSize = 64, - .bInterval = 1, -}, { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = ENDPOINT_ADDRESS_OUT, - .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, - .wMaxPacketSize = 64, - .bInterval = 1, -}}; - -static const struct usb_interface_descriptor hid_iface[] = {{ - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = USB_INTERFACE_INDEX_MAIN, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_HID, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = USB_STRING_INTERFACE_MAIN, - .endpoint = hid_endpoints, - .extra = &hid_function, - .extralen = sizeof(hid_function), -}}; - static const struct usb_endpoint_descriptor hid_endpoints_u2f[2] = {{ .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -245,7 +162,7 @@ static const struct usb_interface_descriptor hid_iface_u2f[] = {{ }}; #if DEBUG_LINK -static const struct usb_endpoint_descriptor hid_endpoints_debug[2] = {{ +static const struct usb_endpoint_descriptor webusb_endpoints_debug[2] = {{ .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = ENDPOINT_ADDRESS_DEBUG_IN, @@ -261,29 +178,64 @@ static const struct usb_endpoint_descriptor hid_endpoints_debug[2] = {{ .bInterval = 1, }}; -static const struct usb_interface_descriptor hid_iface_debug[] = {{ +static const struct usb_interface_descriptor webusb_iface_debug[] = {{ .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, .bInterfaceNumber = USB_INTERFACE_INDEX_DEBUG, .bAlternateSetting = 0, .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_HID, + .bInterfaceClass = USB_CLASS_VENDOR, .bInterfaceSubClass = 0, .bInterfaceProtocol = 0, .iInterface = USB_STRING_INTERFACE_DEBUG, - .endpoint = hid_endpoints_debug, - .extra = &hid_function, - .extralen = sizeof(hid_function), + .endpoint = webusb_endpoints_debug, + .extra = NULL, + .extralen = 0, }}; + #endif +static const struct usb_endpoint_descriptor webusb_endpoints_main[2] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = ENDPOINT_ADDRESS_MAIN_IN, + .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, + .wMaxPacketSize = 64, + .bInterval = 2, +}, { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = ENDPOINT_ADDRESS_MAIN_OUT, + .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, + .wMaxPacketSize = 64, + .bInterval = 2, +}}; + +static const struct usb_interface_descriptor webusb_iface_main[] = {{ + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = USB_INTERFACE_INDEX_MAIN, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_VENDOR, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = USB_STRING_INTERFACE_MAIN, + .endpoint = webusb_endpoints_main, + .extra = NULL, + .extralen = 0, +}}; + + +// Windows are strict about interfaces appearing +// in correct order static const struct usb_interface ifaces[] = {{ .num_altsetting = 1, - .altsetting = hid_iface, + .altsetting = webusb_iface_main, #if DEBUG_LINK }, { .num_altsetting = 1, - .altsetting = hid_iface_debug, + .altsetting = webusb_iface_debug, #endif }, { .num_altsetting = 1, @@ -294,11 +246,7 @@ static const struct usb_config_descriptor config = { .bLength = USB_DT_CONFIGURATION_SIZE, .bDescriptorType = USB_DT_CONFIGURATION, .wTotalLength = 0, -#if DEBUG_LINK - .bNumInterfaces = 3, -#else - .bNumInterfaces = 2, -#endif + .bNumInterfaces = USB_INTERFACE_COUNT, .bConfigurationValue = 1, .iConfiguration = 0, .bmAttributes = 0x80, @@ -312,40 +260,24 @@ static int hid_control_request(usbd_device *dev, struct usb_setup_data *req, uin (void)dev; if ((req->bmRequestType != 0x81) || - (req->bRequest != USB_REQ_GET_DESCRIPTOR) || - (req->wValue != 0x2200)) + (req->bRequest != USB_REQ_GET_DESCRIPTOR) || + (req->wValue != 0x2200)) return 0; - if (req->wIndex == USB_INTERFACE_INDEX_U2F) { - debugLog(0, "", "hid_control_request u2f"); - *buf = (uint8_t *)hid_report_descriptor_u2f; - *len = sizeof(hid_report_descriptor_u2f); - return 1; - } - -#if DEBUG_LINK - if (req->wIndex == USB_INTERFACE_INDEX_DEBUG) { - debugLog(0, "", "hid_control_request debug"); - *buf = (uint8_t *)hid_report_descriptor_debug; - *len = sizeof(hid_report_descriptor_debug); - return 1; - } -#endif - - debugLog(0, "", "hid_control_request main"); - *buf = (uint8_t *)hid_report_descriptor; - *len = sizeof(hid_report_descriptor); + debugLog(0, "", "hid_control_request u2f"); + *buf = (uint8_t *)hid_report_descriptor_u2f; + *len = MIN(*len, sizeof(hid_report_descriptor_u2f)); return 1; } static volatile char tiny = 0; -static void hid_rx_callback(usbd_device *dev, uint8_t ep) +static void main_rx_callback(usbd_device *dev, uint8_t ep) { (void)ep; static CONFIDENTIAL uint8_t buf[64] __attribute__ ((aligned(4))); - if ( usbd_ep_read_packet(dev, ENDPOINT_ADDRESS_OUT, buf, 64) != 64) return; - debugLog(0, "", "hid_rx_callback"); + if ( usbd_ep_read_packet(dev, ENDPOINT_ADDRESS_MAIN_OUT, buf, 64) != 64) return; + debugLog(0, "", "main_rx_callback"); if (!tiny) { msg_read(buf, 64); } else { @@ -353,23 +285,23 @@ static void hid_rx_callback(usbd_device *dev, uint8_t ep) } } -static void hid_u2f_rx_callback(usbd_device *dev, uint8_t ep) +static void u2f_rx_callback(usbd_device *dev, uint8_t ep) { (void)ep; static CONFIDENTIAL uint8_t buf[64] __attribute__ ((aligned(4))); - debugLog(0, "", "hid_u2f_rx_callback"); + debugLog(0, "", "u2f_rx_callback"); if ( usbd_ep_read_packet(dev, ENDPOINT_ADDRESS_U2F_OUT, buf, 64) != 64) return; u2fhid_read(tiny, (const U2FHID_FRAME *) (void*) buf); } #if DEBUG_LINK -static void hid_debug_rx_callback(usbd_device *dev, uint8_t ep) +static void debug_rx_callback(usbd_device *dev, uint8_t ep) { (void)ep; static CONFIDENTIAL uint8_t buf[64] __attribute__ ((aligned(4))); if ( usbd_ep_read_packet(dev, ENDPOINT_ADDRESS_DEBUG_OUT, buf, 64) != 64) return; - debugLog(0, "", "hid_debug_rx_callback"); + debugLog(0, "", "debug_rx_callback"); if (!tiny) { msg_debug_read(buf, 64); } else { @@ -378,17 +310,17 @@ static void hid_debug_rx_callback(usbd_device *dev, uint8_t ep) } #endif -static void hid_set_config(usbd_device *dev, uint16_t wValue) +static void set_config(usbd_device *dev, uint16_t wValue) { (void)wValue; - usbd_ep_setup(dev, ENDPOINT_ADDRESS_IN, USB_ENDPOINT_ATTR_INTERRUPT, 64, 0); - usbd_ep_setup(dev, ENDPOINT_ADDRESS_OUT, USB_ENDPOINT_ATTR_INTERRUPT, 64, hid_rx_callback); + usbd_ep_setup(dev, ENDPOINT_ADDRESS_MAIN_IN, USB_ENDPOINT_ATTR_INTERRUPT, 64, 0); + usbd_ep_setup(dev, ENDPOINT_ADDRESS_MAIN_OUT, USB_ENDPOINT_ATTR_INTERRUPT, 64, main_rx_callback); usbd_ep_setup(dev, ENDPOINT_ADDRESS_U2F_IN, USB_ENDPOINT_ATTR_INTERRUPT, 64, 0); - usbd_ep_setup(dev, ENDPOINT_ADDRESS_U2F_OUT, USB_ENDPOINT_ATTR_INTERRUPT, 64, hid_u2f_rx_callback); + usbd_ep_setup(dev, ENDPOINT_ADDRESS_U2F_OUT, USB_ENDPOINT_ATTR_INTERRUPT, 64, u2f_rx_callback); #if DEBUG_LINK usbd_ep_setup(dev, ENDPOINT_ADDRESS_DEBUG_IN, USB_ENDPOINT_ATTR_INTERRUPT, 64, 0); - usbd_ep_setup(dev, ENDPOINT_ADDRESS_DEBUG_OUT, USB_ENDPOINT_ATTR_INTERRUPT, 64, hid_debug_rx_callback); + usbd_ep_setup(dev, ENDPOINT_ADDRESS_DEBUG_OUT, USB_ENDPOINT_ATTR_INTERRUPT, 64, debug_rx_callback); #endif usbd_register_control_callback( @@ -399,12 +331,29 @@ static void hid_set_config(usbd_device *dev, uint16_t wValue) } static usbd_device *usbd_dev; -static uint8_t usbd_control_buffer[128]; +static uint8_t usbd_control_buffer[256] __attribute__ ((aligned (2))); + +static const struct usb_device_capability_descriptor* capabilities[] = { + (const struct usb_device_capability_descriptor*)&webusb_platform_capability_descriptor, +}; + +static const struct usb_bos_descriptor bos_descriptor = { + .bLength = USB_DT_BOS_SIZE, + .bDescriptorType = USB_DT_BOS, + .bNumDeviceCaps = sizeof(capabilities)/sizeof(capabilities[0]), + .capabilities = capabilities +}; void usbInit(void) { usbd_dev = usbd_init(&otgfs_usb_driver, &dev_descr, &config, usb_strings, sizeof(usb_strings) / sizeof(*usb_strings), usbd_control_buffer, sizeof(usbd_control_buffer)); - usbd_register_set_config_callback(usbd_dev, hid_set_config); + usbd_register_set_config_callback(usbd_dev, set_config); + usb21_setup(usbd_dev, &bos_descriptor); + static const char* origin_url = "trezor.io/start"; + webusb_setup(usbd_dev, origin_url); + // Debug link interface does not have WinUSB set; + // if you really need debug link on windows, edit the descriptor in winusb.c + winusb_setup(usbd_dev, USB_INTERFACE_INDEX_MAIN); } void usbPoll(void) @@ -415,7 +364,7 @@ void usbPoll(void) // write pending data data = msg_out_data(); if (data) { - while ( usbd_ep_write_packet(usbd_dev, ENDPOINT_ADDRESS_IN, data, 64) != 64 ) {} + while ( usbd_ep_write_packet(usbd_dev, ENDPOINT_ADDRESS_MAIN_IN, data, 64) != 64 ) {} } data = u2f_out_data(); if (data) {