diff --git a/src/apps/fido_u2f/__init__.py b/src/apps/fido_u2f/__init__.py index e81ee5d551..11ebc0ab35 100644 --- a/src/apps/fido_u2f/__init__.py +++ b/src/apps/fido_u2f/__init__.py @@ -447,11 +447,13 @@ class ConfirmState: self.confirmed = await dialog -_reg_state = None +_state = None # state for msg_register and msg_authenticate, None or ConfirmState +_lastreq = None # last received register/authenticate request, None or Req async def msg_register(req: Msg) -> Cmd: - global _reg_state + global _state + global _lastreq from apps.common import storage @@ -459,21 +461,30 @@ async def msg_register(req: Msg) -> Cmd: log.warning(__name__, 'not initialized') return msg_error(req, _SW_CONDITIONS_NOT_SATISFIED) - # check input data + # check length of input data if len(req.data) != 64: log.warning(__name__, '_SW_WRONG_LENGTH req.data') return msg_error(req, _SW_WRONG_LENGTH) + # parse challenge and app_id chal = req.data[:32] app_id = req.data[32:] - if _reg_state is None: - _reg_state = ConfirmState(_CONFIRM_REGISTER, app_id) - _reg_state.fork() - if _reg_state.confirmed is None: + # check equality with last request + if _lastreq is None or _lastreq.__dict__ != req.__dict__: + if _state is not None: + _state.kill() + _state = None + _lastreq = req + + # wait for a button or continue + if _state is None: + _state = ConfirmState(_CONFIRM_REGISTER, app_id) + _state.fork() + if _state.confirmed is None: log.info(__name__, 'waiting for button') return msg_error(req, _SW_CONDITIONS_NOT_SATISFIED) - _reg_state = None + _state = None buf = msg_register_sign(chal, app_id) @@ -530,14 +541,10 @@ def msg_register_sign(challenge: bytes, app_id: bytes) -> bytes: return buf -_auth_state = None -_auth_lastreq = None - - async def msg_authenticate(req: Msg) -> Cmd: - global _auth_state - global _auth_lastreq + global _state + global _lastreq from apps.common import storage @@ -575,19 +582,20 @@ async def msg_authenticate(req: Msg) -> Cmd: return msg_error(req, _SW_WRONG_DATA) # check equality with last request - if _auth_lastreq is None or _auth_lastreq.__dict__ != req.__dict__: - if _auth_state is not None: - _auth_state.kill() - _auth_state = None - _auth_lastreq = req + if _lastreq is None or _lastreq.__dict__ != req.__dict__: + if _state is not None: + _state.kill() + _state = None + _lastreq = req - if _auth_state is None: - _auth_state = ConfirmState(_CONFIRM_AUTHENTICATE, auth.appId) - _auth_state.fork() - if _auth_state.confirmed is None: + # wait for a button or continue + if _state is None: + _state = ConfirmState(_CONFIRM_AUTHENTICATE, auth.appId) + _state.fork() + if _state.confirmed is None: log.info(__name__, 'waiting for button') return msg_error(req, _SW_CONDITIONS_NOT_SATISFIED) - _auth_state = None + _state = None buf = msg_authenticate_sign(auth.chal, auth.appId, node.private_key())