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

"sendpin" command hangs when connected to a Trezor Model One #636

Open
nadahalli opened this issue Oct 12, 2022 · 12 comments
Open

"sendpin" command hangs when connected to a Trezor Model One #636

nadahalli opened this issue Oct 12, 2022 · 12 comments

Comments

@nadahalli
Copy link

nadahalli commented Oct 12, 2022

Commands to reproduce the problem.

$./hwi enumerate
[{"type": "trezor", "path": "webusb:001:3", "label": "My Trezor", "model": "trezor_1", "needs_pin_sent": true, "needs_passphrase_sent": true, "error": "Could not open client or get fingerprint information: Trezor is locked. Unlock by using 'promptpin' and then 'sendpin'.", "code": -12}]
$./hwi --device-type trezor promptpin
Use 'sendpin' to provide the number positions for the PIN as displayed on your device's screen
Use the numeric keypad to describe number positions. The layout is:
    7 8 9
    4 5 6
    1 2 3
{"success": true}

When this command runs, the device shows the keypad in a randomzied order, for example:

2 3 5
6 7 1
9 4 8

Say my pin is "1111", I believe I have to send the pin "9999" (real pin mapped to the randomized keypad).

$./hwi --device-type trezor sendpin 9999

This command hangs in the TrezorLib interruptRead command here:

chunk = self.handle.interruptRead(endpoint, 64)

Any ideas what I am doing wrong with respect to the Trezor state machine protocol? Is there some other order in which promptpin and sendpin have to be used?

@prusnak
Copy link
Collaborator

prusnak commented Oct 12, 2022

Say my pin is "1111", I believe I have to send the pin "9999"

No. To enter the PIN 1111 you have to enter 6666. (It's the other way around).

@nadahalli
Copy link
Author

nadahalli commented Oct 12, 2022

Both types of mapping cause the command line to hang.

Just to verify that things are working, I ran ./Trezor-Suite-22.9.3-linux-x86_64.AppImage and it shows a keypad with dots on the computer, and a scrambled keypad on the device. Entering the pin 1111 in the right "position" on the desktop unlocks the wallet.

Additionally, after the pin unlocked the device for the desktop app (/Trezor-Suite-22.9.3-linux-x86_64.AppImage), I closed the desktop app and ran the promptpin command on the commandline again, where it hangs again. My guess is that it has something to do with session management on the device side, but I could be wrong.

@prusnak
Copy link
Collaborator

prusnak commented Oct 12, 2022

Does it help if you reboot and try again? (Do not start Trezor Suite before!)

@nadahalli
Copy link
Author

I can start again at "enumerate" if I disconnect and reconnect the hardware wallet. Promptpin works after that, but sendpin fails again. Is that what you mean?

@prusnak
Copy link
Collaborator

prusnak commented Oct 12, 2022

Is that what you mean?

No, reboot is as in reboot your computer.

@prusnak
Copy link
Collaborator

prusnak commented Oct 12, 2022

Also, do you have the udev files installed? https://wiki.trezor.io/Udev_rules

@nadahalli
Copy link
Author

nadahalli commented Oct 12, 2022

Reboot of the computer doesn't help.
Yes, I have installed Trezor's udev rules. That doesn't seem to help either.

Without "priming" the Trezor with the promptpin command, just sending a dummy sendpin command doesn't hang, but returns a success: false message.

$./hwi --device-type trezor sendpin 1111
{"success": false}

In other information, I have the following versions of the software.

$./hwi --version
hwi 2.1.1
$uname -rv
5.13.0-051300-generic #202106272333 SMP Sun Jun 27 23:36:43 UTC 2021

Trezor firmware version 1.11.2

@prusnak
Copy link
Collaborator

prusnak commented Oct 12, 2022

Any ideas @matejcik ?

@bitcoin-core bitcoin-core deleted a comment from Whiskey992 Oct 12, 2022
@matejcik
Copy link
Contributor

I can reproduce the problem locally.
It seems that when using -t trezor but not -d <path>, hwi tries to enumerate devices.
This tries to query the Trezor for its features.
That cannot be done while Trezor is waiting for PIN, so Trezor ignores the message, so you get stuck at reading from device.

@matejcik
Copy link
Contributor

full stack trace at the stuck point is helpful:

Traceback (most recent call last):
  File "/home/matejcik/.cache/pypoetry/virtualenvs/hwi-zW7m4qgq-py3.10/bin/hwi", line 6, in <module>
    sys.exit(main())
  File "/home/matejcik/projekty/prace/HWI/hwilib/_cli.py", line 304, in main
    result = process_commands(sys.argv[1:])
  File "/home/matejcik/projekty/prace/HWI/hwilib/_cli.py", line 280, in process_commands
    client = find_device(args.password, args.device_type, args.fingerprint, args.expert, args.chain)
  File "/home/matejcik/projekty/prace/HWI/hwilib/commands.py", line 148, in find_device
    devices = enumerate(password)
  File "/home/matejcik/projekty/prace/HWI/hwilib/commands.py", line 117, in enumerate
    result.extend(imported_dev.enumerate(password)) # type: ignore
  File "/home/matejcik/projekty/prace/HWI/hwilib/devices/trezor.py", line 860, in enumerate
    client._prepare_device()
  File "/home/matejcik/projekty/prace/HWI/hwilib/devices/trezor.py", line 312, in _prepare_device
    resp = self.client.refresh_features()
  File "/home/matejcik/projekty/prace/HWI/hwilib/devices/trezorlib/tools.py", line 286, in wrapped_f
    return f(client, *args, **kwargs)
  File "/home/matejcik/projekty/prace/HWI/hwilib/devices/trezorlib/client.py", line 293, in refresh_features
    resp = self.call_raw(messages.GetFeatures())
  File "/home/matejcik/projekty/prace/HWI/hwilib/devices/trezorlib/client.py", line 145, in call_raw
    return self._raw_read()
  File "/home/matejcik/projekty/prace/HWI/hwilib/devices/trezorlib/client.py", line 162, in _raw_read
    msg_type, msg_bytes = self.transport.read()
  File "/home/matejcik/projekty/prace/HWI/hwilib/devices/trezorlib/transport/protocol.py", line 114, in read
    return self.protocol.read()
  File "/home/matejcik/projekty/prace/HWI/hwilib/devices/trezorlib/transport/protocol.py", line 144, in read
    msg_type, datalen, first_chunk = self.read_first()
  File "/home/matejcik/projekty/prace/HWI/hwilib/devices/trezorlib/transport/protocol.py", line 154, in read_first
    chunk = self.handle.read_chunk()
  File "/home/matejcik/projekty/prace/HWI/hwilib/devices/trezorlib/transport/webusb.py", line 76, in read_chunk
    chunk = self.handle.interruptRead(endpoint, 64)
  File "/home/matejcik/.cache/pypoetry/virtualenvs/hwi-zW7m4qgq-py3.10/lib/python3.10/site-packages/usb1/__init__.py", line 1483, in interruptRead
    transferred = self._interruptTransfer(
  File "/home/matejcik/.cache/pypoetry/virtualenvs/hwi-zW7m4qgq-py3.10/lib/python3.10/site-packages/usb1/__init__.py", line 1424, in _interruptTransfer
    mayRaiseUSBError(libusb1.libusb_interrupt_transfer(
KeyboardInterrupt

offending call:
https://github.com/bitcoin-core/HWI/blob/master/hwilib/devices/trezor.py#L860

@bitcoin-core bitcoin-core deleted a comment Oct 13, 2022
@bitcoin-core bitcoin-core deleted a comment from prusnak Oct 13, 2022
@nadahalli
Copy link
Author

Passing the device path works, as it prevents the find_device call.

$./hwi --device-type trezor promptpin
Use 'sendpin' to provide the number positions for the PIN as displayed on your device's screen
Use the numeric keypad to describe number positions. The layout is:
    7 8 9
    4 5 6
    1 2 3
{"success": true}
$./hwi --device-path webusb:001:3 --device-type trezor sendpin 5555
{"success": true}

The offending call is here:

client = find_device(args.password, args.device_type, args.fingerprint, args.expert, args.chain)
, where without --device-path, HWI does a find_device. I guess it cannot be really fixed because if the path is not known, you have to find the device anyway. For now, I will just use both and make it work.

@harding
Copy link
Contributor

harding commented Mar 3, 2024

I think this issue should be re-opened. I just hit this today using a Trezor One for the first time with HWI. As described in the OP, the following command is successful:

hwi -t trezor promptpin

But this command will indefinitely hang:

hwi -t trezor sendpin 1234567890

The only way to sendpin is by using both device and type:

hwi -t trezor -d webusb:001:1 sendpin 1234567890

I think two changes should be made to avoid user confusion:

  1. sendpin for Trezor devices should fail if -d has not been passed. That's preferable to an indefinite hang and it's an opportunity to tell the user that they need to pass -d.
  2. promptpin for Trezor devices should mention in its message that -d needs to passed for the subsequent sendpin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants