async def interact(self): # Just show the address... no real confirmation needed. try: self.refused = True msg = uio.StringIO() self.policy.explain(msg) msg.write('\n\nPress OK to enable HSM mode.') try: ch = await ux_show_story(msg, title=self.title) except AbortInteraction: ch = 'x' finally: del msg self.refused = (ch != 'y') if not self.refused and self.new_file: confirm_char = '12346'[ngu.random.uniform(5)] msg = '''Last chance. You are defining a new policy which \ allows the Coldcard to sign specific transactions without any further user approval.\n\n\ Press %s to save policy and enable HSM mode.''' % confirm_char ch = await ux_show_story(msg, title=self.title, escape='x' + confirm_char, strict_escape=True) self.refused = (ch != confirm_char) except BaseException as exc: self.failed = "Exception" sys.print_exception(exc) self.refused = True self.ux_done = True UserAuthorizedAction.cleanup() # cleanup already done, and nothing more here ... return if self.refused: self.done() # restores/draws menu (might be needed from USB mode) return # go into special HSM mode .. one-way trip self.policy.activate(self.new_file) the_ux.reset(hsm_ux_obj) return
def goto_top_menu(): # Start/restart menu system from menu import MenuSystem from flow import VirginSystem, NormalSystem, EmptyWallet, FactoryMenu from main import pa if version.is_factory_mode(): m = MenuSystem(FactoryMenu) elif pa.is_blank(): # let them play a little before picking a PIN first time m = MenuSystem(VirginSystem, should_cont=lambda: pa.is_blank()) else: assert pa.is_successful(), "nonblank but wrong pin" m = MenuSystem(EmptyWallet if pa.is_secret_blank() else NormalSystem) the_ux.reset(m) return m
async def start_hsm_approval(sf_len=0, usb_mode=False, startup_mode=False): # Show details of the proposed HSM policy (or saved one) # If approved, go into HSM mode and never come back to normal. UserAuthorizedAction.cleanup() is_new = True if sf_len: with SFFile(0, length=sf_len) as fd: json = fd.read(sf_len).decode() else: try: json = open(POLICY_FNAME, 'rt').read() except: raise ValueError("No existing policy") is_new = False # parse as JSON cant_fail = False try: try: js_policy = ujson.loads(json) except: raise ValueError("JSON parse fail") cant_fail = bool(js_policy.get('boot_to_hsm', False)) # parse the policy policy = HSMPolicy() policy.load(js_policy) except BaseException as exc: err = "HSM Policy invalid: %s: %s" % (problem_file_line(exc), str(exc)) if usb_mode: raise ValueError(err) # What to do in a menu case? Shouldn't happen anyway, but # maybe they upgraded the firmware, and so old policy file # isn't suitable anymore. # - or maybe the settings have been f-ed with. print(err) if startup_mode and cant_fail: # die as a brick here, not safe to proceed w/o HSM active import callgate, ux ux.show_fatal_error(err.replace(': ', ':\n ')) callgate.show_logout(1) # die w/ it visible # not reached await ux_show_story("Cannot start HSM.\n\n%s" % err) return # Boot-to-HSM feature: don't ask, just start policy immediately if startup_mode and policy.boot_to_hsm: msg = uio.StringIO() policy.explain(msg) policy.activate(False) the_ux.reset(hsm_ux_obj) return None ar = ApproveHSMPolicy(policy, is_new) UserAuthorizedAction.active_request = ar if startup_mode: return ar if usb_mode: # for USB case, kill any menu stack, and put our thing at the top abort_and_goto(UserAuthorizedAction.active_request) else: # menu item case: add to stack, so we can still back out from ux import the_ux the_ux.push(UserAuthorizedAction.active_request) return ar