def init(self, expect_initialized: Optional[bool] = True) -> bitbox02.BitBox02: if self.bb02 is not None: return self.bb02 for device_info in devices.get_any_bitbox02s(): if device_info["path"].decode() == self.device_path: bb02 = bitbox02.BitBox02( transport=self.transport, device_info=device_info, noise_config=self.noise_config, ) try: bb02.check_min_version() except FirmwareVersionOutdatedException as exc: sys.stderr.write("WARNING: {}\n".format(exc)) raise self.bb02 = bb02 is_initialized = bb02.device_info()["initialized"] if expect_initialized is not None: if expect_initialized: if not is_initialized: raise HWWError( "The BitBox02 must be initialized first.", DEVICE_NOT_INITIALIZED, ) elif is_initialized: raise UnavailableActionError( "The BitBox02 must be wiped before setup.") return bb02 raise Exception( "Could not find the hid device info for path {}".format( self.device_path))
def pairing_dialog(self): def pairing_step(code: str, device_response: Callable[[], bool]) -> bool: msg = "Please compare and confirm the pairing code on your BitBox02:\n" + code self.handler.show_message(msg) try: res = device_response() except: # Close the hid device on exception with self.device_manager().hid_lock: hid_device.close() raise finally: self.handler.finished() return res def exists_remote_static_pubkey(pubkey: bytes) -> bool: bitbox02_config = self.config.get("bitbox02") noise_keys = bitbox02_config.get("remote_static_noise_keys") if noise_keys is not None: if pubkey.hex() in [noise_key for noise_key in noise_keys]: return True return False def set_remote_static_pubkey(pubkey: bytes) -> None: if not exists_remote_static_pubkey(pubkey): bitbox02_config = self.config.get("bitbox02") if bitbox02_config.get("remote_static_noise_keys") is not None: bitbox02_config["remote_static_noise_keys"].append(pubkey.hex()) else: bitbox02_config["remote_static_noise_keys"] = [pubkey.hex()] self.config.set_key("bitbox02", bitbox02_config) def get_noise_privkey() -> Optional[bytes]: bitbox02_config = self.config.get("bitbox02") privkey = bitbox02_config.get("noise_privkey") if privkey is not None: return bytes.fromhex(privkey) return None def set_noise_privkey(privkey: bytes) -> None: bitbox02_config = self.config.get("bitbox02") bitbox02_config["noise_privkey"] = privkey.hex() self.config.set_key("bitbox02", bitbox02_config) def attestation_warning() -> None: self.handler.show_error( "The BitBox02 attestation failed.\nTry reconnecting the BitBox02.\nWarning: The device might not be genuine, if the\n problem persists please contact Shift support.", blocking=True ) class NoiseConfig(bitbox_api_protocol.BitBoxNoiseConfig): """NoiseConfig extends BitBoxNoiseConfig""" def show_pairing(self, code: str, device_response: Callable[[], bool]) -> bool: return pairing_step(code, device_response) def attestation_check(self, result: bool) -> None: if not result: attestation_warning() def contains_device_static_pubkey(self, pubkey: bytes) -> bool: return exists_remote_static_pubkey(pubkey) def add_device_static_pubkey(self, pubkey: bytes) -> None: return set_remote_static_pubkey(pubkey) def get_app_static_privkey(self) -> Optional[bytes]: return get_noise_privkey() def set_app_static_privkey(self, privkey: bytes) -> None: return set_noise_privkey(privkey) if self.bitbox02_device is None: with self.device_manager().hid_lock: hid_device = hid.device() hid_device.open_path(self.bitbox_hid_info["path"]) bitbox02_device = bitbox02.BitBox02( transport=u2fhid.U2FHid(hid_device), device_info=self.bitbox_hid_info, noise_config=NoiseConfig(), ) try: bitbox02_device.check_min_version() except FirmwareVersionOutdatedException: raise self.bitbox02_device = bitbox02_device self.fail_if_not_initialized()
def connect_to_usb_bitbox(debug: bool, use_cache: bool) -> int: """ Connects and runs the main menu on a BitBox02 connected over USB. """ try: bitbox = devices.get_any_bitbox02() except devices.TooManyFoundException: print("Multiple bitboxes detected. Only one supported") return 1 except devices.NoneFoundException: try: bootloader = devices.get_any_bitbox02_bootloader() except devices.TooManyFoundException: print("Multiple bitbox bootloaders detected. Only one supported") return 1 except devices.NoneFoundException: print("Neither bitbox nor bootloader found.") return 1 else: hid_device = hid.device() hid_device.open_path(bootloader["path"]) bootloader_connection = bitbox02.Bootloader( u2fhid.U2FHid(hid_device), bootloader) boot_app = SendMessageBootloader(bootloader_connection) return boot_app.run() else: def show_pairing(code: str, device_response: Callable[[], bool]) -> bool: print( "Please compare and confirm the pairing code on your BitBox02:" ) print(code) if not device_response(): return False return input("Accept pairing? [y]/n: ").strip() != "n" class NoiseConfig(util.NoiseConfigUserCache): """NoiseConfig extends NoiseConfigUserCache""" def __init__(self) -> None: super().__init__("shift/send_message") def show_pairing(self, code: str, device_response: Callable[[], bool]) -> bool: return show_pairing(code, device_response) def attestation_check(self, result: bool) -> None: if result: print("Device attestation PASSED") else: print("Device attestation FAILED") class NoiseConfigNoCache(bitbox_api_protocol.BitBoxNoiseConfig): """NoiseConfig extends BitBoxNoiseConfig""" def show_pairing(self, code: str, device_response: Callable[[], bool]) -> bool: return show_pairing(code, device_response) def attestation_check(self, result: bool) -> None: if result: print("Device attestation PASSED") else: print("Device attestation FAILED") if use_cache: config: bitbox_api_protocol.BitBoxNoiseConfig = NoiseConfig() else: config = NoiseConfigNoCache() hid_device = hid.device() hid_device.open_path(bitbox["path"]) bitbox_connection = bitbox02.BitBox02( transport=u2fhid.U2FHid(hid_device), device_info=bitbox, noise_config=config) try: bitbox_connection.check_min_version() except FirmwareVersionOutdatedException as exc: print("WARNING: ", exc) if debug: print("Device Info:") pprint.pprint(bitbox) return SendMessage(bitbox_connection, debug).run()