Skip to content
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

Improve Nitrokey Start upgrade process #255

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

robin-nitrokey
Copy link
Member

This PR improves the Nitrokey Start upgrade process with the goal to avoid bricked devices after failed updates.

Changes

Checklist

  • tested with Python3.9
  • run make check or make fix for the formatting check
  • signed commits
  • updated documentation (e.g. parameter description, inline doc, docs.nitrokey)
  • added labels

With this patch, we register a custom signal handler for the start
update subcommand that asks the user for confirmation if they trigger a
SIGINT signal, for example by pressing Ctrl+C.
This patch improves the error messages for the Nitrokey Start update
process so that it no longer recommends device reinsertion.  Instead,
users should try to repeat the update if it fails.  If they remove the
device after an unsuccessful update, they risk bricking the device.
@robin-nitrokey robin-nitrokey added the device/Nitrokey Start Concerns Nitrokey Start label Jul 19, 2022
With this patch, we replace the /releases API endpoint with
/releases/latest.  This endpoint only returns proper releases, not
pre-releases, so users are no longer offered firmware release
candidates.
@robin-nitrokey
Copy link
Member Author

I’ve added checks for the udev rules (#232) and changed the release lookup to ignore pre-releases.

Copy link
Member

@szszszsz szszszsz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good!
Please check the note regarding the udev rules.

for d in dirs:
if os.path.isdir(d):
for name in os.listdir(d):
if fnmatch.fnmatch(name, "??-nitrokey.rules"):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIR using anything starting with number over 70- will probably not work. At some point we had a rule starting with 99-, which brought a couple of issues.
I would change this to accept only the official name, which starts with 41-, to avoid potential problems.
Ideally it would be really nice to check for the updates of the udev file and compare hashes to determine, whether it is up to date.

@szszszsz
Copy link
Member

A couple of ideas more:

  • It would be nice to check pynitrokey version against Pypi to see if it is the latest one before starting the update process.
  • One final thing I am considering is to make sure that other smart card services like gnupg and pcscd are not running during the update.

If that would not take significant effort, it would be great to have these two. What do you think @robin-nitrokey ?

@robin-nitrokey
Copy link
Member Author

One final thing I am considering is to make sure that other smart card services like gnupg and pcscd are not running during the update.

There’s already kill_smartcard_services that is called if the card is not found.

@szszszsz
Copy link
Member

Ok, but there might be one problem with it. Once bootloader shows up, it can be still attached by pcscd due to automatic rerun by systemd. Is this rechecked during connection attempt with the bootloader?

@robin-nitrokey
Copy link
Member Author

As far as I see, the exception handler that calls kill_smartcard_services wraps the main invocation so it should also catch bootloader issues. Also, kill_smartcard_services executes sudo systemctl stop pcscd pcscd.socket which should also stop automatic restarting via the socket.

@szszszsz
Copy link
Member

Alright. This is what I wanted to know. Looks good!

@szszszsz
Copy link
Member

szszszsz commented Aug 8, 2022

bump

@robin-nitrokey
Copy link
Member Author

From my point of view, this is ready to merge as soon it has been tested with an actual device.

@szszszsz
Copy link
Member

szszszsz commented Nov 8, 2022

I have merged in the latest master changes. Will merge to master if you do not mind @robin-nitrokey .

@szszszsz
Copy link
Member

@robin-nitrokey This looks OK for merge. Anything against?
I can fix the conflicts of course.

@robin-nitrokey
Copy link
Member Author

I think this should be tested at least once due to consequences of an update failure, otherwise it is good to merge.

@szszszsz szszszsz self-assigned this Dec 29, 2022
@daringer
Copy link
Collaborator

  • needs a rebase
  • tried it, some work, no real issues
  • nitropy start list works fine
  • nitropy start update leads to a:
Do you want to continue? [yes/no]: yes
...
Starting bootloader upload procedure
error while running update
	Exception encountered: OnlyBusyICCError('Found only busy ICC: [None]')
...

tried killing gpg-agent, factory-resetting, restart pcscd, run as root - all of them lead to the same output/error

@alt3r-3go
Copy link

alt3r-3go commented Feb 18, 2024

Just tested this one (after rebasing onto current master), works fine for me for list, start list and start update commands (I do not observe those "ICC" errors reported by @daringer earlier EDIT: I actually do, after factory-resetting the token, see below). Also [accidentally :)] tested the udev rules check - worked as intended.

I'd suggest merging this one, these seem to be worthwhile updates and there are some other ones that could be added later (e.g., #298, #91, to name but a few). I also plan for proposing one for the issue I'm personally facing (Nitrokey/nitrokey-start-firmware#23).

EDIT: noticed one small item about the udev message, please see a line comment below.

):
"""update device's firmware"""

if not find_udev_rules():

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed when testing my (unrelated) changes on top this PR - there is an udev-related advice in local_critical(), which seems to be redundant now, so probably should be removed.

GH review functionality doesn't allow me to attach a comment to an unchanged line, so putting it here. The line I'm talking about is:

f"- Please check if you have udev rules installed: {UDEV_URL}"

@alt3r-3go
Copy link

Looks like I actually do observe the "ICC" error. I had an already-provisioned Start and with that the start update only gave me the "6581" error described in Nitrokey/nitrokey-start-firmware#23. That's what I reported above. Now, after factory-resetting the token and trying the update again, I see the same ICC error. Apologies for any confusion caused. I'll dig into that and will report back if/when I find the root cause.

@alt3r-3go
Copy link

alt3r-3go commented Feb 18, 2024

That error is also present on the master for me, so doesn't seem to be related to this PR.

At the end of the day, it looks like something is holding on to the token, and after some iteration of killing gpg-agent, pcscd, gnome-keyring-agent (just in case), I'm now seeing a firm and repeatable USBTimeoutError(110, 'Operation timed out'), on both the rebased PR, master and PyPi version of pynitrokey, on two different hosts with two different VMs, but no ICC error.

The list works fine, and so does factory-reset via gpg, i.e., doesn't look like a bricked token.

Maybe this deserves a dedicated issue at this point. I'll continue debugging this later next week as this blocks me from updating my token.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
device/Nitrokey Start Concerns Nitrokey Start
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants