def on_render(self) -> None: if not self.repaint: return image = None if not storage.is_initialized(): label = "Go to trezor.io/start" else: label = storage.device.get_label() or "My Trezor" image = storage.device.get_homescreen() if not image: image = res.load("apps/homescreen/res/bg.toif") if storage.is_initialized() and storage.device.no_backup(): ui.header_error("SEEDLESS") elif storage.is_initialized() and storage.device.unfinished_backup(): ui.header_error("BACKUP FAILED!") elif storage.is_initialized() and storage.device.needs_backup(): ui.header_warning("NEEDS BACKUP!") elif storage.is_initialized() and not config.has_pin(): ui.header_warning("PIN NOT SET!") else: ui.display.bar(0, 0, ui.WIDTH, ui.HEIGHT, ui.BG) ui.display.avatar(48, 48 - 10, image, ui.WHITE, ui.BLACK) ui.display.text_center(ui.WIDTH // 2, 220, label, ui.BOLD, ui.FG, ui.BG) self.repaint = False
def _check_state(msg: RecoveryDevice) -> None: if not msg.dry_run and storage.is_initialized(): raise wire.UnexpectedMessage("Already initialized") if msg.dry_run and not storage.is_initialized(): raise wire.NotInitialized("Device is not initialized") if msg.enforce_wordlist is False: raise wire.ProcessError( "Value enforce_wordlist must be True, Trezor Core enforces words automatically." )
def on_render(self) -> None: # warning bar on top if storage.is_initialized() and storage.device.no_backup(): ui.header_error("SEEDLESS") elif storage.is_initialized() and storage.device.unfinished_backup(): ui.header_error("BACKUP FAILED!") elif storage.is_initialized() and storage.device.needs_backup(): ui.header_warning("NEEDS BACKUP!") elif storage.is_initialized() and not config.has_pin(): ui.header_warning("PIN NOT SET!") else: ui.display.bar(0, 0, ui.WIDTH, ui.HEIGHT, ui.BG) # homescreen with shifted avatar and text on bottom ui.display.avatar(48, 48 - 10, self.image, ui.WHITE, ui.BLACK) ui.display.text_center(ui.WIDTH // 2, 220, self.label, ui.BOLD, ui.FG, ui.BG)
async def add_resident_credential( ctx: wire.Context, msg: WebAuthnAddResidentCredential) -> Success: if not storage.is_initialized(): raise wire.NotInitialized("Device is not initialized") if not msg.credential_id: raise wire.ProcessError("Missing credential ID parameter.") try: cred = Fido2Credential.from_cred_id(bytes(msg.credential_id), None) except Exception: text = Text("Import credential", ui.ICON_WRONG, ui.RED) text.normal( "The credential you are", "trying to import does", "not belong to this", "authenticator.", ) await require_confirm(ctx, text, confirm=None, cancel="Close") raise wire.ActionCancelled content = ConfirmContent(ConfirmAddCredential(cred)) await require_confirm(ctx, content) if store_resident_credential(cred): return Success(message="Credential added") else: raise wire.ProcessError("Internal credential storage is full.")
def _validate(msg: RecoveryDevice) -> None: if not msg.dry_run and storage.is_initialized(): raise wire.UnexpectedMessage("Already initialized") if msg.dry_run and not storage.is_initialized(): raise wire.NotInitialized("Device is not initialized") if msg.enforce_wordlist is False: raise wire.ProcessError( "Value enforce_wordlist must be True, Trezor Core enforces words automatically." ) if msg.dry_run: # check that only allowed fields are set for key, value in msg.__dict__.items(): if key not in DRY_RUN_ALLOWED_FIELDS and value is not None: raise wire.ProcessError( "Forbidden field set in dry-run: {}".format(key))
def get_features() -> Features: f = Features() f.vendor = "trezor.io" f.language = "en-US" f.major_version = utils.VERSION_MAJOR f.minor_version = utils.VERSION_MINOR f.patch_version = utils.VERSION_PATCH f.revision = utils.GITREV.encode() f.model = utils.MODEL f.device_id = storage.device.get_device_id() f.label = storage.device.get_label() f.initialized = storage.is_initialized() f.pin_protection = config.has_pin() f.pin_cached = config.has_pin() f.passphrase_protection = storage.device.is_passphrase_enabled() f.needs_backup = storage.device.needs_backup() f.unfinished_backup = storage.device.unfinished_backup() f.no_backup = storage.device.no_backup() f.flags = storage.device.get_flags() f.recovery_mode = storage.recovery.is_in_progress() f.backup_type = mnemonic.get_type() if utils.BITCOIN_ONLY: f.capabilities = [ Capability.Bitcoin, Capability.Crypto, Capability.Shamir, Capability.ShamirGroups, Capability.PassphraseEntry, ] else: f.capabilities = [ Capability.Bitcoin, Capability.Bitcoin_like, Capability.Binance, Capability.Cardano, Capability.Crypto, Capability.EOS, Capability.Ethereum, Capability.Lisk, Capability.Monero, Capability.NEM, Capability.Ripple, Capability.Stellar, Capability.Tezos, Capability.U2F, Capability.Shamir, Capability.ShamirGroups, Capability.PassphraseEntry, ] f.sd_card_present = io.SDCard().present() f.sd_protection = storage.sd_salt.is_enabled() f.wipe_code_protection = config.has_wipe_code() f.session_id = cache.get_session_id() f.passphrase_always_on_device = storage.device.get_passphrase_always_on_device( ) return f
async def get_keychain(ctx: wire.Context, namespaces: list) -> Keychain: if not storage.is_initialized(): raise wire.NotInitialized("Device is not initialized") seed = cache.get(cache.APP_COMMON_SEED) if seed is None: passphrase = await get_passphrase(ctx) seed = mnemonic.get_seed(passphrase) cache.set(cache.APP_COMMON_SEED, seed) keychain = Keychain(seed, namespaces) return keychain
def derive_slip21_node_without_passphrase(path: list) -> Slip21Node: if not storage.is_initialized(): raise Exception("Device is not initialized") seed = storage.cache.get_seed_without_passphrase() if seed is None: seed = mnemonic.get_seed(progress_bar=False) storage.cache.set_seed_without_passphrase(seed) node = Slip21Node(seed) node.derive_path(path) return node
def derive_slip21_node_without_passphrase(path: list) -> Slip21Node: if not storage.is_initialized(): raise Exception("Device is not initialized") seed = cache.get(cache.APP_COMMON_SEED_WITHOUT_PASSPHRASE) if seed is None: seed = mnemonic.get_seed(progress_bar=False) cache.set(cache.APP_COMMON_SEED_WITHOUT_PASSPHRASE, seed) node = Slip21Node(seed) node.derive_path(path) return node
def derive_node_without_passphrase( path: list, curve_name: str = "secp256k1" ) -> bip32.HDNode: if not storage.is_initialized(): raise Exception("Device is not initialized") seed = cache.get(cache.APP_COMMON_SEED_WITHOUT_PASSPHRASE) if seed is None: seed = mnemonic.get_seed(progress_bar=False) cache.set(cache.APP_COMMON_SEED_WITHOUT_PASSPHRASE, seed) node = bip32.from_seed(seed, curve_name) node.derive_path(path) return node
async def get_keychain(ctx: wire.Context, namespaces: list) -> Keychain: if not storage.is_initialized(): raise wire.NotInitialized("Device is not initialized") seed = storage.cache.get_seed() if seed is None: passphrase = storage.cache.get_passphrase() if passphrase is None: passphrase = await protect_by_passphrase(ctx) storage.cache.set_passphrase(passphrase) seed = mnemonic.get_seed(passphrase) storage.cache.set_seed(seed) keychain = Keychain(seed, namespaces) return keychain
def _validate(msg) -> int: if storage.is_initialized(): raise wire.UnexpectedMessage("Already initialized") if not msg.mnemonics: raise wire.ProcessError("No mnemonic provided") word_count = len(msg.mnemonics[0].split(" ")) for m in msg.mnemonics[1:]: if word_count != len(m.split(" ")): raise wire.ProcessError( "All shares are required to have the same number of words") return word_count
async def backup_device(ctx, msg): if not storage.is_initialized(): raise wire.NotInitialized("Device is not initialized") if not storage.device.needs_backup(): raise wire.ProcessError("Seed already backed up") mnemonic_secret, mnemonic_type = mnemonic.get() storage.device.set_unfinished_backup(True) storage.device.set_backed_up() await backup_seed(ctx, mnemonic_type, mnemonic_secret) storage.device.set_unfinished_backup(False) await layout.show_backup_success(ctx) return Success(message="Seed successfully backed up")
async def change_pin(ctx: wire.Context, msg: ChangePin) -> Success: if not is_initialized(): raise wire.NotInitialized("Device is not initialized") # confirm that user wants to change the pin await require_confirm_change_pin(ctx, msg) # get old pin curpin, salt = await request_pin_and_sd_salt(ctx, "Enter old PIN") # if changing pin, pre-check the entered pin before getting new pin if curpin and not msg.remove: if not config.check_pin(pin_to_int(curpin), salt): await show_pin_invalid(ctx) raise wire.PinInvalid("PIN invalid") # get new pin if not msg.remove: newpin = await request_pin_confirm(ctx) else: newpin = "" # write into storage if not config.change_pin(pin_to_int(curpin), pin_to_int(newpin), salt, salt): if newpin: await show_pin_matches_wipe_code(ctx) else: await show_pin_invalid(ctx) raise wire.PinInvalid("PIN invalid") if newpin: if curpin: msg_screen = "changed your PIN." msg_wire = "PIN changed" else: msg_screen = "enabled PIN protection." msg_wire = "PIN enabled" else: msg_screen = "disabled PIN protection." msg_wire = "PIN removed" await show_success(ctx, ("You have successfully", msg_screen)) return Success(message=msg_wire)
async def get_keychain(ctx: wire.Context) -> Keychain: if not storage.is_initialized(): raise wire.NotInitialized("Device is not initialized") passphrase = await get_passphrase(ctx) if mnemonic.is_bip39(): # derive the root node from mnemonic and passphrase via Cardano Icarus algorithm root = bip32.from_mnemonic_cardano(mnemonic.get_secret().decode(), passphrase) else: # derive the root node via SLIP-0023 seed = mnemonic.get_seed(passphrase) root = bip32.from_seed(seed, "ed25519 cardano seed") # derive the namespaced root node for i in SEED_NAMESPACE: root.derive_cardano(i) keychain = Keychain(root) return keychain
async def change_wipe_code(ctx: wire.Context, msg: ChangeWipeCode) -> Success: if not is_initialized(): raise wire.NotInitialized("Device is not initialized") # Confirm that user wants to set or remove the wipe code. has_wipe_code = config.has_wipe_code() await _require_confirm_action(ctx, msg, has_wipe_code) # Get the unlocking PIN. pin, salt = await request_pin_and_sd_salt(ctx) if not msg.remove: # Pre-check the entered PIN. if config.has_pin() and not config.check_pin(pin_to_int(pin), salt): await show_pin_invalid(ctx) raise wire.PinInvalid("PIN invalid") # Get new wipe code. wipe_code = await _request_wipe_code_confirm(ctx, pin) else: wipe_code = "" # Write into storage. if not config.change_wipe_code(pin_to_int(pin), salt, pin_to_int(wipe_code)): await show_pin_invalid(ctx) raise wire.PinInvalid("PIN invalid") if wipe_code: if has_wipe_code: msg_screen = "changed the wipe code." msg_wire = "Wipe code changed" else: msg_screen = "set the wipe code." msg_wire = "Wipe code set" else: msg_screen = "disabled the wipe code." msg_wire = "Wipe code removed" await show_success(ctx, ("You have successfully", msg_screen)) return Success(message=msg_wire)
def _validate_reset_device(msg: ResetDevice) -> None: msg.backup_type = msg.backup_type or _DEFAULT_BACKUP_TYPE if msg.backup_type not in ( BackupType.Bip39, BackupType.Slip39_Basic, BackupType.Slip39_Advanced, ): raise wire.ProcessError("Backup type not implemented.") if backup_types.is_slip39_backup_type(msg.backup_type): if msg.strength not in (128, 256): raise wire.ProcessError( "Invalid strength (has to be 128 or 256 bits)") else: # BIP-39 if msg.strength not in (128, 192, 256): raise wire.ProcessError( "Invalid strength (has to be 128, 192 or 256 bits)") if msg.display_random and (msg.skip_backup or msg.no_backup): raise wire.ProcessError( "Can't show internal entropy when backup is skipped") if storage.is_initialized(): raise wire.UnexpectedMessage("Already initialized")
async def get_keychain(ctx: wire.Context) -> Keychain: if not storage.is_initialized(): raise wire.NotInitialized("Device is not initialized") if mnemonic.is_bip39(): # derive the root node from mnemonic and passphrase passphrase = await _get_passphrase(ctx) root = bip32.from_mnemonic_cardano(mnemonic.get_secret().decode(), passphrase) else: seed = storage.cache.get_seed() if seed is None: passphrase = await _get_passphrase(ctx) seed = mnemonic.get_seed(passphrase) storage.cache.set_seed(seed) root = bip32.from_seed(seed, "ed25519 cardano seed") # derive the namespaced root node for i in SEED_NAMESPACE: root.derive_cardano(i) keychain = Keychain(SEED_NAMESPACE, root) return keychain
import trezorio as io from trezorui import Display import storage import storage.resident_credentials from trezor import config d = Display() d.clear() d.backlight(255) config.init(False) salt = None config.unlock(1, salt) storage.init_unlocked() storage.cache.start_session() print("is_initialized: ", storage.is_initialized()) print("version: ", storage.device.is_version_stored()) print("version: ", storage.device.get_version()) print("needs backup: ", storage.device.needs_backup()) storage.device.set_backed_up() print("needs backup: ", storage.device.needs_backup()) flags = storage.device.get_flags() print("flags", flags) storage.device.set_flags(0x200) print("flags", storage.device.get_flags()) secret = "0" * 32 backup_type = 0 storage.device.store_mnemonic_secret( secret, backup_type,
def __init__(self) -> None: super().__init__() if not storage.is_initialized(): self.label = "Go to trezor.io/start"
def _get_seed_without_passphrase() -> bytes: if not storage.is_initialized(): raise Exception("Device is not initialized") return mnemonic.get_seed(progress_bar=False)
async def _get_seed(ctx: wire.Context) -> bytes: if not storage.is_initialized(): raise wire.NotInitialized("Device is not initialized") passphrase = await get_passphrase(ctx) return mnemonic.get_seed(passphrase)
def get_features() -> Features: f = Features() f.vendor = "trezor.io" f.language = "en-US" f.major_version = utils.VERSION_MAJOR f.minor_version = utils.VERSION_MINOR f.patch_version = utils.VERSION_PATCH f.revision = utils.GITREV.encode() f.model = utils.MODEL f.device_id = storage.device.get_device_id() f.label = storage.device.get_label() f.pin_protection = config.has_pin() f.pin_cached = config.is_unlocked() f.passphrase_protection = storage.device.is_passphrase_enabled() if utils.BITCOIN_ONLY: f.capabilities = [ Capability.Bitcoin, Capability.Crypto, Capability.Shamir, Capability.ShamirGroups, Capability.PassphraseEntry, ] else: f.capabilities = [ Capability.Bitcoin, Capability.Bitcoin_like, Capability.Binance, Capability.Cardano, Capability.Crypto, Capability.EOS, Capability.Ethereum, Capability.Lisk, Capability.Monero, Capability.NEM, Capability.Ripple, Capability.Stellar, Capability.Tezos, Capability.U2F, Capability.Shamir, Capability.ShamirGroups, Capability.PassphraseEntry, ] f.sd_card_present = sdcard.is_present() # private fields: if config.is_unlocked(): # While this is technically not private, we can't reliably find the value while # locked. Instead of sending always False, we choose to not send it. f.initialized = storage.is_initialized() f.needs_backup = storage.device.needs_backup() f.unfinished_backup = storage.device.unfinished_backup() f.no_backup = storage.device.no_backup() f.flags = storage.device.get_flags() f.recovery_mode = storage.recovery.is_in_progress() f.backup_type = mnemonic.get_type() f.sd_protection = storage.sd_salt.is_enabled() f.wipe_code_protection = config.has_wipe_code() f.passphrase_always_on_device = storage.device.get_passphrase_always_on_device( ) return f