@ -29,27 +29,18 @@
# 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_MAIN_IN (0x81)
# define ENDPOINT_ADDRESS_MAIN_OUT (0x01)
# if DEBUG_LINK
# define ENDPOINT_ADDRESS_IN (0x81)
# define ENDPOINT_ADDRESS_OUT (0x01)
# 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)
@ -59,7 +50,7 @@
X ( SERIAL_NUMBER , storage_uuid_str ) \
X ( INTERFACE_MAIN , " TREZOR Interface " ) \
X ( INTERFACE_DEBUG , " TREZOR Debug Link Interface " ) \
X ( INTERFACE_U2F , " TREZOR U2F Interface" ) \
X ( INTERFACE_U2F , " U2F Interface" )
# define X(name, value) USB_STRING_##name,
enum {
@ -77,20 +68,60 @@ static const char *usb_strings[] = {
static const struct usb_device_descriptor dev_descr = {
. bLength = USB_DT_DEVICE_SIZE ,
. bDescriptorType = USB_DT_DEVICE ,
. bcdUSB = 0x02 1 0,
. bcdUSB = 0x02 0 0,
. bDeviceClass = 0 ,
. bDeviceSubClass = 0 ,
. bDeviceProtocol = 0 ,
. bMaxPacketSize0 = 64 ,
. idVendor = 0x534c ,
. idProduct = 0x0001 ,
. bcdDevice = 0x0 2 00,
. bcdDevice = 0x0 1 00,
. 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)
@ -110,6 +141,26 @@ 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 {
@ -130,112 +181,109 @@ static const struct {
}
} ;
static const struct usb_endpoint_descriptor hid_endpoints_u2f [ 2 ] = { {
static const struct usb_endpoint_descriptor hid_endpoints [ 2 ] = { {
. bLength = USB_DT_ENDPOINT_SIZE ,
. bDescriptorType = USB_DT_ENDPOINT ,
. bEndpointAddress = ENDPOINT_ADDRESS_ U2F_ IN,
. 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_ U2F_ OUT,
. bEndpointAddress = ENDPOINT_ADDRESS_ OUT,
. bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT ,
. wMaxPacketSize = 64 ,
. bInterval = 1 ,
} } ;
static const struct usb_interface_descriptor hid_iface _u2f [ ] = { {
static const struct usb_interface_descriptor hid_iface [ ] = { {
. bLength = USB_DT_INTERFACE_SIZE ,
. bDescriptorType = USB_DT_INTERFACE ,
. bInterfaceNumber = USB_INTERFACE_INDEX_ U2F ,
. bInterfaceNumber = USB_INTERFACE_INDEX_ MAIN ,
. bAlternateSetting = 0 ,
. bNumEndpoints = 2 ,
. bInterfaceClass = USB_CLASS_HID ,
. bInterfaceSubClass = 0 ,
. bInterfaceProtocol = 0 ,
. iInterface = USB_STRING_INTERFACE_ U2F ,
. endpoint = hid_endpoints _u2f ,
. extra = & hid_function _u2f ,
. extralen = sizeof ( hid_function _u2f ) ,
. iInterface = USB_STRING_INTERFACE_ MAIN ,
. endpoint = hid_endpoints ,
. extra = & hid_function ,
. extralen = sizeof ( hid_function ) ,
} } ;
# if DEBUG_LINK
static const struct usb_endpoint_descriptor webusb_endpoints_debug [ 2 ] = { {
static const struct usb_endpoint_descriptor hid_endpoints_u2f [ 2 ] = { {
. bLength = USB_DT_ENDPOINT_SIZE ,
. bDescriptorType = USB_DT_ENDPOINT ,
. bEndpointAddress = ENDPOINT_ADDRESS_ DEBUG _IN,
. bEndpointAddress = ENDPOINT_ADDRESS_ U2F _IN,
. bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT ,
. wMaxPacketSize = 64 ,
. bInterval = 1 ,
. bInterval = 2 ,
} , {
. bLength = USB_DT_ENDPOINT_SIZE ,
. bDescriptorType = USB_DT_ENDPOINT ,
. bEndpointAddress = ENDPOINT_ADDRESS_ DEBUG _OUT,
. bEndpointAddress = ENDPOINT_ADDRESS_ U2F _OUT,
. bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT ,
. wMaxPacketSize = 64 ,
. bInterval = 1 ,
. bInterval = 2 ,
} } ;
static const struct usb_interface_descriptor webusb_iface_debug [ ] = { {
static const struct usb_interface_descriptor hid_iface_u2f [ ] = { {
. bLength = USB_DT_INTERFACE_SIZE ,
. bDescriptorType = USB_DT_INTERFACE ,
. bInterfaceNumber = USB_INTERFACE_INDEX_ DEBUG ,
. bInterfaceNumber = USB_INTERFACE_INDEX_ U2F ,
. bAlternateSetting = 0 ,
. bNumEndpoints = 2 ,
. bInterfaceClass = USB_CLASS_ VENDOR ,
. bInterfaceClass = USB_CLASS_ HID ,
. bInterfaceSubClass = 0 ,
. bInterfaceProtocol = 0 ,
. iInterface = USB_STRING_INTERFACE_ DEBUG ,
. endpoint = webusb_endpoints_debug ,
. extra = NULL ,
. extralen = 0 ,
. iInterface = USB_STRING_INTERFACE_ U2F ,
. endpoint = hid_endpoints_u2f ,
. extra = & hid_function_u2f ,
. extralen = sizeof ( hid_function_u2f ) ,
} } ;
# endif
static const struct usb_endpoint_descriptor webusb_endpoints_main [ 2 ] = { {
# if DEBUG_LINK
static const struct usb_endpoint_descriptor hid_endpoints_debug [ 2 ] = { {
. bLength = USB_DT_ENDPOINT_SIZE ,
. bDescriptorType = USB_DT_ENDPOINT ,
. bEndpointAddress = ENDPOINT_ADDRESS_ MAIN _IN,
. bEndpointAddress = ENDPOINT_ADDRESS_ DEBUG _IN,
. bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT ,
. wMaxPacketSize = 64 ,
. bInterval = 1 ,
} , {
. bLength = USB_DT_ENDPOINT_SIZE ,
. bDescriptorType = USB_DT_ENDPOINT ,
. bEndpointAddress = ENDPOINT_ADDRESS_ MAIN _OUT,
. bEndpointAddress = ENDPOINT_ADDRESS_ DEBUG _OUT,
. bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT ,
. wMaxPacketSize = 64 ,
. bInterval = 1 ,
} } ;
static const struct usb_interface_descriptor webusb_iface_main [ ] = { {
static const struct usb_interface_descriptor hid_iface_debug [ ] = { {
. bLength = USB_DT_INTERFACE_SIZE ,
. bDescriptorType = USB_DT_INTERFACE ,
. bInterfaceNumber = USB_INTERFACE_INDEX_ MAIN ,
. bInterfaceNumber = USB_INTERFACE_INDEX_ DEBUG ,
. bAlternateSetting = 0 ,
. bNumEndpoints = 2 ,
. bInterfaceClass = USB_CLASS_ VENDOR ,
. bInterfaceClass = USB_CLASS_ HID ,
. bInterfaceSubClass = 0 ,
. bInterfaceProtocol = 0 ,
. iInterface = USB_STRING_INTERFACE_ MAIN ,
. endpoint = webusb_endpoints_main ,
. extra = NULL ,
. extralen = 0 ,
. iInterface = USB_STRING_INTERFACE_ DEBUG ,
. endpoint = hid_endpoints_debug ,
. extra = & hid_function ,
. extralen = sizeof ( hid_function ) ,
} } ;
# endif
// Windows are strict about interfaces appearing
// in correct order
static const struct usb_interface ifaces [ ] = { {
. num_altsetting = 1 ,
. altsetting = webusb_iface_main ,
. altsetting = hid_iface ,
# if DEBUG_LINK
} , {
. num_altsetting = 1 ,
. altsetting = webusb _iface_debug,
. altsetting = hid _iface_debug,
# endif
} , {
. num_altsetting = 1 ,
@ -246,7 +294,11 @@ static const struct usb_config_descriptor config = {
. bLength = USB_DT_CONFIGURATION_SIZE ,
. bDescriptorType = USB_DT_CONFIGURATION ,
. wTotalLength = 0 ,
. bNumInterfaces = USB_INTERFACE_COUNT ,
# if DEBUG_LINK
. bNumInterfaces = 3 ,
# else
. bNumInterfaces = 2 ,
# endif
. bConfigurationValue = 1 ,
. iConfiguration = 0 ,
. bmAttributes = 0x80 ,
@ -260,24 +312,40 @@ 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 ;
debugLog ( 0 , " " , " hid_control_request u2f " ) ;
* buf = ( uint8_t * ) hid_report_descriptor_u2f ;
* len = MIN ( * len , sizeof ( hid_report_descriptor_u2f ) ) ;
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 ) ;
return 1 ;
}
static volatile char tiny = 0 ;
static void main_rx_callback ( usbd_device * dev , uint8_t ep )
static void hid _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_MAIN_OUT , buf , 64 ) ! = 64 ) return ;
debugLog ( 0 , " " , " main_rx_callback " ) ;
if ( usbd_ep_read_packet ( dev , ENDPOINT_ADDRESS_ OUT, buf , 64 ) ! = 64 ) return ;
debugLog ( 0 , " " , " hid _rx_callback" ) ;
if ( ! tiny ) {
msg_read ( buf , 64 ) ;
} else {
@ -285,23 +353,23 @@ static void main_rx_callback(usbd_device *dev, uint8_t ep)
}
}
static void u2f_rx_callback( usbd_device * dev , uint8_t ep )
static void hid_ u2f_rx_callback( usbd_device * dev , uint8_t ep )
{
( void ) ep ;
static CONFIDENTIAL uint8_t buf [ 64 ] __attribute__ ( ( aligned ( 4 ) ) ) ;
debugLog ( 0 , " " , " u2f_rx_callback" ) ;
debugLog ( 0 , " " , " hid_ 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 debug_rx_callback( usbd_device * dev , uint8_t ep )
static void hid_ 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 , " " , " debug_rx_callback" ) ;
debugLog ( 0 , " " , " hid_ debug_rx_callback" ) ;
if ( ! tiny ) {
msg_debug_read ( buf , 64 ) ;
} else {
@ -310,17 +378,17 @@ static void debug_rx_callback(usbd_device *dev, uint8_t ep)
}
# endif
static void set_config( usbd_device * dev , uint16_t wValue )
static void hid_ set_config( usbd_device * dev , uint16_t wValue )
{
( void ) wValue ;
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_ 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_U2F_IN , USB_ENDPOINT_ATTR_INTERRUPT , 64 , 0 ) ;
usbd_ep_setup ( dev , ENDPOINT_ADDRESS_U2F_OUT , USB_ENDPOINT_ATTR_INTERRUPT , 64 , u2f_rx_callback) ;
usbd_ep_setup ( dev , ENDPOINT_ADDRESS_U2F_OUT , USB_ENDPOINT_ATTR_INTERRUPT , 64 , hid_ 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 , debug_rx_callback) ;
usbd_ep_setup ( dev , ENDPOINT_ADDRESS_DEBUG_OUT , USB_ENDPOINT_ATTR_INTERRUPT , 64 , hid_ debug_rx_callback) ;
# endif
usbd_register_control_callback (
@ -331,29 +399,12 @@ static void set_config(usbd_device *dev, uint16_t wValue)
}
static usbd_device * usbd_dev ;
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
} ;
static uint8_t usbd_control_buffer [ 128 ] ;
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 , 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 ) ;
usbd_register_set_config_callback ( usbd_dev , hid_set_config ) ;
}
void usbPoll ( void )
@ -364,7 +415,7 @@ void usbPoll(void)
// write pending data
data = msg_out_data ( ) ;
if ( data ) {
while ( usbd_ep_write_packet ( usbd_dev , ENDPOINT_ADDRESS_ MAIN_ IN, data , 64 ) ! = 64 ) { }
while ( usbd_ep_write_packet ( usbd_dev , ENDPOINT_ADDRESS_ IN, data , 64 ) ! = 64 ) { }
}
data = u2f_out_data ( ) ;
if ( data ) {