def init_unlocked() -> None: # Check for storage version upgrade. version = device.get_version() if version == common.STORAGE_VERSION_01: _migrate_from_version_01() # In FWs <= 2.3.1 'version' denoted whether the device is initialized or not. # In 2.3.2 we have introduced a new field 'initialized' for that. if device.is_version_stored() and not device.is_initialized(): common.set_bool(common.APP_DEVICE, device.INITIALIZED, True, public=True)
async def _get_keychain_bip39(ctx: wire.Context) -> Keychain: if not device.is_initialized(): raise wire.NotInitialized("Device is not initialized") # ask for passphrase, loading from cache if necessary passphrase = await _get_passphrase(ctx) # derive the root node from mnemonic and passphrase via Cardano Icarus algorithm secret_bytes = mnemonic.get_secret() assert secret_bytes is not None root = bip32.from_mnemonic_cardano(secret_bytes.decode(), passphrase.decode()) return Keychain(root)
async def get_keychain(ctx: wire.Context) -> Keychain: if not device.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") keychain = Keychain(root) return keychain
async def get_keychain(ctx: wire.Context) -> Keychain: if not device.is_initialized(): raise wire.NotInitialized("Device is not initialized") if mnemonic.is_bip39(): passphrase = await get_passphrase(ctx) # derive the root node from mnemonic and passphrase via Cardano Icarus algorithm secret_bytes = mnemonic.get_secret() assert secret_bytes is not None root = bip32.from_mnemonic_cardano(secret_bytes.decode(), passphrase) else: # derive the root node via SLIP-0023 https://github.com/satoshilabs/slips/blob/master/slip-0022.md seed = await get_seed(ctx) root = bip32.from_seed(seed, "ed25519 cardano seed") keychain = Keychain(root) return keychain
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 error_pin_invalid(ctx) # 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 error_pin_matches_wipe_code(ctx) else: await error_pin_invalid(ctx) if newpin: if curpin: msg_screen = "You have successfully changed your PIN." msg_wire = "PIN changed" else: msg_screen = "You have successfully enabled PIN protection." msg_wire = "PIN enabled" else: msg_screen = "You have successfully disabled PIN protection." msg_wire = "PIN removed" await require(show_success(ctx, "success_pin", msg_screen)) return Success(message=msg_wire)
async def _get_keychain_bip39( ctx: wire.Context, derivation_type: CardanoDerivationType) -> Keychain: if not device.is_initialized(): raise wire.NotInitialized("Device is not initialized") if derivation_type == CardanoDerivationType.LEDGER: seed = await get_seed(ctx) return Keychain(cardano.from_seed_ledger(seed)) if not cache.get(cache.APP_COMMON_DERIVE_CARDANO): raise wire.ProcessError( "Cardano derivation is not enabled for this session") if derivation_type == CardanoDerivationType.ICARUS: cache_entry = cache.APP_CARDANO_ICARUS_SECRET else: cache_entry = cache.APP_CARDANO_ICARUS_TREZOR_SECRET secret = await _get_secret(ctx, cache_entry) root = cardano.from_secret(secret) return Keychain(root)
async def derive_and_store_roots(ctx: wire.Context) -> None: if not device.is_initialized(): raise wire.NotInitialized("Device is not initialized") need_seed = not cache.is_set(cache.APP_COMMON_SEED) need_cardano_secret = cache.get( cache.APP_COMMON_DERIVE_CARDANO ) and not cache.is_set(cache.APP_CARDANO_ICARUS_SECRET) if not need_seed and not need_cardano_secret: return passphrase = await get_passphrase(ctx) if need_seed: common_seed = mnemonic.get_seed(passphrase) cache.set(cache.APP_COMMON_SEED, common_seed) if need_cardano_secret: from apps.cardano.seed import derive_and_store_secrets derive_and_store_secrets(passphrase)
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 error_pin_invalid(ctx) # 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 error_pin_invalid(ctx) if wipe_code: if has_wipe_code: msg_screen = "You have successfully changed the wipe code." msg_wire = "Wipe code changed" else: msg_screen = "You have successfully set the wipe code." msg_wire = "Wipe code set" else: msg_screen = "You have successfully disabled the wipe code." msg_wire = "Wipe code removed" await require(show_success(ctx, "success_wipe_code", msg_screen)) return Success(message=msg_wire)
def derive_and_store_secrets(passphrase: str) -> None: assert device.is_initialized() assert cache.get(cache.APP_COMMON_DERIVE_CARDANO) if not mnemonic.is_bip39(): # nothing to do for SLIP-39, where we can derive the root from the main seed return icarus_secret = mnemonic.derive_cardano_icarus(passphrase, trezor_derivation=False) words = mnemonic.get_secret() assert words is not None, "Mnemonic is not set" # count ASCII spaces, add 1 to get number of words words_count = sum(c == 0x20 for c in words) + 1 if words_count == 24: icarus_trezor_secret = mnemonic.derive_cardano_icarus( passphrase, trezor_derivation=True) else: icarus_trezor_secret = icarus_secret cache.set(cache.APP_CARDANO_ICARUS_SECRET, icarus_secret) cache.set(cache.APP_CARDANO_ICARUS_TREZOR_SECRET, icarus_trezor_secret)
def _get_seed_without_passphrase() -> bytes: if not device.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 device.is_initialized(): raise wire.NotInitialized("Device is not initialized") passphrase = await get_passphrase(ctx) return mnemonic.get_seed(passphrase)