From 637cc55cdde7c139543bc618b8b2f64ebf90bfcc Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bonicoli Date: Tue, 2 Mar 2021 11:59:07 +0100 Subject: [PATCH] Wait that udev has set owner and group Udev rules take some time to be applied, then fido2 lib fails to open the key since group of the device hasn't been set: $ solo key update Wrote temporary copy of firmware-4.1.1.json to /tmp/tmpa67i8qxc.json sha256sums coincide: 45e7071107fa5acb494e4c5d4831344dd531b1a537a230a6157f4f71dba87e2c Switching into bootloader mode... error: problem flashing firmware! no Solo found With this patch, the key is found after switching into bootloader mode (but the key doesn't switch to bootloader mode, which is another issue): $ solo key update Wrote temporary copy of firmware-4.1.1.json to /tmp/tmpvwzbaat0.json sha256sums coincide: 45e7071107fa5acb494e4c5d4831344dd531b1a537a230a6157f4f71dba87e2c Switching into bootloader mode... Wait for device '205C36995548'... using signature version <=2.5.3 erasing firmware... Could not switch into bootloader mode. Please put key into bootloader mode: 1. Unplug key 2. While holding button, plug in key for 2s --- solo/cli/update.py | 2 -- solo/client.py | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/solo/cli/update.py b/solo/cli/update.py index c2c3d10..8c24148 100644 --- a/solo/cli/update.py +++ b/solo/cli/update.py @@ -12,7 +12,6 @@ import json import sys import tempfile -import time import click import requests @@ -184,7 +183,6 @@ def update(serial, yes, local_firmware_server, alpha): if not solo_client.is_solo_bootloader(): print("Switching into bootloader mode...") solo_client.enter_bootloader_or_die() - time.sleep(0.5) solo_client = solo.client.find(serial) solo_client.set_reboot(False) diff --git a/solo/client.py b/solo/client.py index b47cf24..c168deb 100644 --- a/solo/client.py +++ b/solo/client.py @@ -9,6 +9,7 @@ import base64 import json +import os import struct import sys import tempfile @@ -16,6 +17,7 @@ from cryptography import x509 from cryptography.hazmat.backends import default_backend +from fido2._pyu2f import hidtransport from fido2.attestation import Attestation from fido2.client import Fido2Client from fido2.ctap import CtapError @@ -259,10 +261,26 @@ def enter_solo_bootloader(self): this command will tell the token to boot directly to the bootloader so it can be reprogrammed """ + statinfo = os.stat(self.dev.descriptor["path"]) + serial_number = self.dev.descriptor.get("serial_number") + if self.exchange != self.exchange_hid: self.send_data_hid(CTAPHID.INIT, "\x11\x11\x11\x11\x11\x11\x11\x11") self.send_data_hid(SoloBootloader.HIDCommandEnterBoot, "") + print("Wait for device %r..." % serial_number) + for i in range(0, 5): + time.sleep(0.5) + for d in hidtransport.hid.Enumerate(): + if hidtransport.HidUsageSelector(d): + if d.get("serial_number") == serial_number: + statnew = os.stat(d["path"]) + if ( + statinfo.st_uid == statnew.st_uid + and statinfo.st_gid == statnew.st_gid + ): + break + def enter_bootloader_or_die(self): try: self.enter_solo_bootloader()