-
-
Notifications
You must be signed in to change notification settings - Fork 675
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
auto-lock for trezor-core #1027
Conversation
open question: should FIDO use the global idle timer for its PIN timeout? I think FIDO should respect the user-configured auto-lock delay, AS LONG AS it's 10 minutes (the default) or less. Opinions? If it respects the autolock fully, we can remove the custom timeout feature of the PIN dialog. We can also replace the custom timeout by an idle callback, for a slightly different result. As implemented, the PIN timeout applies to FIDO unlocks only. With an idle callback, it would apply to all device activity. |
277cb17
to
76b01a0
Compare
the UI report seems wrong -- as if tests copied a lot of their screens from their longer friends |
660d4f4
to
8f3480b
Compare
@@ -26,6 +26,7 @@ async def get(ctx: wire.Context) -> str: | |||
|
|||
|
|||
async def _request_from_user(ctx: wire.Context) -> str: | |||
workflow.close_others() # request exclusive UI access |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this needed? _request_on_device
is calling button_request
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's because of _entry_dialog()
. We are now in the passphrase flow and that always puts something on screen
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean why it is not in _entry_dialog
then. In _entry_dialog
for _request_on_host
and _request_on_device
has it in button_request
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes more sense to me like this.
Before (no "request UI exclusivity" exists): we draw things as needed, and as a special case, in _entry_dialog
we also need to make sure that default is killed.
Now: in _request_from_user
we are entering the UI-enabled part of passphrase entry. Request UI exclusivity because we need it in either case: the fact that button_request()
does the same thing later becomes an implementation detail.
if __debug__ and self.should_notify_layout_change: | ||
from apps.debug import notify_layout_change | ||
|
||
self.should_notify_layout_change = False | ||
notify_layout_change(self) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems at least this block we could refactor to separate ui.Layout function and use here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That doesn't really seem worth it? This is a one-off. If we end up doing something like this in more places, the requirements will become clearer.
(fwiw if we want to get rid of this, we could change backlight_fade(style.BACKLIGHT_NORMAL)
to backlight.fade(self.backlight_level)
and remove the copy-paste. It didn't seem worth polluting all Layouts with a new variable, but maybe the cost is negligible.
same thing with the loop.sleep()
which could also be a class or instance variable, and in case of homescreen and lockscreen could be changed to something like loop.DO_NOT_RESCHEDULE
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
backlight.fade(self.backlight_level)
I would do it. My concern is that if we change something in Layout.handle_rendering
we forget to add it here. IMHO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done in 7a2b8e7
Btw this is not turned on on default for both old and new users correct? I should talk to Product whether we would like to turn this on in Suite by default (aka during onboarding). I have reviewed the code without the fido2 part. The loop and workflow code looks alright as well AFAICT! |
Very good point. With this PR, auto-lock is always enabled. If the user never configured it, the default timeout of 10 minutes is used. |
Unable to test. When I load this firmware on a physical device I get a black screen after startup. |
That's because this PR is missing b01b24f. That is why force-pushes are needed sometimes :/. Maybe let's finish the review and rebase then? |
I tried to rebase on master and run this on a real hardware. Currently the device freezes after the initial startup, I'm investigating. |
i fixed the scheduler issue by lowering resolution, and cherry-picked b01b24f so that this branch can now run on real hardware. Ready for review again. |
|
I don't think I moved this. Compared to 2.3.0 it looks the same. |
core/src/trezor/loop.py
Outdated
value is the calculated deadline. | ||
"""Pause current task and resume it after given delay. | ||
|
||
Resultvalue is the calculated deadline. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed (i think?) in 50052a6
core/src/storage/device.py
Outdated
@@ -40,6 +40,8 @@ | |||
HOMESCREEN_MAXSIZE = 16384 | |||
AUTOLOCK_DELAY_MINIMUM = 10 * 1000 # 10 seconds | |||
AUTOLOCK_DELAY_DEFAULT = 10 * 60 * 1000 # 10 minutes | |||
# autolock intervals larger than AUTOLOCK_DELAY_MAX cause issues in the scheduler |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.. AUTOLOCK_DELAY_MAXIMUM ..
Yes, I am nit-picking 👼 .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done in a00abbf
I see it's also not showing the label, so that might be causing a shift in the background image. |
so that pytest doesn't think it is a testcase
The original wait_layout was unreliable, because there are no guarantees re order of arrival of the respective events. Still, TT's event handling is basically deterministic, so as long as the host sent its messages close enough to each other, the order worked out. This is no longer the case with the introduction of loop.spawn: TT's behavior is still deterministic, but now ButtonAck is processed *before* the corresponding wait_layout, so the waiting side waits forever. In the new process, the host must first register to receive layout events, and then receives all of them (so the number of calls to wait_layout must match the number of layout changes). DebugLinkWatchLayout message must be version-gated, because of an unfortunate collection of bugs in previous versions wrt unknown message handling; and this interests us because upgrade-tests are using wait_layout feature.
this makes sense, really: close_others() requests UI exclusivity, and that is something that generally happens at the same places we emit a ButtonRequest
This will have unintended consequences if you call a wirelink function on the debulink interface. TT allows this ... and will behave badly.
This prevents a race condition where sometimes an Initialize message could arrive before the homescreen was fully booted -- and Recovery homescreen would cancel it as part of its bootup sequence.
This avoids problems with large timeouts causing the scheduler queue to think the time counter has overflown, and ordering the autolock task before immediate tasks. The maximum reasonable time difference is 0x20000000, which in microseconds is ~8 minutes, but in milliseconds a more reasonable ~6 days.
54ffbb5
to
093f886
Compare
fixes #75
this has WAY more commits than it rightly should.
The core functionality is f1c3172, which introduces a global idle timer. It is then possible to register an idle callback, which, after a configurable timeout (we already have autolock timeout fields in storage), engages the lock.
Another big part is a new
loop.spawn
syscall (docs included), which serves as a "controllable" subtask on the application level. All workflow tasks are nowspawn
ed, so that it is possible to shut them down when the autolock engages. (this also answers this comment)As a nicety, the lockscreen is now dimmed. I'm not sure about the backlight level, maybe we'll need to tweak that a little.
The remaining 80 % of the work is busywork:
workflow.kill_default()
was superseded byworkflow.close_others()
, because we now have the capability to shut down ALL tasks, not just the default.button_request()
function that does just that in addition toButtonRequest/ButtonAck
calls. The logic here is that when you are callingButtonRequest
, you want to do something on the UI, and so you need to shut down whatever was there before you.debuglink.wait_layout
has been reworked. If you are usingwait_layout
, you need to wait for all layout changes that happen. In exchange, it's resilient to race conditions: you will receive all layout changes that happen.ButtonRequestType.PinEntry
, to cleanly distinguish the TT asking for PIN on screen.There's work to be done on the FIDO app, where another
loop.spawn
should be used for the keepalive loop, and that might simplify #729.