Skip to content

Commit

Permalink
Merge #406: [1.2.x] Backports for 1.2.1
Browse files Browse the repository at this point in the history
b45607c bitbox02: unlock during enumerate() (Marko Bencun)
070d5ea bitbox02: fix enumerate regression (Marko Bencun)
087bc69 Add back support for Ledger legacy USB product IDs (TamtamHero)
b8f0901 Upgrade USB enumeration logic for Ledger products (TamtamHero)

Pull request description:

  Backports #403 #399 #404 to the 1.x branch for a 1.2.1 release.

Top commit has no ACKs.

Tree-SHA512: 98803ebe742b0277762f7ae008dc70bddfcc98c72ff0eedbe265637ae8e117e0585a9a7df617cb03e078fcbf9b3a31a2e12f6827a975d9042994a4f616e52048
  • Loading branch information
achow101 committed Nov 24, 2020
2 parents afec2cd + b45607c commit 1b65d78
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 35 deletions.
68 changes: 41 additions & 27 deletions hwilib/devices/bitbox02.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ def enumerate(password: str = "") -> List[Dict[str, object]]:
path = device_info["path"].decode()
client = Bitbox02Client(path)
client.set_noise_config(SilentNoiseConfig())
d_data: Dict[str, object] = {}
bb02 = None
with handle_errors(common_err_msgs["enumerate"], d_data):
bb02 = client.init(expect_initialized=None)
version, platform, edition, unlocked = bitbox02.BitBox02.get_info(
client.transport
)
Expand All @@ -188,25 +192,32 @@ def enumerate(password: str = "") -> List[Dict[str, object]]:

assert isinstance(edition, BitBox02Edition)

d_data = {
"type": "bitbox02",
"path": path,
"model": {
BitBox02Edition.MULTI: "bitbox02_multi",
BitBox02Edition.BTCONLY: "bitbox02_btconly",
}[edition],
"needs_pin_sent": False,
"needs_passphrase_sent": False,
}
d_data.update(
{
"type": "bitbox02",
"path": path,
"model": {
BitBox02Edition.MULTI: "bitbox02_multi",
BitBox02Edition.BTCONLY: "bitbox02_btconly",
}[edition],
"needs_pin_sent": False,
"needs_passphrase_sent": False,
}
)

with handle_errors(common_err_msgs["enumerate"], d_data):
if not unlocked:
raise DeviceNotReadyError(
"Please load wallet to unlock."
if _using_external_gui
else "Please use any subcommand to unlock"
)
d_data["fingerprint"] = client.get_master_fingerprint_hex()
if bb02 is not None:
with handle_errors(common_err_msgs["enumerate"], d_data):
if not bb02.device_info()["initialized"]:
raise DeviceNotReadyError(
"BitBox02 is not initialized. Please initialize it using the BitBoxApp."
)
elif not unlocked:
raise DeviceNotReadyError(
"Please load wallet to unlock."
if _using_external_gui
else "Please use any subcommand to unlock"
)
d_data["fingerprint"] = client.get_master_fingerprint_hex()

result.append(d_data)

Expand Down Expand Up @@ -246,7 +257,7 @@ def __init__(self, path: str, password: str = "", expert: bool = False) -> None:
Initializes a new BitBox02 client instance.
"""
super().__init__(path, password=password, expert=expert)
if password != "":
if password:
raise BadArgumentError(
"The BitBox02 does not accept a passphrase from the host. Please enable the passphrase option and enter the passphrase on the device during unlock."
)
Expand All @@ -264,7 +275,7 @@ def __init__(self, path: str, password: str = "", expert: bool = False) -> None:
def set_noise_config(self, noise_config: BitBoxNoiseConfig) -> None:
self.noise_config = noise_config

def init(self, expect_initialized: bool = True) -> bitbox02.BitBox02:
def init(self, expect_initialized: Optional[bool] = True) -> bitbox02.BitBox02:
if self.bb02 is not None:
return self.bb02

Expand All @@ -282,14 +293,17 @@ def init(self, expect_initialized: bool = True) -> bitbox02.BitBox02:
raise
self.bb02 = bb02
is_initialized = bb02.device_info()["initialized"]
if expect_initialized:
if not is_initialized:
raise HWWError(
"The BitBox02 must be initialized first.",
DEVICE_NOT_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."
)
elif is_initialized:
raise UnavailableActionError("The BitBox02 must be wiped before setup.")

return bb02
raise Exception(
Expand Down
25 changes: 17 additions & 8 deletions hwilib/devices/ledger.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,14 @@
SIMULATOR_PATH = 'tcp:127.0.0.1:9999'

LEDGER_VENDOR_ID = 0x2c97
LEDGER_DEVICE_IDS = [
0x0001, # Ledger Nano S
0x0004, # Ledger Nano X
]
LEDGER_MODEL_IDS = {
0x10: "ledger_nano_s",
0x40: "ledger_nano_x"
}
LEDGER_LEGACY_PRODUCT_IDS = {
0x0001: "ledger_nano_s",
0x0004: "ledger_nano_x"
}

# minimal checking of string keypath
def check_keypath(key_path):
Expand Down Expand Up @@ -386,9 +390,8 @@ def toggle_passphrase(self):
def enumerate(password=''):
results = []
devices = []
for device_id in LEDGER_DEVICE_IDS:
devices.extend(hid.enumerate(LEDGER_VENDOR_ID, device_id))
devices.append({'path': SIMULATOR_PATH.encode(), 'interface_number': 0, 'product_id': 1})
devices.extend(hid.enumerate(LEDGER_VENDOR_ID, 0))
devices.append({'path': SIMULATOR_PATH.encode(), 'interface_number': 0, 'product_id': 0x1000})

for d in devices:
if ('interface_number' in d and d['interface_number'] == 0
Expand All @@ -397,7 +400,13 @@ def enumerate(password=''):

path = d['path'].decode()
d_data['type'] = 'ledger'
d_data['model'] = 'ledger_nano_x' if d['product_id'] == 0x0004 else 'ledger_nano_s'
model = d['product_id'] >> 8
if model in LEDGER_MODEL_IDS.keys():
d_data['model'] = LEDGER_MODEL_IDS[model]
elif d['product_id'] in LEDGER_LEGACY_PRODUCT_IDS.keys():
d_data['model'] = LEDGER_LEGACY_PRODUCT_IDS[d['product_id']]
else:
continue
d_data['path'] = path

if path == SIMULATOR_PATH:
Expand Down

0 comments on commit 1b65d78

Please sign in to comment.