4 * Copyright (c) 2020 César Belley <cesar.belley@lse.epita.fr>
5 * Written by César Belley <cesar.belley@lse.epita.fr>
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 #include "qemu/osdep.h"
27 #include "qemu/module.h"
28 #include "qapi/error.h"
30 #include "hw/usb/hid.h"
31 #include "migration/vmstate.h"
36 /* U2F key Vendor / Product */
37 #define U2F_KEY_VENDOR_NUM 0x46f4 /* CRC16() of "QEMU" */
38 #define U2F_KEY_PRODUCT_NUM 0x0005
48 static const USBDescStrings desc_strings
= {
49 [STR_MANUFACTURER
] = "QEMU",
50 [STR_PRODUCT
] = "U2F USB key",
51 [STR_SERIALNUMBER
] = "0",
52 [STR_CONFIG
] = "U2F key config",
53 [STR_INTERFACE
] = "U2F key interface"
56 static const USBDescIface desc_iface_u2f_key
= {
57 .bInterfaceNumber
= 0,
59 .bInterfaceClass
= USB_CLASS_HID
,
60 .bInterfaceSubClass
= 0x0,
61 .bInterfaceProtocol
= 0x0,
63 .descs
= (USBDescOther
[]) {
67 0x09, /* u8 bLength */
68 USB_DT_HID
, /* u8 bDescriptorType */
69 0x10, 0x01, /* u16 HID_class */
70 0x00, /* u8 country_code */
71 0x01, /* u8 num_descriptors */
72 USB_DT_REPORT
, /* u8 type: Report */
73 0x22, 0, /* u16 len */
77 .eps
= (USBDescEndpoint
[]) {
79 .bEndpointAddress
= USB_DIR_IN
| 0x01,
80 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
81 .wMaxPacketSize
= U2FHID_PACKET_SIZE
,
84 .bEndpointAddress
= USB_DIR_OUT
| 0x01,
85 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
86 .wMaxPacketSize
= U2FHID_PACKET_SIZE
,
93 static const USBDescDevice desc_device_u2f_key
= {
95 .bMaxPacketSize0
= U2FHID_PACKET_SIZE
,
96 .bNumConfigurations
= 1,
97 .confs
= (USBDescConfig
[]) {
100 .bConfigurationValue
= 1,
101 .iConfiguration
= STR_CONFIG
,
102 .bmAttributes
= USB_CFG_ATT_ONE
,
105 .ifs
= &desc_iface_u2f_key
,
110 static const USBDesc desc_u2f_key
= {
112 .idVendor
= U2F_KEY_VENDOR_NUM
,
113 .idProduct
= U2F_KEY_PRODUCT_NUM
,
115 .iManufacturer
= STR_MANUFACTURER
,
116 .iProduct
= STR_PRODUCT
,
117 .iSerialNumber
= STR_SERIALNUMBER
,
119 .full
= &desc_device_u2f_key
,
123 static const uint8_t u2f_key_hid_report_desc
[] = {
124 0x06, 0xd0, 0xf1, /* Usage Page (FIDO) */
125 0x09, 0x01, /* Usage (FIDO) */
126 0xa1, 0x01, /* Collection (HID Application) */
127 0x09, 0x20, /* Usage (FIDO data in) */
128 0x15, 0x00, /* Logical Minimum (0) */
129 0x26, 0xFF, 0x00, /* Logical Maximum (0xff) */
130 0x75, 0x08, /* Report Size (8) */
131 0x95, 0x40, /* Report Count (0x40) */
132 0x81, 0x02, /* Input (Data, Variable, Absolute) */
133 0x09, 0x21, /* Usage (FIDO data out) */
134 0x15, 0x00, /* Logical Minimum (0) */
135 0x26, 0xFF, 0x00, /* Logical Maximum (0xFF) */
136 0x75, 0x08, /* Report Size (8) */
137 0x95, 0x40, /* Report Count (0x40) */
138 0x91, 0x02, /* Output (Data, Variable, Absolute) */
139 0xC0 /* End Collection */
142 static void u2f_key_reset(U2FKeyState
*key
)
144 key
->pending_in_start
= 0;
145 key
->pending_in_end
= 0;
146 key
->pending_in_num
= 0;
149 static void u2f_key_handle_reset(USBDevice
*dev
)
151 U2FKeyState
*key
= U2F_KEY(dev
);
156 static void u2f_key_handle_control(USBDevice
*dev
, USBPacket
*p
,
157 int request
, int value
, int index
, int length
, uint8_t *data
)
159 U2FKeyState
*key
= U2F_KEY(dev
);
162 ret
= usb_desc_handle_control(dev
, p
, request
, value
, index
, length
, data
);
168 case InterfaceRequest
| USB_REQ_GET_DESCRIPTOR
:
169 switch (value
>> 8) {
171 memcpy(data
, u2f_key_hid_report_desc
,
172 sizeof(u2f_key_hid_report_desc
));
173 p
->actual_length
= sizeof(u2f_key_hid_report_desc
);
181 p
->actual_length
= 1;
184 key
->idle
= (uint8_t)(value
>> 8);
188 p
->status
= USB_RET_STALL
;
194 static void u2f_key_recv_from_guest(U2FKeyState
*key
, USBPacket
*p
)
196 U2FKeyClass
*kc
= U2F_KEY_GET_CLASS(key
);
197 uint8_t packet
[U2FHID_PACKET_SIZE
];
199 if (kc
->recv_from_guest
== NULL
|| p
->iov
.size
!= U2FHID_PACKET_SIZE
) {
203 usb_packet_copy(p
, packet
, p
->iov
.size
);
204 kc
->recv_from_guest(key
, packet
);
207 static void u2f_pending_in_add(U2FKeyState
*key
,
208 const uint8_t packet
[U2FHID_PACKET_SIZE
])
212 if (key
->pending_in_num
>= U2FHID_PENDING_IN_NUM
) {
216 index
= key
->pending_in_end
;
217 key
->pending_in_end
= (index
+ 1) % U2FHID_PENDING_IN_NUM
;
218 ++key
->pending_in_num
;
220 memcpy(key
->pending_in
[index
], packet
, U2FHID_PACKET_SIZE
);
223 static uint8_t *u2f_pending_in_get(U2FKeyState
*key
)
227 if (key
->pending_in_num
== 0) {
231 index
= key
->pending_in_start
;
232 key
->pending_in_start
= (index
+ 1) % U2FHID_PENDING_IN_NUM
;
233 --key
->pending_in_num
;
235 return key
->pending_in
[index
];
238 static void u2f_key_handle_data(USBDevice
*dev
, USBPacket
*p
)
240 U2FKeyState
*key
= U2F_KEY(dev
);
243 /* Endpoint number check */
244 if (p
->ep
->nr
!= 1) {
245 p
->status
= USB_RET_STALL
;
251 u2f_key_recv_from_guest(key
, p
);
254 packet_in
= u2f_pending_in_get(key
);
255 if (packet_in
== NULL
) {
256 p
->status
= USB_RET_NAK
;
259 usb_packet_copy(p
, packet_in
, U2FHID_PACKET_SIZE
);
262 p
->status
= USB_RET_STALL
;
267 void u2f_send_to_guest(U2FKeyState
*key
,
268 const uint8_t packet
[U2FHID_PACKET_SIZE
])
270 u2f_pending_in_add(key
, packet
);
271 usb_wakeup(key
->ep
, 0);
274 static void u2f_key_unrealize(USBDevice
*dev
)
276 U2FKeyState
*key
= U2F_KEY(dev
);
277 U2FKeyClass
*kc
= U2F_KEY_GET_CLASS(key
);
279 if (kc
->unrealize
!= NULL
) {
284 static void u2f_key_realize(USBDevice
*dev
, Error
**errp
)
286 U2FKeyState
*key
= U2F_KEY(dev
);
287 U2FKeyClass
*kc
= U2F_KEY_GET_CLASS(key
);
288 Error
*local_err
= NULL
;
290 usb_desc_create_serial(dev
);
294 if (kc
->realize
!= NULL
) {
295 kc
->realize(key
, &local_err
);
296 if (local_err
!= NULL
) {
297 error_propagate(errp
, local_err
);
301 key
->ep
= usb_ep_get(dev
, USB_TOKEN_IN
, 1);
304 const VMStateDescription vmstate_u2f_key
= {
307 .minimum_version_id
= 1,
308 .fields
= (VMStateField
[]) {
309 VMSTATE_USB_DEVICE(dev
, U2FKeyState
),
310 VMSTATE_UINT8(idle
, U2FKeyState
),
311 VMSTATE_UINT8_2DARRAY(pending_in
, U2FKeyState
,
312 U2FHID_PENDING_IN_NUM
, U2FHID_PACKET_SIZE
),
313 VMSTATE_UINT8(pending_in_start
, U2FKeyState
),
314 VMSTATE_UINT8(pending_in_end
, U2FKeyState
),
315 VMSTATE_UINT8(pending_in_num
, U2FKeyState
),
316 VMSTATE_END_OF_LIST()
320 static void u2f_key_class_init(ObjectClass
*klass
, void *data
)
322 DeviceClass
*dc
= DEVICE_CLASS(klass
);
323 USBDeviceClass
*uc
= USB_DEVICE_CLASS(klass
);
325 uc
->product_desc
= "QEMU U2F USB key";
326 uc
->usb_desc
= &desc_u2f_key
;
327 uc
->handle_reset
= u2f_key_handle_reset
;
328 uc
->handle_control
= u2f_key_handle_control
;
329 uc
->handle_data
= u2f_key_handle_data
;
330 uc
->handle_attach
= usb_desc_attach
;
331 uc
->realize
= u2f_key_realize
;
332 uc
->unrealize
= u2f_key_unrealize
;
333 dc
->desc
= "QEMU U2F key";
334 dc
->vmsd
= &vmstate_u2f_key
;
337 static const TypeInfo u2f_key_info
= {
338 .name
= TYPE_U2F_KEY
,
339 .parent
= TYPE_USB_DEVICE
,
340 .instance_size
= sizeof(U2FKeyState
),
342 .class_size
= sizeof(U2FKeyClass
),
343 .class_init
= u2f_key_class_init
,
346 static void u2f_key_register_types(void)
348 type_register_static(&u2f_key_info
);
349 usb_legacy_register(TYPE_U2F_KEY
, "u2f-key", NULL
);
352 type_init(u2f_key_register_types
)