From 7bf873f189e32a0ed97f81f99bbc078d0a360b43 Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Thu, 28 May 2026 14:36:01 +0200 Subject: [PATCH 1/2] Fix U2F UP not timing out There was 2 issues preventing the U2F UP from timing out: 1. There was no timeout waiting for packets while U2F UP is on. 2. When timing out for packets the U2F UP logic was skipped. The fixes are: 1. A timeout of 1 second is used when U2F UP is on. 2. We execute the rest of the loop body (except for packet processing). --- src/lib.rs | 49 +++++++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index eb79d91b..edbbca8b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,15 +33,16 @@ fn main() -> ! { let mut u2f: Option = None; debug!("OpenSK initialized"); loop { - match (wink.is_some(), opensk_ctap.should_wink()) { - (true, true) | (false, false) => (), - (false, true) => wink = Some(blink::Blink::new_ms(100)), - (true, false) => wink = None, - } - let mut packet = [0; 64]; - let timeout = wink.is_some().then_some(500); - match env::hid_connection::recv(&mut packet, timeout).unwrap() { - RecvStatus::Timeout => continue, + update_state(&mut wink, opensk_ctap.should_wink(), || { + blink::Blink::new_ms(100) + }); + let mut packet = Some([0; 64]); + let mut timeout = None; + timeout = timeout.or(wink.is_some().then_some(500)); + #[cfg(feature = "ctap1")] + (timeout = timeout.or(u2f.is_some().then_some(1000))); + match env::hid_connection::recv(packet.as_mut().unwrap(), timeout).unwrap() { + RecvStatus::Timeout => packet = None, RecvStatus::Received(endpoint) => assert_eq!(endpoint, UsbEndpoint::MainHid), } #[cfg(feature = "ctap1")] @@ -49,16 +50,28 @@ fn main() -> ! { u2f = None; opensk_ctap.u2f_grant_user_presence(); } - for packet in opensk_ctap.process_hid_packet(&packet, Transport::MainHid) { - opensk_ctap - .env() - .hid_connection() - .send(&packet, UsbEndpoint::MainHid) - .unwrap(); + if let Some(packet) = packet { + for packet in opensk_ctap.process_hid_packet(&packet, Transport::MainHid) { + opensk_ctap + .env() + .hid_connection() + .send(&packet, UsbEndpoint::MainHid) + .unwrap(); + } } #[cfg(feature = "ctap1")] - if opensk_ctap.u2f_needs_user_presence() && u2f.is_none() { - u2f = Some(touch::Touch::new()); - } + update_state( + &mut u2f, + opensk_ctap.u2f_needs_user_presence(), + touch::Touch::new, + ); + } +} + +fn update_state(state: &mut Option, target: bool, build: impl FnOnce() -> T) { + *state = match (state.is_some(), target) { + (true, true) | (false, false) => return, + (true, false) => None, + (false, true) => Some(build()), } } From 6c70df9b648c7fbd765830120b5de30bf268fc5b Mon Sep 17 00:00:00 2001 From: ia0 Date: Thu, 28 May 2026 20:55:04 +0200 Subject: [PATCH 2/2] review --- src/lib.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index edbbca8b..aaaefc40 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,13 +36,15 @@ fn main() -> ! { update_state(&mut wink, opensk_ctap.should_wink(), || { blink::Blink::new_ms(100) }); - let mut packet = Some([0; 64]); - let mut timeout = None; - timeout = timeout.or(wink.is_some().then_some(500)); + let mut recv_packet = Some([0; 64]); + let mut timeout = false; + timeout |= wink.is_some(); #[cfg(feature = "ctap1")] - (timeout = timeout.or(u2f.is_some().then_some(1000))); - match env::hid_connection::recv(packet.as_mut().unwrap(), timeout).unwrap() { - RecvStatus::Timeout => packet = None, + (timeout |= u2f.is_some()); + match env::hid_connection::recv(recv_packet.as_mut().unwrap(), timeout.then_some(500)) + .unwrap() + { + RecvStatus::Timeout => recv_packet = None, RecvStatus::Received(endpoint) => assert_eq!(endpoint, UsbEndpoint::MainHid), } #[cfg(feature = "ctap1")] @@ -50,12 +52,12 @@ fn main() -> ! { u2f = None; opensk_ctap.u2f_grant_user_presence(); } - if let Some(packet) = packet { - for packet in opensk_ctap.process_hid_packet(&packet, Transport::MainHid) { + if let Some(recv_packet) = recv_packet { + for send_packet in opensk_ctap.process_hid_packet(&recv_packet, Transport::MainHid) { opensk_ctap .env() .hid_connection() - .send(&packet, UsbEndpoint::MainHid) + .send(&send_packet, UsbEndpoint::MainHid) .unwrap(); } }