1 /* 2 * U2F USB Passthru 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 26 #include "qemu/osdep.h" 27 #include "qemu/module.h" 28 #include "qemu/main-loop.h" 29 #include "qemu/error-report.h" 30 #include "qapi/error.h" 31 #include "hw/qdev-properties.h" 32 #include "hw/usb.h" 33 #include "migration/vmstate.h" 34 35 #include "u2f.h" 36 37 #define NONCE_SIZE 8 38 #define BROADCAST_CID 0xFFFFFFFF 39 #define TRANSACTION_TIMEOUT 120000 40 41 struct transaction { 42 uint32_t cid; 43 uint16_t resp_bcnt; 44 uint16_t resp_size; 45 46 /* Nonce for broadcast isolation */ 47 uint8_t nonce[NONCE_SIZE]; 48 }; 49 50 typedef struct U2FPassthruState U2FPassthruState; 51 52 #define CURRENT_TRANSACTIONS_NUM 4 53 54 struct U2FPassthruState { 55 U2FKeyState base; 56 57 /* Host device */ 58 char *hidraw; 59 int hidraw_fd; 60 61 /* Current Transactions */ 62 struct transaction current_transactions[CURRENT_TRANSACTIONS_NUM]; 63 uint8_t current_transactions_start; 64 uint8_t current_transactions_end; 65 uint8_t current_transactions_num; 66 67 /* Transaction time checking */ 68 int64_t last_transaction_time; 69 QEMUTimer timer; 70 }; 71 72 #define TYPE_U2F_PASSTHRU "u2f-passthru" 73 #define PASSTHRU_U2F_KEY(obj) \ 74 OBJECT_CHECK(U2FPassthruState, (obj), TYPE_U2F_PASSTHRU) 75 76 /* Init packet sizes */ 77 #define PACKET_INIT_HEADER_SIZE 7 78 #define PACKET_INIT_DATA_SIZE (U2FHID_PACKET_SIZE - PACKET_INIT_HEADER_SIZE) 79 80 /* Cont packet sizes */ 81 #define PACKET_CONT_HEADER_SIZE 5 82 #define PACKET_CONT_DATA_SIZE (U2FHID_PACKET_SIZE - PACKET_CONT_HEADER_SIZE) 83 84 struct packet_init { 85 uint32_t cid; 86 uint8_t cmd; 87 uint8_t bcnth; 88 uint8_t bcntl; 89 uint8_t data[PACKET_INIT_DATA_SIZE]; 90 } QEMU_PACKED; 91 92 static inline uint32_t packet_get_cid(const void *packet) 93 { 94 return *((uint32_t *)packet); 95 } 96 97 static inline bool packet_is_init(const void *packet) 98 { 99 return ((uint8_t *)packet)[4] & (1 << 7); 100 } 101 102 static inline uint16_t packet_init_get_bcnt( 103 const struct packet_init *packet_init) 104 { 105 uint16_t bcnt = 0; 106 bcnt |= packet_init->bcnth << 8; 107 bcnt |= packet_init->bcntl; 108 109 return bcnt; 110 } 111 112 static void u2f_passthru_reset(U2FPassthruState *key) 113 { 114 timer_del(&key->timer); 115 qemu_set_fd_handler(key->hidraw_fd, NULL, NULL, key); 116 key->last_transaction_time = 0; 117 key->current_transactions_start = 0; 118 key->current_transactions_end = 0; 119 key->current_transactions_num = 0; 120 } 121 122 static void u2f_timeout_check(void *opaque) 123 { 124 U2FPassthruState *key = opaque; 125 int64_t time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); 126 127 if (time > key->last_transaction_time + TRANSACTION_TIMEOUT) { 128 u2f_passthru_reset(key); 129 } else { 130 timer_mod(&key->timer, time + TRANSACTION_TIMEOUT / 4); 131 } 132 } 133 134 static int u2f_transaction_get_index(U2FPassthruState *key, uint32_t cid) 135 { 136 for (int i = 0; i < key->current_transactions_num; ++i) { 137 int index = (key->current_transactions_start + i) 138 % CURRENT_TRANSACTIONS_NUM; 139 if (cid == key->current_transactions[index].cid) { 140 return index; 141 } 142 } 143 return -1; 144 } 145 146 static struct transaction *u2f_transaction_get(U2FPassthruState *key, 147 uint32_t cid) 148 { 149 int index = u2f_transaction_get_index(key, cid); 150 if (index < 0) { 151 return NULL; 152 } 153 return &key->current_transactions[index]; 154 } 155 156 static struct transaction *u2f_transaction_get_from_nonce(U2FPassthruState *key, 157 const uint8_t nonce[NONCE_SIZE]) 158 { 159 for (int i = 0; i < key->current_transactions_num; ++i) { 160 int index = (key->current_transactions_start + i) 161 % CURRENT_TRANSACTIONS_NUM; 162 if (key->current_transactions[index].cid == BROADCAST_CID 163 && memcmp(nonce, key->current_transactions[index].nonce, 164 NONCE_SIZE) == 0) { 165 return &key->current_transactions[index]; 166 } 167 } 168 return NULL; 169 } 170 171 static void u2f_transaction_close(U2FPassthruState *key, uint32_t cid) 172 { 173 int index, next_index; 174 index = u2f_transaction_get_index(key, cid); 175 if (index < 0) { 176 return; 177 } 178 next_index = (index + 1) % CURRENT_TRANSACTIONS_NUM; 179 180 /* Rearrange to ensure the oldest is at the start position */ 181 while (next_index != key->current_transactions_end) { 182 memcpy(&key->current_transactions[index], 183 &key->current_transactions[next_index], 184 sizeof(struct transaction)); 185 186 index = next_index; 187 next_index = (index + 1) % CURRENT_TRANSACTIONS_NUM; 188 } 189 190 key->current_transactions_end = index; 191 --key->current_transactions_num; 192 193 if (key->current_transactions_num == 0) { 194 u2f_passthru_reset(key); 195 } 196 } 197 198 static void u2f_transaction_add(U2FPassthruState *key, uint32_t cid, 199 const uint8_t nonce[NONCE_SIZE]) 200 { 201 uint8_t index; 202 struct transaction *transaction; 203 204 if (key->current_transactions_num >= CURRENT_TRANSACTIONS_NUM) { 205 /* Close the oldest transaction */ 206 index = key->current_transactions_start; 207 transaction = &key->current_transactions[index]; 208 u2f_transaction_close(key, transaction->cid); 209 } 210 211 /* Index */ 212 index = key->current_transactions_end; 213 key->current_transactions_end = (index + 1) % CURRENT_TRANSACTIONS_NUM; 214 ++key->current_transactions_num; 215 216 /* Transaction */ 217 transaction = &key->current_transactions[index]; 218 transaction->cid = cid; 219 transaction->resp_bcnt = 0; 220 transaction->resp_size = 0; 221 222 /* Nonce */ 223 if (nonce != NULL) { 224 memcpy(transaction->nonce, nonce, NONCE_SIZE); 225 } 226 } 227 228 static void u2f_passthru_read(void *opaque); 229 230 static void u2f_transaction_start(U2FPassthruState *key, 231 const struct packet_init *packet_init) 232 { 233 int64_t time; 234 235 /* Transaction */ 236 if (packet_init->cid == BROADCAST_CID) { 237 u2f_transaction_add(key, packet_init->cid, packet_init->data); 238 } else { 239 u2f_transaction_add(key, packet_init->cid, NULL); 240 } 241 242 /* Time */ 243 time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); 244 if (key->last_transaction_time == 0) { 245 qemu_set_fd_handler(key->hidraw_fd, u2f_passthru_read, NULL, key); 246 timer_init_ms(&key->timer, QEMU_CLOCK_VIRTUAL, u2f_timeout_check, key); 247 timer_mod(&key->timer, time + TRANSACTION_TIMEOUT / 4); 248 } 249 key->last_transaction_time = time; 250 } 251 252 static void u2f_passthru_recv_from_host(U2FPassthruState *key, 253 const uint8_t packet[U2FHID_PACKET_SIZE]) 254 { 255 struct transaction *transaction; 256 uint32_t cid; 257 258 /* Retrieve transaction */ 259 cid = packet_get_cid(packet); 260 if (cid == BROADCAST_CID) { 261 struct packet_init *packet_init; 262 if (!packet_is_init(packet)) { 263 return; 264 } 265 packet_init = (struct packet_init *)packet; 266 transaction = u2f_transaction_get_from_nonce(key, packet_init->data); 267 } else { 268 transaction = u2f_transaction_get(key, cid); 269 } 270 271 /* Ignore no started transaction */ 272 if (transaction == NULL) { 273 return; 274 } 275 276 if (packet_is_init(packet)) { 277 struct packet_init *packet_init = (struct packet_init *)packet; 278 transaction->resp_bcnt = packet_init_get_bcnt(packet_init); 279 transaction->resp_size = PACKET_INIT_DATA_SIZE; 280 281 if (packet_init->cid == BROADCAST_CID) { 282 /* Nonce checking for legitimate response */ 283 if (memcmp(transaction->nonce, packet_init->data, NONCE_SIZE) 284 != 0) { 285 return; 286 } 287 } 288 } else { 289 transaction->resp_size += PACKET_CONT_DATA_SIZE; 290 } 291 292 /* Transaction end check */ 293 if (transaction->resp_size >= transaction->resp_bcnt) { 294 u2f_transaction_close(key, cid); 295 } 296 u2f_send_to_guest(&key->base, packet); 297 } 298 299 static void u2f_passthru_read(void *opaque) 300 { 301 U2FPassthruState *key = opaque; 302 U2FKeyState *base = &key->base; 303 uint8_t packet[2 * U2FHID_PACKET_SIZE]; 304 int ret; 305 306 /* Full size base queue check */ 307 if (base->pending_in_num >= U2FHID_PENDING_IN_NUM) { 308 return; 309 } 310 311 ret = read(key->hidraw_fd, packet, sizeof(packet)); 312 if (ret < 0) { 313 /* Detach */ 314 if (base->dev.attached) { 315 usb_device_detach(&base->dev); 316 u2f_passthru_reset(key); 317 } 318 return; 319 } 320 if (ret != U2FHID_PACKET_SIZE) { 321 return; 322 } 323 u2f_passthru_recv_from_host(key, packet); 324 } 325 326 static void u2f_passthru_recv_from_guest(U2FKeyState *base, 327 const uint8_t packet[U2FHID_PACKET_SIZE]) 328 { 329 U2FPassthruState *key = PASSTHRU_U2F_KEY(base); 330 uint8_t host_packet[U2FHID_PACKET_SIZE + 1]; 331 ssize_t written; 332 333 if (packet_is_init(packet)) { 334 u2f_transaction_start(key, (struct packet_init *)packet); 335 } 336 337 host_packet[0] = 0; 338 memcpy(host_packet + 1, packet, U2FHID_PACKET_SIZE); 339 340 written = write(key->hidraw_fd, host_packet, sizeof(host_packet)); 341 if (written != sizeof(host_packet)) { 342 error_report("%s: Bad written size (req 0x%zu, val 0x%zd)", 343 TYPE_U2F_PASSTHRU, sizeof(host_packet), written); 344 } 345 } 346 347 static void u2f_passthru_unrealize(U2FKeyState *base) 348 { 349 U2FPassthruState *key = PASSTHRU_U2F_KEY(base); 350 351 u2f_passthru_reset(key); 352 qemu_close(key->hidraw_fd); 353 } 354 355 static void u2f_passthru_realize(U2FKeyState *base, Error **errp) 356 { 357 U2FPassthruState *key = PASSTHRU_U2F_KEY(base); 358 int fd; 359 360 if (key->hidraw == NULL) { 361 error_setg(errp, "%s: Missing hidraw", TYPE_U2F_PASSTHRU); 362 return; 363 } 364 365 fd = qemu_open(key->hidraw, O_RDWR); 366 if (fd < 0) { 367 error_setg(errp, "%s: Failed to open %s", TYPE_U2F_PASSTHRU, 368 key->hidraw); 369 return; 370 } 371 key->hidraw_fd = fd; 372 u2f_passthru_reset(key); 373 } 374 375 static int u2f_passthru_post_load(void *opaque, int version_id) 376 { 377 U2FPassthruState *key = opaque; 378 u2f_passthru_reset(key); 379 return 0; 380 } 381 382 static const VMStateDescription u2f_passthru_vmstate = { 383 .name = "u2f-key-passthru", 384 .version_id = 1, 385 .minimum_version_id = 1, 386 .post_load = u2f_passthru_post_load, 387 .fields = (VMStateField[]) { 388 VMSTATE_U2F_KEY(base, U2FPassthruState), 389 VMSTATE_END_OF_LIST() 390 } 391 }; 392 393 static Property u2f_passthru_properties[] = { 394 DEFINE_PROP_STRING("hidraw", U2FPassthruState, hidraw), 395 DEFINE_PROP_END_OF_LIST(), 396 }; 397 398 static void u2f_passthru_class_init(ObjectClass *klass, void *data) 399 { 400 DeviceClass *dc = DEVICE_CLASS(klass); 401 U2FKeyClass *kc = U2F_KEY_CLASS(klass); 402 403 kc->realize = u2f_passthru_realize; 404 kc->unrealize = u2f_passthru_unrealize; 405 kc->recv_from_guest = u2f_passthru_recv_from_guest; 406 dc->desc = "QEMU U2F passthrough key"; 407 dc->vmsd = &u2f_passthru_vmstate; 408 device_class_set_props(dc, u2f_passthru_properties); 409 } 410 411 static const TypeInfo u2f_key_passthru_info = { 412 .name = TYPE_U2F_PASSTHRU, 413 .parent = TYPE_U2F_KEY, 414 .instance_size = sizeof(U2FPassthruState), 415 .class_init = u2f_passthru_class_init 416 }; 417 418 static void u2f_key_passthru_register_types(void) 419 { 420 type_register_static(&u2f_key_passthru_info); 421 } 422 423 type_init(u2f_key_passthru_register_types) 424