Exemple #1
0
    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))
Exemple #2
0
    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()
Exemple #3
0
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()