Coverage for admin/unlock.py: 89%
46 statements
« prev ^ index » next coverage.py v7.2.7, created at 2024-04-05 20:41 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2024-04-05 20:41 +0000
1# The MIT License (MIT)
2#
3# Copyright (c) 2021 RSK Labs Ltd
4#
5# Permission is hereby granted, free of charge, to any person obtaining a copy of
6# this software and associated documentation files (the "Software"), to deal in
7# the Software without restriction, including without limitation the rights to
8# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9# of the Software, and to permit persons to whom the Software is furnished to do
10# so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice shall be included in all
13# copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21# SOFTWARE.
23from ledger.hsm2dongle import HSM2Dongle
24from ledger.pin import BasePin
25from .misc import (
26 info,
27 head,
28 bls,
29 get_hsm,
30 dispose_hsm,
31 PIN_ERROR_MESSAGE_ANYCHARS,
32 AdminError,
33 ask_for_pin,
34)
37def do_unlock(options, exit=True, no_exec=False, label=True):
38 if label:
39 head("### -> Unlock", fill="#")
41 hsm = None
43 # Validate pin (if given)
44 pin = None
45 if options.pin is not None:
46 if not BasePin.is_valid(options.pin.encode(), options.any_pin):
47 raise AdminError(PIN_ERROR_MESSAGE_ANYCHARS)
48 pin = options.pin.encode()
50 # Connection
51 hsm = get_hsm(options.verbose)
53 # Mode check
54 info("Finding mode... ", options.verbose)
55 mode = hsm.get_current_mode()
56 info(f"Mode: {mode.name.capitalize()}")
58 # Onboard check
59 if mode in [HSM2Dongle.MODE.BOOTLOADER, HSM2Dongle.MODE.SIGNER]:
60 info("Is device onboarded? ... ", options.verbose)
61 is_onboarded = hsm.is_onboarded()
62 info(f"Onboarded: {bls(is_onboarded)}")
63 if not is_onboarded:
64 raise AdminError("Device not onboarded")
66 # Modes for which we can't unlock
67 if mode == HSM2Dongle.MODE.UNKNOWN:
68 raise AdminError("Device mode unknown. Already unlocked? Otherwise disconnect "
69 "and re-connect the ledger and try again")
70 if mode == HSM2Dongle.MODE.SIGNER or mode == HSM2Dongle.MODE.UI_HEARTBEAT:
71 raise AdminError("Device already unlocked")
73 # Echo check
74 info("Sending echo... ", options.verbose)
75 if not hsm.echo():
76 raise AdminError("Echo error")
77 info("Echo OK")
79 # Ask the user for a pin if one not given
80 if pin is None:
81 info("Please enter the pin.")
82 pin = ask_for_pin(any_pin=True)
84 # Unlock device with PIN
85 info("Unlocking with PIN... ", options.verbose)
86 if not hsm.unlock(pin):
87 raise AdminError("Unable to unlock: PIN mismatch")
88 info("PIN accepted")
90 # Exit the bootloader, go into menu (or, if app is properly signed, into
91 # the app)
92 if exit:
93 autoexec = not (options.no_exec or no_exec)
94 info(f"Exiting to menu/app (execute signer: {bls(autoexec)})... ",
95 options.verbose)
96 try:
97 hsm.exit_menu(autoexec=autoexec)
98 except Exception:
99 # exit_menu() always throws due to USB disconnection. we don't care
100 pass
101 info("Exit OK")
103 dispose_hsm(hsm)