Exemple #1
0
    async def storage_menu(self):
        """Manage storage"""
        buttons = [
            # id, text
            (None, "Key management"),
            (0, "Save key to flash"),
            (1, "Load key from flash"),
            (2, "Delete key from flash"),
        ]

        # we stay in this menu until back is pressed
        while True:
            # wait for menu selection
            menuitem = await self.show(Menu(buttons, last=(255, None)))
            # process the menu button:
            # back button
            if menuitem == 255:
                return
            elif menuitem == 0:
                await self.save_mnemonic()
                await self.show(
                    Alert("Success!",
                          "Your key is stored in flash now.",
                          button_text="OK"))
            elif menuitem == 1:
                await self.load_mnemonic()
                await self.show(
                    Alert("Success!", "Your key is loaded.", button_text="OK"))
            elif menuitem == 2:
                await self.delete_mnemonic()
                await self.show(
                    Alert("Success!",
                          "Your key is deleted from flash.",
                          button_text="OK"))
    async def storage_menu(self):
        """Manage storage"""
        enabled = self.connection.isCardInserted()
        buttons = [
            # id, text
            (None, "Smartcard storage"),
            (0, "Save key to the card", enabled),
            (1, "Load key from the card", enabled),
            (2, "Delete key from the card", enabled),
            (3, "Use a different card", enabled)
        ]

        # we stay in this menu until back is pressed
        while True:
            note = "Card fingerprint: %s" % self.hexid
            # wait for menu selection
            menuitem = await self.show(
                Menu(buttons, note=note, last=(255, None)))
            # process the menu button:
            # back button
            if menuitem == 255:
                return
            elif menuitem == 0:
                await self.save_mnemonic()
                await self.show(
                    Alert(
                        "Success!",
                        "Your key is stored on the smartcard now.",
                        button_text="OK",
                    ))
            elif menuitem == 1:
                await self.load_mnemonic()
                await self.show(
                    Alert("Success!", "Your key is loaded.", button_text="OK"))
            elif menuitem == 2:
                await self.delete_mnemonic()
                await self.show(
                    Alert(
                        "Success!",
                        "Your key is deleted from the smartcard.",
                        button_text="OK",
                    ))
            elif menuitem == 3:
                if await self.show(
                        Prompt(
                            "Switching the smartcard",
                            "To use a different smartcard you need "
                            "to provide a PIN for current one first!\n\n"
                            "Continue?")):
                    self.lock()
                    await self.unlock()
                    self.lock()
                    self.applet.close_secure_channel()
                    await self.show(
                        Alert("Please swap the card",
                              "Now you can insert another card and set it up.",
                              button_text="Continue"))
                    await self.check_card(check_pin=True)
                    await self.unlock()
Exemple #3
0
 async def settings_menu(self, show_screen, keystore):
     title = "QR scanner"
     controls = [{
         "label": "Enable QR scanner",
         "hint":
         "Enable or disable QR scanner and remove corresponding button from the main menu",
         "value": self.settings.get("enabled", True)
     }, {
         "label": "Sound",
         "hint": "To beep or not to beep?",
         "value": self.settings.get("sound", True)
     }, {
         "label": "Aim light",
         "hint": "Laser eyes!",
         "value": self.settings.get("aim", True)
     }, {
         "label": "Flashlight",
         "hint": "Can create blicks on the screen",
         "value": self.settings.get("light", False)
     }]
     scr = HostSettings(controls, title=title)
     res = await show_screen(scr)
     if res:
         enabled, sound, aim, light = res
         self.settings = {
             "enabled": enabled,
             "aim": aim,
             "light": light,
             "sound": sound,
         }
         self.save_settings(keystore)
         self.configure()
         await show_screen(
             Alert("Success!", "\n\nSettings updated!",
                   button_text="Close"))
Exemple #4
0
 async def show_xpub(self, derivation, show_screen):
     self.show_loader(title="Deriving the key...")
     derivation = derivation.rstrip("/")
     net = NETWORKS[self.network]
     xpub = self.keystore.get_xpub(derivation)
     ver = bip32.detect_version(derivation, default="xpub", network=net)
     canonical = xpub.to_base58(net["xpub"])
     slip132 = xpub.to_base58(ver)
     if slip132 == canonical:
         slip132 = None
     fingerprint = hexlify(self.keystore.fingerprint).decode()
     prefix = "[%s%s]" % (
         fingerprint,
         derivation[1:],
     )
     res = await show_screen(
         XPubScreen(xpub=canonical, slip132=slip132, prefix=prefix))
     if res:
         fname = "%s-%s.txt" % (fingerprint, derivation[2:].replace(
             "/", "-"))
         if not platform.is_sd_present():
             raise AppError("SD card is not present")
         platform.mount_sdcard()
         with open(platform.fpath("/sd/%s" % fname), "w") as f:
             f.write(res)
         platform.unmount_sdcard()
         await show_screen(
             Alert("Saved!",
                   "Extended public key is saved to the file:\n\n%s" %
                   fname,
                   button_text="Close"))
Exemple #5
0
    async def setup_pin(self, get_word=None):
        """
        PIN setup screen - first choose, then confirm
        If PIN codes are the same -> return the PIN
        If not -> try again
        """
        scr = PinScreen(
            title="Choose your PIN code",
            note="Remember these words,"
            "they will stay the same on this device.",
            get_word=self.get_auth_word,
            subtitle=self.pin_subtitle,
        )
        pin1 = await self.show(scr)

        scr = PinScreen(
            title="Confirm your PIN code",
            note="Remember these words,"
            "they will stay the same on this device.",
            get_word=self.get_auth_word,
            subtitle=self.pin_subtitle,
        )
        pin2 = await self.show(scr)

        # check if PIN is the same
        if pin1 == pin2:
            return pin1
        # if not - show an error
        await self.show(Alert("Error!", "PIN codes are different!"))
        return await self.setup_pin(get_word)
Exemple #6
0
    async def export_mnemonic(self):
        if await self.show(
                Prompt(
                    "Warning", "You need to confirm your PIN code "
                    "to export your recovery phrase.\n\n"
                    "Your recovery phrase will be saved "
                    "to the SD card as plain text.\n\n"
                    "Anybody who has access to this SD card "
                    "will be able to read your recovery phrase!\n\n"
                    "Continue?")):
            self.lock()
            await self.unlock()

            filename = "seed-export-%s.txt" % self.mnemonic.split()[0]
            filepath = "%s/%s" % (self.sdpath, filename)

            if not platform.is_sd_present():
                raise KeyStoreError("SD card is not present")

            platform.mount_sdcard()

            with open(filepath, "w") as f:
                f.write("bip39: ")
                f.write(self.mnemonic)

            platform.unmount_sdcard()

            await self.show(
                Alert("Success!",
                      "Your seed is exported.\n\nName: %s" % filename,
                      button_text="OK"))
Exemple #7
0
 async def show_xpub(self, derivation, show_screen):
     self.show_loader(title="Deriving the key...")
     derivation = derivation.rstrip("/")
     net = NETWORKS[self.network]
     xpub = self.keystore.get_xpub(derivation)
     ver = bip32.detect_version(derivation, default="xpub", network=net)
     canonical = xpub.to_base58(net["xpub"])
     slip132 = xpub.to_base58(ver)
     if slip132 == canonical:
         slip132 = None
     fingerprint = hexlify(self.keystore.fingerprint).decode()
     prefix = "[%s%s]" % (
         fingerprint,
         derivation[1:],
     )
     res = await show_screen(XPubScreen(xpub=canonical, slip132=slip132, prefix=prefix))
     if res == XPubScreen.CREATE_WALLET:
         await self.create_wallet(derivation, canonical, prefix, ver, show_screen)
     elif res:
         filename = "%s-%s.txt" % (fingerprint, derivation[2:].replace("/", "-"))
         self.write_file(filename, res)
         await show_screen(
             Alert("Saved!",
                   "Extended public key is saved to the file:\n\n%s" % filename,
                   button_text="Close")
         )
Exemple #8
0
 async def change_pin(self):
     # get_auth_word function can generate words from part of the PIN
     old_pin = await self.get_pin(title="First enter your old PIN code")
     # check pin - will raise if not valid
     self._unlock(old_pin)
     new_pin = await self.setup_pin()
     self._change_pin(old_pin, new_pin)
     await self.show(
         Alert("Success!", "PIN code is sucessfully changed!", button_text="OK")
     )
Exemple #9
0
    async def storage_menu(self):
        """Manage storage"""
        buttons = [
            # id, text
            (None, "Manage keys on SD card and internal flash"),
            (0, "Save key"),
            (1, "Load key"),
            (2, "Delete key"),
        ]

        # disabled if SD card is not present
        buttons.append(
            (3, "Export recovery phrase to SD", platform.is_sd_present()))

        # we stay in this menu until back is pressed
        while True:
            # wait for menu selection
            menuitem = await self.show(Menu(buttons, last=(255, None)))
            # process the menu button:
            # back button
            if menuitem == 255:
                return
            elif menuitem == 0:
                filename = await self.save_mnemonic()
                if filename:
                    await self.show(
                        Alert("Success!",
                              "Your key is stored now.\n\nName: %s" % filename,
                              button_text="OK"))
            elif menuitem == 1:
                if await self.load_mnemonic():
                    await self.show(
                        Alert("Success!",
                              "Your key is loaded.",
                              button_text="OK"))
            elif menuitem == 2:
                if await self.delete_mnemonic():
                    await self.show(
                        Alert("Success!",
                              "Your key is deleted.",
                              button_text="OK"))
            elif menuitem == 3:
                await self.export_mnemonic()
Exemple #10
0
    async def storage_menu(self):
        """Manage storage and display of the recovery phrase"""
        enabled = self.connection.isCardInserted()
        buttons = [
            # id, text
            (None, "Smartcard storage"),
            (0, "Save key to the card", enabled),
            (1, "Load key from the card", enabled),
            (2, "Delete key from the card", enabled),
            (3, "Show recovery phrase"),
        ]

        # we stay in this menu until back is pressed
        while True:
            # wait for menu selection
            menuitem = await self.show(Menu(buttons, last=(255, None)))
            # process the menu button:
            # back button
            if menuitem == 255:
                return
            elif menuitem == 0:
                await self.save_mnemonic()
                await self.show(
                    Alert(
                        "Success!",
                        "Your key is stored on the smartcard now.",
                        button_text="OK",
                    ))
            elif menuitem == 1:
                await self.load_mnemonic()
                await self.show(
                    Alert("Success!", "Your key is loaded.", button_text="OK"))
            elif menuitem == 2:
                await self.delete_mnemonic()
                await self.show(
                    Alert(
                        "Success!",
                        "Your key is deleted from the smartcard.",
                        button_text="OK",
                    ))
            elif menuitem == 3:
                await self.show(MnemonicScreen(self.mnemonic))
Exemple #11
0
    async def storage_menu(self):
        """Manage storage and display of the recovery phrase"""
        buttons = [
            # id, text
            (None, "Manage keys on SD card and internal flash"),
            (0, "Save key"),
            (1, "Load key"),
            (2, "Delete key"),
            (None, "Other"),
            (3, "Show recovery phrase"),
        ]

        # we stay in this menu until back is pressed
        while True:
            # wait for menu selection
            menuitem = await self.show(Menu(buttons, last=(255, None)))
            # process the menu button:
            # back button
            if menuitem == 255:
                return
            elif menuitem == 0:
                if await self.save_mnemonic():
                    await self.show(
                        Alert("Success!",
                              "Your key is stored now.",
                              button_text="OK"))
            elif menuitem == 1:
                if await self.load_mnemonic():
                    await self.show(
                        Alert("Success!",
                              "Your key is loaded.",
                              button_text="OK"))
            elif menuitem == 2:
                if await self.delete_mnemonic():
                    await self.show(
                        Alert("Success!",
                              "Your key is deleted.",
                              button_text="OK"))
            elif menuitem == 3:
                await self.show_mnemonic()
Exemple #12
0
 async def settings_menu(self, show_screen, keystore):
     title = self.settings_button or "Settings"
     controls = [{
         "label": "Enable " + title,
         "hint":
         "This setting will completely enable or disable this communication channel and remove corresponding button from the main menu",
         "value": self.settings["enabled"]
     }]
     scr = HostSettings(controls, title=title)
     res = await show_screen(scr)
     if res:
         self.settings["enabled"] = res[0]
         self.save_settings(keystore)
         await show_screen(
             Alert("Success!", "\n\nSettings updated!",
                   button_text="Close"))
Exemple #13
0
    async def change_pin(self):
        # get_auth_word function can generate words from part of the PIN
        old_pin = await self.get_pin(title="First enter your old PIN code",
                                     with_cancel=True)
        if old_pin is None:
            return

        # check pin - will raise if not valid
        self.show_loader("Verifying PIN code...")
        self._unlock(old_pin)
        new_pin = await self.setup_pin()
        self.show_loader("Setting new PIN code...")
        self._change_pin(old_pin, new_pin)
        await self.show(
            Alert("Success!",
                  "PIN code is successfully changed!",
                  button_text="OK"))
Exemple #14
0
 async def export_menu(self, show_screen):
     while True:
         buttons = [
             (None, "Export options"),
             (1, "Show QR code"),
             (2, "Save to SD card", platform.is_sd_present()),
         ]
         menuitem = await show_screen(
             Menu(buttons,
                  last=(255, None),
                  title="Export wallet %s" % self.name))
         desc = add_checksum(str(self.descriptor.branch(0)))
         obj = {
             "descriptor": desc,
             "label": self.name,
         }
         if self.descriptor.num_branches > 2:
             obj["branches"] = [
                 add_checksum(str(self.descriptor.branch(i)))
                 for i in range(self.descriptor.num_branches)
             ]
         if menuitem == 1:
             await show_screen(
                 QRAlert(
                     title="Export wallet %s" % self.name,
                     qr_width=450,
                     message=
                     "Scan this QR code with compatible software wallet",
                     qr_message=json.dumps(obj)))
         elif menuitem == 2:
             if not platform.is_sd_present():
                 raise WalletError("SD card is not present")
             platform.mount_sdcard()
             fname = "/sd/%s.json" % self.name
             with open(platform.fpath(fname), "w") as f:
                 json.dump(obj, f)
             platform.unmount_sdcard()
             await show_screen(
                 Alert("Success!",
                       "Wallet descriptor is written to\n\n%s" % fname))
         else:
             return
Exemple #15
0
 async def init(self, show_fn):
     """
     Waits for keystore media 
     and loads internal secret and PIN state
     """
     self.show = show_fn
     platform.maybe_mkdir(self.path)
     self.load_secret(self.path)
     self.load_state()
     # check if init is called for the first time
     # and we have less than max PIN attempts
     if (not self.initialized
             and self.pin_attempts_left != self.pin_attempts_max):
         scr = Alert("Warning!",
                     "You only have %d of %d attempts\n"
                     "to enter correct PIN code!" %
                     (self.pin_attempts_left, self.pin_attempts_max),
                     button_text="OK")
         await self.show(scr)
     self.initialized = True
Exemple #16
0
    async def show_card_info(self):
        note = "Card fingerprint: %s" % self.hexid
        version = "%s v%s" % (self.applet.NAME, self.applet.version)
        platform = self.applet.platform
        data = self.applet.get_secret()
        key_saved = len(data) > 0
        encrypted = True
        decryptable = True
        same_mnemonic = False
        if key_saved:
            try:
                d, encrypted = self.parse_data(data)
                if "entropy" in d:
                    self._is_key_saved = True
                same_mnemonic = (self.mnemonic == bip39.mnemonic_from_bytes(
                    d["entropy"]))
            except KeyStoreError as e:
                decryptable = False
        # yes = lv.SYMBOL.OK+" Yes"
        # no = lv.SYMBOL.CLOSE+" No"
        yes = "Yes"
        no = "No"
        props = [
            "\n#7f8fa4 PLATFORM #",
            "Implementation: %s" % platform,
            "Version: %s" % version,
            "\n#7f8fa4 KEY INFO: #",
            "Key saved: " + (yes if key_saved else no),
        ]
        if key_saved:
            if decryptable:
                props.append("Same as current key: " +
                             (yes if same_mnemonic else no))
            props.append("Encrypted: " + (yes if encrypted else no))
            if encrypted:
                props.append("Decryptable: " + (yes if decryptable else no))

        scr = Alert("Smartcard info", "\n\n".join(props), note=note)
        scr.message.set_recolor(True)
        await self.show(scr)
Exemple #17
0
    async def menu(self, show_screen, show_all=False):
        net = NETWORKS[self.network]
        coin = net["bip32"]
        if not show_all:
            buttons = [
                (None, "Recommended"),
                ("m/84h/%dh/%dh" % (coin, self.account), "Single key"),
                ("m/48h/%dh/%dh/2h" % (coin, self.account), "Multisig"),
                (None, "Other keys"),
                (0, "Show more keys"),
                (2, "Change account number"),
                (1, "Enter custom derivation"),
                (3, "Export all keys to SD"),
            ]
        else:
            buttons = [
                (None, "Recommended"),
                (
                    "m/84h/%dh/%dh" % (coin, self.account),
                    "Single Native Segwit\nm/84h/%dh/%dh" % (coin, self.account)
                ),
                (
                    "m/48h/%dh/%dh/2h" % (coin, self.account),
                    "Multisig Native Segwit\nm/48h/%dh/%dh/2h" % (coin, self.account),
                ),
                (None, "Other keys"),
            ]
            if self.is_taproot_enabled:
                buttons.append((
                    "m/86h/%dh/%dh" % (coin, self.account),
                    "Single Taproot\nm/86h/%dh/%dh" % (coin, self.account)
                ))
            buttons.extend([
                (
                    "m/49h/%dh/%dh" % (coin, self.account),
                    "Single Nested Segwit\nm/49h/%dh/%dh" % (coin, self.account)
                ),
                (
                    "m/48h/%dh/%dh/1h" % (coin, self.account),
                    "Multisig Nested Segwit\nm/48h/%dh/%dh/1h" % (coin, self.account),
                ),
            ])
        # wait for menu selection
        menuitem = await show_screen(Menu(buttons, last=(255, None),
                                          title="Select the key",
                                          note="Current account number: %d" % self.account))

        # process the menu button:
        # back button
        if menuitem == 255:
            return False
        elif menuitem == 0:
            return await self.menu(show_screen, show_all=True)
        elif menuitem == 1:
            der = await show_screen(DerivationScreen())
            if der is not None:
                await self.show_xpub(der, show_screen)
                return True
        elif menuitem == 3:
            file_format = await self.save_menu(show_screen)
            if file_format:
                filename = self.save_all_to_sd(file_format)
                await show_screen(
                    Alert("Saved!",
                          "Public keys are saved to the file:\n\n%s" % filename,
                          button_text="Close")
                )
        elif menuitem == 2:
            account = await show_screen(NumericScreen(current_val=str(self.account)))
            if account and int(account) > 0x80000000:
                raise AppError('Account number too large')
            try:
                self.account = int(account)
            except:
                self.account = 0
            return await self.menu(show_screen)
        else:
            await self.show_xpub(menuitem, show_screen)
            return True
        return False
Exemple #18
0
    async def storage_menu(self):
        """Manage storage"""
        enabled = self.connection.isCardInserted()
        buttons = [
            # id, text, enabled, color
            (None, "Smartcard storage"),
            (0, "Save key to the card", enabled),
            (1, "Load key from the card", enabled and self.is_key_saved),
            (2, "Delete key from the card", enabled and self.is_key_saved),
            (3, "Use a different card", enabled),
            (4, lv.SYMBOL.SETTINGS + " Get card info", enabled),
            # (5, lv.SYMBOL.TRASH + " Wipe the card", enabled, 0x951E2D),
        ]

        # we stay in this menu until back is pressed
        while True:
            # check updated status
            buttons[2] = (1, "Load key from the card", enabled
                          and self.is_key_saved)
            buttons[3] = (2, "Delete key from the card", enabled
                          and self.is_key_saved)
            note = "Card fingerprint: %s" % self.hexid
            # wait for menu selection
            menuitem = await self.show(
                Menu(buttons, note=note, last=(255, None)))
            # process the menu button:
            # back button
            if menuitem == 255:
                return
            elif menuitem == 0:
                await self.save_mnemonic()
                await self.show(
                    Alert(
                        "Success!",
                        "Your key is stored on the smartcard now.",
                        button_text="OK",
                    ))
            elif menuitem == 1:
                await self.load_mnemonic()
                await self.show(
                    Alert("Success!", "Your key is loaded.", button_text="OK"))
            elif menuitem == 2:
                if await self.show(
                        Prompt("Are you sure?",
                               "\n\nDelete the key from the card?")):
                    await self.delete_mnemonic()
                    await self.show(
                        Alert(
                            "Success!",
                            "Your key is deleted from the smartcard.",
                            button_text="OK",
                        ))
            elif menuitem == 3:
                if await self.show(
                        Prompt(
                            "Switching the smartcard",
                            "To use a different smartcard you need "
                            "to provide a PIN for current one first!\n\n"
                            "Continue?")):
                    self.lock()
                    await self.unlock()
                    self.lock()
                    self.applet.close_secure_channel()
                    self._userkey = None
                    await self.show(
                        Alert("Please swap the card",
                              "Now you can insert another card and set it up.",
                              button_text="Continue"))
                    await self.check_card(check_pin=True)
                    await self.unlock()
            elif menuitem == 4:
                await self.show_card_info()
            else:
                raise KeyStoreError("Invalid menu")