1 // Copyright 2024 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use usb_util::DescriptorType; 6 7 // How long it takes for the security key to become inactive and time out all previously pending 8 // transactions since last activity. 9 pub const TRANSACTION_TIMEOUT_MILLIS: u64 = 120_000; 10 11 // How long to wait before timing out and canceling a USB transfer from the guest if the host 12 // security key is unresponsive. 13 pub const USB_TRANSFER_TIMEOUT_MILLIS: u64 = 5_000; 14 15 // 5ms is the default USB interrupt polling rate according to specs. 16 pub const USB_POLL_RATE_MILLIS: u64 = 5; 17 18 // Some applications expect a very short RTT when handling packets between host key and guest, half 19 // a millisecond seems like a decent compromise. 20 pub const PACKET_POLL_RATE_NANOS: u64 = 50_000; 21 22 // Total max number of transactions we can hold in our key. Any more transactions will push older 23 // transactions away from the stack. 24 pub const MAX_TRANSACTIONS: usize = 4; 25 26 // Max number of incoming packets still to be processed by the guest 27 pub const U2FHID_MAX_IN_PENDING: usize = 32; 28 29 pub const U2FHID_PACKET_SIZE: usize = 64; 30 pub const PACKET_INIT_HEADER_SIZE: usize = 7; 31 pub const PACKET_CONT_HEADER_SIZE: usize = 5; 32 pub const PACKET_INIT_DATA_SIZE: usize = U2FHID_PACKET_SIZE - PACKET_INIT_HEADER_SIZE; 33 pub const PACKET_CONT_DATA_SIZE: usize = U2FHID_PACKET_SIZE - PACKET_CONT_HEADER_SIZE; 34 pub const BROADCAST_CID: u32 = 0xFFFFFFFF; 35 36 pub const NONCE_SIZE: usize = 8; 37 pub const EMPTY_NONCE: [u8; NONCE_SIZE] = [0u8; NONCE_SIZE]; 38 39 // It's a valid init packet only if the 7th bit of the cmd field is set 40 pub const PACKET_INIT_VALID_CMD: u8 = 0b1000_0000; 41 pub const U2FHID_ERROR_CMD: u8 = 0xBF; 42 43 pub const U2FHID_CONTROL_ENDPOINT: u8 = 0x00; 44 pub const U2FHID_IN_ENDPOINT: u8 = 0x81; 45 pub const U2FHID_OUT_ENDPOINT: u8 = 0x01; 46 47 // Generic HID commands 48 pub const HID_GET_IDLE: u8 = 0x02; 49 pub const HID_SET_IDLE: u8 = 0x0A; 50 pub const HID_GET_REPORT_DESC: u8 = 0x22; 51 52 pub const HID_MAX_DESCRIPTOR_SIZE: usize = 4096; 53 54 // Descriptor data taken from: https://github.com/gl-sergei/u2f-token/blob/master/src/usb-hid.c 55 // With minor modifications for our own PID and VID and other strings 56 pub const U2FHID_DEVICE_DESC: &[u8] = &[ 57 18, 58 DescriptorType::Device as u8, 59 0x10, 60 0x01, 61 0x00, 62 0x00, 63 0x00, 64 0x40, 65 // Google Vendor ID 66 0xd1, 67 0x18, 68 // Unique Product ID 69 0xd0, 70 0xf1, 71 0x00, 72 0x01, 73 0, 74 0, 75 0, 76 1, 77 ]; 78 79 pub const HID_REPORT_DESC_HEADER: &[u8] = &[ 80 0x06, 0xd0, 0xf1, // Usage Page (FIDO) 81 0x09, 0x01, // Usage (FIDO) 82 ]; 83 84 pub const U2FHID_CONFIG_DESC: &[u8] = &[ 85 9, 86 DescriptorType::Configuration as u8, 87 /* Configuration Descriptor. */ 88 41, 89 0x00, /* wTotalLength. */ 90 0x01, /* bNumInterfaces. */ 91 0x01, /* bConfigurationValue. */ 92 0, /* iConfiguration. */ 93 0x80, /* bmAttributes. */ 94 15, /* bMaxPower (100mA). */ 95 /* Interface Descriptor. */ 96 9, /* bLength: Interface Descriptor size */ 97 DescriptorType::Interface as u8, 98 0, /* bInterfaceNumber: Number of Interface */ 99 0x00, /* bAlternateSetting: Alternate setting */ 100 0x02, /* bNumEndpoints: Two endpoints used */ 101 0x03, /* bInterfaceClass: HID */ 102 0x00, /* bInterfaceSubClass: no boot */ 103 0x00, /* bInterfaceProtocol: 0=none */ 104 0x00, /* iInterface */ 105 /* HID Descriptor. */ 106 9, /* bLength: HID Descriptor size */ 107 0x21, /* bDescriptorType: HID */ 108 0x10, 109 0x01, /* bcdHID: HID Class Spec release number */ 110 0x00, /* bCountryCode: Hardware target country */ 111 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ 112 0x22, /* bDescriptorType */ 113 0x22, 114 0, /* wItemLength: Total length of Report descriptor */ 115 /* Endpoint IN1 Descriptor */ 116 7, /* bLength: Endpoint Descriptor size */ 117 DescriptorType::Endpoint as u8, 118 0x81, /* bEndpointAddress: (IN1) */ 119 0x03, /* bmAttributes: Interrupt */ 120 0x40, 121 0x00, /* wMaxPacketSize: 64 */ 122 0x05, /* bInterval (5ms) */ 123 /* Endpoint OUT1 Descriptor */ 124 7, /* bLength: Endpoint Descriptor size */ 125 DescriptorType::Endpoint as u8, 126 0x01, /* bEndpointAddress: (OUT1) */ 127 0x03, /* bmAttributes: Interrupt */ 128 0x40, 129 0x00, /* wMaxPacketSize: 64 */ 130 0x05, /* bInterval (5ms) */ 131 ]; 132 133 pub const HID_REPORT_DESC: &[u8] = &[ 134 0x06, 0xd0, 0xf1, /* USAGE_PAGE (FIDO Alliance) */ 135 0x09, 0x01, /* USAGE (Keyboard) */ 136 0xa1, 0x01, /* COLLECTION (Application) */ 137 0x09, 0x20, /* USAGE (Input report data) */ 138 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 139 0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ 140 0x75, 0x08, /* REPORT_SIZE (8) */ 141 0x95, 0x40, /* REPORT_COUNT (64) */ 142 0x81, 0x02, /* INPUT (Data,Var,Abs); Modifier byte */ 143 0x09, 0x21, /* USAGE (Output report data) */ 144 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 145 0x26, 0xff, 0x00, /* LOGICAL_MAXIMUM (255) */ 146 0x75, 0x08, /* REPORT_SIZE (8) */ 147 0x95, 0x40, /* REPORT_COUNT (64) */ 148 0x91, 0x02, /* OUTPUT (Data,Var,Abs); Modifier byte */ 149 0xc0, /* END_COLLECTION */ 150 ]; 151