FIDO U2FHID features a keep-alive response command (code 0xbb). A
keep-alive response signifies that the request is being processed
and the transaction should not be closed yet.
u2f-passthru does not recognize this command, and hence closes the
transaction prematurely upon receiving it. This prevents some U2F
security keys from being passed through correctly (Yubikey 4/5).
Fix this by recognizing the keep-alive response and, if received,
by keeping the transaction alive regardless of the resp_bcnt limit.
Signed-off-by: David Bouman <dbouman03@gmail.com>
Fixes: 299976b050bf (hw/usb: Add U2F key passthru mode)
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2293
---
hw/usb/u2f-passthru.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/hw/usb/u2f-passthru.c b/hw/usb/u2f-passthru.c
index d0fb7b377c..c1e4db3467 100644
--- a/hw/usb/u2f-passthru.c
+++ b/hw/usb/u2f-passthru.c
@@ -296,10 +296,14 @@ static void u2f_passthru_recv_from_host(U2FPassthruState *key,
return;
}
+ bool keepalive = false;
if (packet_is_init(packet)) {
transaction->resp_bcnt = packet_init_get_bcnt(packet);
transaction->resp_size = PACKET_INIT_DATA_SIZE;
+ if (packet->init.cmd == U2FHID_CMD_KEEPALIVE)
+ keepalive = true;
+
if (packet->cid == BROADCAST_CID) {
/* Nonce checking for legitimate response */
if (memcmp(transaction->nonce, packet->init.data, NONCE_SIZE)
@@ -312,7 +316,7 @@ static void u2f_passthru_recv_from_host(U2FPassthruState *key,
}
/* Transaction end check */
- if (transaction->resp_size >= transaction->resp_bcnt) {
+ if (!keepalive && transaction->resp_size >= transaction->resp_bcnt) {
u2f_transaction_close(key, cid);
}
u2f_send_to_guest(&key->base, raw_packet);
--
2.34.1