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#include "qemu/osdep.h"
27#include "qemu/module.h"
28#include "qapi/error.h"
29#include "hw/usb.h"
30#include "hw/usb/hid.h"
31#include "migration/vmstate.h"
32#include "desc.h"
33
34#include "u2f.h"
35
36
37#define U2F_KEY_VENDOR_NUM 0x46f4
38#define U2F_KEY_PRODUCT_NUM 0x0005
39
40enum {
41 STR_MANUFACTURER = 1,
42 STR_PRODUCT,
43 STR_SERIALNUMBER,
44 STR_CONFIG,
45 STR_INTERFACE
46};
47
48static 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"
54};
55
56static const USBDescIface desc_iface_u2f_key = {
57 .bInterfaceNumber = 0,
58 .bNumEndpoints = 2,
59 .bInterfaceClass = USB_CLASS_HID,
60 .bInterfaceSubClass = 0x0,
61 .bInterfaceProtocol = 0x0,
62 .ndesc = 1,
63 .descs = (USBDescOther[]) {
64 {
65
66 .data = (uint8_t[]) {
67 0x09,
68 USB_DT_HID,
69 0x10, 0x01,
70 0x00,
71 0x01,
72 USB_DT_REPORT,
73 0x22, 0,
74 },
75 },
76 },
77 .eps = (USBDescEndpoint[]) {
78 {
79 .bEndpointAddress = USB_DIR_IN | 0x01,
80 .bmAttributes = USB_ENDPOINT_XFER_INT,
81 .wMaxPacketSize = U2FHID_PACKET_SIZE,
82 .bInterval = 0x05,
83 }, {
84 .bEndpointAddress = USB_DIR_OUT | 0x01,
85 .bmAttributes = USB_ENDPOINT_XFER_INT,
86 .wMaxPacketSize = U2FHID_PACKET_SIZE,
87 .bInterval = 0x05,
88 },
89 },
90
91};
92
93static const USBDescDevice desc_device_u2f_key = {
94 .bcdUSB = 0x0100,
95 .bMaxPacketSize0 = U2FHID_PACKET_SIZE,
96 .bNumConfigurations = 1,
97 .confs = (USBDescConfig[]) {
98 {
99 .bNumInterfaces = 1,
100 .bConfigurationValue = 1,
101 .iConfiguration = STR_CONFIG,
102 .bmAttributes = USB_CFG_ATT_ONE,
103 .bMaxPower = 15,
104 .nif = 1,
105 .ifs = &desc_iface_u2f_key,
106 },
107 },
108};
109
110static const USBDesc desc_u2f_key = {
111 .id = {
112 .idVendor = U2F_KEY_VENDOR_NUM,
113 .idProduct = U2F_KEY_PRODUCT_NUM,
114 .bcdDevice = 0,
115 .iManufacturer = STR_MANUFACTURER,
116 .iProduct = STR_PRODUCT,
117 .iSerialNumber = STR_SERIALNUMBER,
118 },
119 .full = &desc_device_u2f_key,
120 .str = desc_strings,
121};
122
123static const uint8_t u2f_key_hid_report_desc[] = {
124 0x06, 0xd0, 0xf1,
125 0x09, 0x01,
126 0xa1, 0x01,
127 0x09, 0x20,
128 0x15, 0x00,
129 0x26, 0xFF, 0x00,
130 0x75, 0x08,
131 0x95, 0x40,
132 0x81, 0x02,
133 0x09, 0x21,
134 0x15, 0x00,
135 0x26, 0xFF, 0x00,
136 0x75, 0x08,
137 0x95, 0x40,
138 0x91, 0x02,
139 0xC0
140};
141
142static void u2f_key_reset(U2FKeyState *key)
143{
144 key->pending_in_start = 0;
145 key->pending_in_end = 0;
146 key->pending_in_num = 0;
147}
148
149static void u2f_key_handle_reset(USBDevice *dev)
150{
151 U2FKeyState *key = U2F_KEY(dev);
152
153 u2f_key_reset(key);
154}
155
156static void u2f_key_handle_control(USBDevice *dev, USBPacket *p,
157 int request, int value, int index, int length, uint8_t *data)
158{
159 U2FKeyState *key = U2F_KEY(dev);
160 int ret;
161
162 ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
163 if (ret >= 0) {
164 return;
165 }
166
167 switch (request) {
168 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
169 switch (value >> 8) {
170 case 0x22:
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);
174 break;
175 default:
176 goto fail;
177 }
178 break;
179 case HID_GET_IDLE:
180 data[0] = key->idle;
181 p->actual_length = 1;
182 break;
183 case HID_SET_IDLE:
184 key->idle = (uint8_t)(value >> 8);
185 break;
186 default:
187 fail:
188 p->status = USB_RET_STALL;
189 break;
190 }
191
192}
193
194static void u2f_key_recv_from_guest(U2FKeyState *key, USBPacket *p)
195{
196 U2FKeyClass *kc = U2F_KEY_GET_CLASS(key);
197 uint8_t packet[U2FHID_PACKET_SIZE];
198
199 if (kc->recv_from_guest == NULL || p->iov.size != U2FHID_PACKET_SIZE) {
200 return;
201 }
202
203 usb_packet_copy(p, packet, p->iov.size);
204 kc->recv_from_guest(key, packet);
205}
206
207static void u2f_pending_in_add(U2FKeyState *key,
208 const uint8_t packet[U2FHID_PACKET_SIZE])
209{
210 uint8_t index;
211
212 if (key->pending_in_num >= U2FHID_PENDING_IN_NUM) {
213 return;
214 }
215
216 index = key->pending_in_end;
217 key->pending_in_end = (index + 1) % U2FHID_PENDING_IN_NUM;
218 ++key->pending_in_num;
219
220 memcpy(key->pending_in[index], packet, U2FHID_PACKET_SIZE);
221}
222
223static uint8_t *u2f_pending_in_get(U2FKeyState *key)
224{
225 uint8_t index;
226
227 if (key->pending_in_num == 0) {
228 return NULL;
229 }
230
231 index = key->pending_in_start;
232 key->pending_in_start = (index + 1) % U2FHID_PENDING_IN_NUM;
233 --key->pending_in_num;
234
235 return key->pending_in[index];
236}
237
238static void u2f_key_handle_data(USBDevice *dev, USBPacket *p)
239{
240 U2FKeyState *key = U2F_KEY(dev);
241 uint8_t *packet_in;
242
243
244 if (p->ep->nr != 1) {
245 p->status = USB_RET_STALL;
246 return;
247 }
248
249 switch (p->pid) {
250 case USB_TOKEN_OUT:
251 u2f_key_recv_from_guest(key, p);
252 break;
253 case USB_TOKEN_IN:
254 packet_in = u2f_pending_in_get(key);
255 if (packet_in == NULL) {
256 p->status = USB_RET_NAK;
257 return;
258 }
259 usb_packet_copy(p, packet_in, U2FHID_PACKET_SIZE);
260 break;
261 default:
262 p->status = USB_RET_STALL;
263 break;
264 }
265}
266
267void u2f_send_to_guest(U2FKeyState *key,
268 const uint8_t packet[U2FHID_PACKET_SIZE])
269{
270 u2f_pending_in_add(key, packet);
271 usb_wakeup(key->ep, 0);
272}
273
274static void u2f_key_unrealize(USBDevice *dev)
275{
276 U2FKeyState *key = U2F_KEY(dev);
277 U2FKeyClass *kc = U2F_KEY_GET_CLASS(key);
278
279 if (kc->unrealize != NULL) {
280 kc->unrealize(key);
281 }
282}
283
284static void u2f_key_realize(USBDevice *dev, Error **errp)
285{
286 U2FKeyState *key = U2F_KEY(dev);
287 U2FKeyClass *kc = U2F_KEY_GET_CLASS(key);
288 Error *local_err = NULL;
289
290 usb_desc_create_serial(dev);
291 usb_desc_init(dev);
292 u2f_key_reset(key);
293
294 if (kc->realize != NULL) {
295 kc->realize(key, &local_err);
296 if (local_err != NULL) {
297 error_propagate(errp, local_err);
298 return;
299 }
300 }
301 key->ep = usb_ep_get(dev, USB_TOKEN_IN, 1);
302}
303
304const VMStateDescription vmstate_u2f_key = {
305 .name = "u2f-key",
306 .version_id = 1,
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()
317 }
318};
319
320static void u2f_key_class_init(ObjectClass *klass, void *data)
321{
322 DeviceClass *dc = DEVICE_CLASS(klass);
323 USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
324
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;
335}
336
337static const TypeInfo u2f_key_info = {
338 .name = TYPE_U2F_KEY,
339 .parent = TYPE_USB_DEVICE,
340 .instance_size = sizeof(U2FKeyState),
341 .abstract = true,
342 .class_size = sizeof(U2FKeyClass),
343 .class_init = u2f_key_class_init,
344};
345
346static void u2f_key_register_types(void)
347{
348 type_register_static(&u2f_key_info);
349}
350
351type_init(u2f_key_register_types)
352