u2f.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. /*
  2. * U2F USB device.
  3. *
  4. * Copyright (c) 2020 César Belley <cesar.belley@lse.epita.fr>
  5. * Written by César Belley <cesar.belley@lse.epita.fr>
  6. *
  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:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  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
  23. * THE SOFTWARE.
  24. */
  25. #include "qemu/osdep.h"
  26. #include "qemu/module.h"
  27. #include "qapi/error.h"
  28. #include "hw/usb.h"
  29. #include "hw/usb/hid.h"
  30. #include "migration/vmstate.h"
  31. #include "desc.h"
  32. #include "u2f.h"
  33. /* U2F key Vendor / Product */
  34. #define U2F_KEY_VENDOR_NUM 0x46f4 /* CRC16() of "QEMU" */
  35. #define U2F_KEY_PRODUCT_NUM 0x0005
  36. enum {
  37. STR_MANUFACTURER = 1,
  38. STR_PRODUCT,
  39. STR_SERIALNUMBER,
  40. STR_CONFIG,
  41. STR_INTERFACE
  42. };
  43. static const USBDescStrings desc_strings = {
  44. [STR_MANUFACTURER] = "QEMU",
  45. [STR_PRODUCT] = "U2F USB key",
  46. [STR_SERIALNUMBER] = "0",
  47. [STR_CONFIG] = "U2F key config",
  48. [STR_INTERFACE] = "U2F key interface"
  49. };
  50. static const USBDescIface desc_iface_u2f_key = {
  51. .bInterfaceNumber = 0,
  52. .bNumEndpoints = 2,
  53. .bInterfaceClass = USB_CLASS_HID,
  54. .bInterfaceSubClass = 0x0,
  55. .bInterfaceProtocol = 0x0,
  56. .ndesc = 1,
  57. .descs = (USBDescOther[]) {
  58. {
  59. /* HID descriptor */
  60. .data = (uint8_t[]) {
  61. 0x09, /* u8 bLength */
  62. USB_DT_HID, /* u8 bDescriptorType */
  63. 0x10, 0x01, /* u16 HID_class */
  64. 0x00, /* u8 country_code */
  65. 0x01, /* u8 num_descriptors */
  66. USB_DT_REPORT, /* u8 type: Report */
  67. 0x22, 0, /* u16 len */
  68. },
  69. },
  70. },
  71. .eps = (USBDescEndpoint[]) {
  72. {
  73. .bEndpointAddress = USB_DIR_IN | 0x01,
  74. .bmAttributes = USB_ENDPOINT_XFER_INT,
  75. .wMaxPacketSize = U2FHID_PACKET_SIZE,
  76. .bInterval = 0x05,
  77. }, {
  78. .bEndpointAddress = USB_DIR_OUT | 0x01,
  79. .bmAttributes = USB_ENDPOINT_XFER_INT,
  80. .wMaxPacketSize = U2FHID_PACKET_SIZE,
  81. .bInterval = 0x05,
  82. },
  83. },
  84. };
  85. static const USBDescDevice desc_device_u2f_key = {
  86. .bcdUSB = 0x0100,
  87. .bMaxPacketSize0 = U2FHID_PACKET_SIZE,
  88. .bNumConfigurations = 1,
  89. .confs = (USBDescConfig[]) {
  90. {
  91. .bNumInterfaces = 1,
  92. .bConfigurationValue = 1,
  93. .iConfiguration = STR_CONFIG,
  94. .bmAttributes = USB_CFG_ATT_ONE,
  95. .bMaxPower = 15,
  96. .nif = 1,
  97. .ifs = &desc_iface_u2f_key,
  98. },
  99. },
  100. };
  101. static const USBDesc desc_u2f_key = {
  102. .id = {
  103. .idVendor = U2F_KEY_VENDOR_NUM,
  104. .idProduct = U2F_KEY_PRODUCT_NUM,
  105. .bcdDevice = 0,
  106. .iManufacturer = STR_MANUFACTURER,
  107. .iProduct = STR_PRODUCT,
  108. .iSerialNumber = STR_SERIALNUMBER,
  109. },
  110. .full = &desc_device_u2f_key,
  111. .str = desc_strings,
  112. };
  113. static const uint8_t u2f_key_hid_report_desc[] = {
  114. 0x06, 0xd0, 0xf1, /* Usage Page (FIDO) */
  115. 0x09, 0x01, /* Usage (FIDO) */
  116. 0xa1, 0x01, /* Collection (HID Application) */
  117. 0x09, 0x20, /* Usage (FIDO data in) */
  118. 0x15, 0x00, /* Logical Minimum (0) */
  119. 0x26, 0xFF, 0x00, /* Logical Maximum (0xff) */
  120. 0x75, 0x08, /* Report Size (8) */
  121. 0x95, 0x40, /* Report Count (0x40) */
  122. 0x81, 0x02, /* Input (Data, Variable, Absolute) */
  123. 0x09, 0x21, /* Usage (FIDO data out) */
  124. 0x15, 0x00, /* Logical Minimum (0) */
  125. 0x26, 0xFF, 0x00, /* Logical Maximum (0xFF) */
  126. 0x75, 0x08, /* Report Size (8) */
  127. 0x95, 0x40, /* Report Count (0x40) */
  128. 0x91, 0x02, /* Output (Data, Variable, Absolute) */
  129. 0xC0 /* End Collection */
  130. };
  131. static void u2f_key_reset(U2FKeyState *key)
  132. {
  133. key->pending_in_start = 0;
  134. key->pending_in_end = 0;
  135. key->pending_in_num = 0;
  136. }
  137. static void u2f_key_handle_reset(USBDevice *dev)
  138. {
  139. U2FKeyState *key = U2F_KEY(dev);
  140. u2f_key_reset(key);
  141. }
  142. static void u2f_key_handle_control(USBDevice *dev, USBPacket *p,
  143. int request, int value, int index, int length, uint8_t *data)
  144. {
  145. U2FKeyState *key = U2F_KEY(dev);
  146. int ret;
  147. ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
  148. if (ret >= 0) {
  149. return;
  150. }
  151. switch (request) {
  152. case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
  153. switch (value >> 8) {
  154. case 0x22:
  155. memcpy(data, u2f_key_hid_report_desc,
  156. sizeof(u2f_key_hid_report_desc));
  157. p->actual_length = sizeof(u2f_key_hid_report_desc);
  158. break;
  159. default:
  160. goto fail;
  161. }
  162. break;
  163. case HID_GET_IDLE:
  164. data[0] = key->idle;
  165. p->actual_length = 1;
  166. break;
  167. case HID_SET_IDLE:
  168. key->idle = (uint8_t)(value >> 8);
  169. break;
  170. default:
  171. fail:
  172. p->status = USB_RET_STALL;
  173. break;
  174. }
  175. }
  176. static void u2f_key_recv_from_guest(U2FKeyState *key, USBPacket *p)
  177. {
  178. U2FKeyClass *kc = U2F_KEY_GET_CLASS(key);
  179. uint8_t packet[U2FHID_PACKET_SIZE];
  180. if (kc->recv_from_guest == NULL || p->iov.size != U2FHID_PACKET_SIZE) {
  181. return;
  182. }
  183. usb_packet_copy(p, packet, p->iov.size);
  184. kc->recv_from_guest(key, packet);
  185. }
  186. static void u2f_pending_in_add(U2FKeyState *key,
  187. const uint8_t packet[U2FHID_PACKET_SIZE])
  188. {
  189. uint8_t index;
  190. if (key->pending_in_num >= U2FHID_PENDING_IN_NUM) {
  191. return;
  192. }
  193. index = key->pending_in_end;
  194. key->pending_in_end = (index + 1) % U2FHID_PENDING_IN_NUM;
  195. ++key->pending_in_num;
  196. memcpy(key->pending_in[index], packet, U2FHID_PACKET_SIZE);
  197. }
  198. static uint8_t *u2f_pending_in_get(U2FKeyState *key)
  199. {
  200. uint8_t index;
  201. if (key->pending_in_num == 0) {
  202. return NULL;
  203. }
  204. index = key->pending_in_start;
  205. key->pending_in_start = (index + 1) % U2FHID_PENDING_IN_NUM;
  206. --key->pending_in_num;
  207. return key->pending_in[index];
  208. }
  209. static void u2f_key_handle_data(USBDevice *dev, USBPacket *p)
  210. {
  211. U2FKeyState *key = U2F_KEY(dev);
  212. uint8_t *packet_in;
  213. /* Endpoint number check */
  214. if (p->ep->nr != 1) {
  215. p->status = USB_RET_STALL;
  216. return;
  217. }
  218. switch (p->pid) {
  219. case USB_TOKEN_OUT:
  220. u2f_key_recv_from_guest(key, p);
  221. break;
  222. case USB_TOKEN_IN:
  223. packet_in = u2f_pending_in_get(key);
  224. if (packet_in == NULL) {
  225. p->status = USB_RET_NAK;
  226. return;
  227. }
  228. usb_packet_copy(p, packet_in, U2FHID_PACKET_SIZE);
  229. break;
  230. default:
  231. p->status = USB_RET_STALL;
  232. break;
  233. }
  234. }
  235. void u2f_send_to_guest(U2FKeyState *key,
  236. const uint8_t packet[U2FHID_PACKET_SIZE])
  237. {
  238. u2f_pending_in_add(key, packet);
  239. usb_wakeup(key->ep, 0);
  240. }
  241. static void u2f_key_unrealize(USBDevice *dev)
  242. {
  243. U2FKeyState *key = U2F_KEY(dev);
  244. U2FKeyClass *kc = U2F_KEY_GET_CLASS(key);
  245. if (kc->unrealize != NULL) {
  246. kc->unrealize(key);
  247. }
  248. }
  249. static void u2f_key_realize(USBDevice *dev, Error **errp)
  250. {
  251. U2FKeyState *key = U2F_KEY(dev);
  252. U2FKeyClass *kc = U2F_KEY_GET_CLASS(key);
  253. Error *local_err = NULL;
  254. usb_desc_create_serial(dev);
  255. usb_desc_init(dev);
  256. u2f_key_reset(key);
  257. if (kc->realize != NULL) {
  258. kc->realize(key, &local_err);
  259. if (local_err != NULL) {
  260. error_propagate(errp, local_err);
  261. return;
  262. }
  263. }
  264. key->ep = usb_ep_get(dev, USB_TOKEN_IN, 1);
  265. }
  266. const VMStateDescription vmstate_u2f_key = {
  267. .name = "u2f-key",
  268. .version_id = 1,
  269. .minimum_version_id = 1,
  270. .fields = (const VMStateField[]) {
  271. VMSTATE_USB_DEVICE(dev, U2FKeyState),
  272. VMSTATE_UINT8(idle, U2FKeyState),
  273. VMSTATE_UINT8_2DARRAY(pending_in, U2FKeyState,
  274. U2FHID_PENDING_IN_NUM, U2FHID_PACKET_SIZE),
  275. VMSTATE_UINT8(pending_in_start, U2FKeyState),
  276. VMSTATE_UINT8(pending_in_end, U2FKeyState),
  277. VMSTATE_UINT8(pending_in_num, U2FKeyState),
  278. VMSTATE_END_OF_LIST()
  279. }
  280. };
  281. static void u2f_key_class_init(ObjectClass *klass, void *data)
  282. {
  283. DeviceClass *dc = DEVICE_CLASS(klass);
  284. USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
  285. uc->product_desc = "QEMU U2F USB key";
  286. uc->usb_desc = &desc_u2f_key;
  287. uc->handle_reset = u2f_key_handle_reset;
  288. uc->handle_control = u2f_key_handle_control;
  289. uc->handle_data = u2f_key_handle_data;
  290. uc->handle_attach = usb_desc_attach;
  291. uc->realize = u2f_key_realize;
  292. uc->unrealize = u2f_key_unrealize;
  293. dc->desc = "QEMU U2F key";
  294. dc->vmsd = &vmstate_u2f_key;
  295. }
  296. static const TypeInfo u2f_key_info = {
  297. .name = TYPE_U2F_KEY,
  298. .parent = TYPE_USB_DEVICE,
  299. .instance_size = sizeof(U2FKeyState),
  300. .abstract = true,
  301. .class_size = sizeof(U2FKeyClass),
  302. .class_init = u2f_key_class_init,
  303. };
  304. static void u2f_key_register_types(void)
  305. {
  306. type_register_static(&u2f_key_info);
  307. }
  308. type_init(u2f_key_register_types)