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