def test_upgrade_reset(gen, from_tag, to_tag): def asserts(tag, client): check_version(tag, emu.client.version) assert not client.features.pin_protection assert not client.features.passphrase_protection assert client.features.initialized assert client.features.label == LABEL assert client.features.language == LANGUAGE assert not client.features.needs_backup assert not client.features.unfinished_backup assert not client.features.no_backup with EmulatorWrapper(gen, from_tag) as emu: device.reset( emu.client, display_random=False, strength=STRENGTH, passphrase_protection=False, pin_protection=False, label=LABEL, language=LANGUAGE, ) device_id = emu.client.features.device_id asserts(from_tag, emu.client) storage = emu.storage() with EmulatorWrapper(gen, to_tag, storage=storage) as emu: assert device_id == emu.client.features.device_id asserts(to_tag, emu.client)
def reset(client, strength=128, skip_backup=False): mnemonic = None word_count = strength // 32 * 3 def input_flow(): nonlocal mnemonic # 1. Confirm Reset # 2. Backup your seed # 3. Confirm warning yield from click_through(client.debug, screens=3, code=B.ResetDevice) # mnemonic phrases btn_code = yield assert btn_code == B.ResetDevice mnemonic = read_and_confirm_mnemonic(client.debug, words=word_count) # confirm recovery seed check btn_code = yield assert btn_code == B.Success client.debug.press_yes() # confirm success btn_code = yield assert btn_code == B.Success client.debug.press_yes() with client: client.set_expected_responses([ messages.ButtonRequest(code=B.ResetDevice), messages.EntropyRequest(), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.Success), messages.ButtonRequest(code=B.Success), messages.Success(), messages.Features(), ]) client.set_input_flow(input_flow) # No PIN, no passphrase, don't display random device.reset( client, display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, label="test", language="english", backup_type=BackupType.Bip39, ) # Check if device is properly initialized assert client.features.initialized is True assert client.features.needs_backup is False assert client.features.pin_protection is False assert client.features.passphrase_protection is False return mnemonic
def test_interrupt_backup_fails(client): device.reset( client, display_random=False, strength=128, passphrase_protection=False, pin_protection=False, label="test", language="english", skip_backup=True, ) assert client.features.initialized is True assert client.features.needs_backup is True assert client.features.unfinished_backup is False assert client.features.no_backup is False # start backup client.call_raw(messages.BackupDevice()) # interupt backup by sending initialize client.init_device() # check that device state is as expected assert client.features.initialized is True assert client.features.needs_backup is False assert client.features.unfinished_backup is True assert client.features.no_backup is False # Second attempt at backup should fail with pytest.raises(TrezorFailure, match=r".*Seed already backed up"): device.backup(client)
def test_reset_device(client: Client): assert client.features.pin_protection is False assert client.features.passphrase_protection is False os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), client: client.set_expected_responses( [messages.ButtonRequest] + [messages.EntropyRequest] + [messages.ButtonRequest] * 24 + [messages.Success, messages.Features] ) device.reset(client, False, 128, True, False, "label", "en-US") with pytest.raises(TrezorFailure): # This must fail, because device is already initialized # Using direct call because `device.reset` has its own check client.call( messages.ResetDevice( display_random=False, strength=128, passphrase_protection=True, pin_protection=False, label="label", language="en-US", ) )
def test_upgrade_reset_no_backup(gen, from_tag, to_tag): def asserts(tag, client): assert not client.features.pin_protection assert not client.features.passphrase_protection assert client.features.initialized assert client.features.label == LABEL assert client.features.language == LANGUAGE assert not client.features.needs_backup assert not client.features.unfinished_backup assert client.features.no_backup with EmulatorWrapper(gen, from_tag) as emu: device.reset( emu.client, display_random=False, strength=STRENGTH, passphrase_protection=False, pin_protection=False, label=LABEL, language=LANGUAGE, no_backup=True, ) device_id = emu.client.features.device_id asserts(from_tag, emu.client) address = btc.get_address(emu.client, "Bitcoin", PATH) storage = emu.storage() with EmulatorWrapper(gen, to_tag, storage=storage) as emu: assert device_id == emu.client.features.device_id asserts(to_tag, emu.client) assert btc.get_address(emu.client, "Bitcoin", PATH) == address
def test_skip_backup_msg(client: Client, backup_type, backup_flow): os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), client: device.reset( client, skip_backup=True, passphrase_protection=False, pin_protection=False, backup_type=backup_type, ) assert client.features.initialized is True assert client.features.needs_backup is True assert client.features.unfinished_backup is False assert client.features.no_backup is False assert client.features.backup_type is backup_type secret = backup_flow(client) client.init_device() assert client.features.initialized is True assert client.features.needs_backup is False assert client.features.unfinished_backup is False assert client.features.backup_type is backup_type assert secret is not None state = client.debug.state() assert state.mnemonic_type is backup_type assert state.mnemonic_secret == secret
def test_skip_backup_msg(client, backup_type, backup_flow): device.reset( client, skip_backup=True, passphrase_protection=False, pin_protection=False, backup_type=backup_type, ) assert client.features.initialized is True assert client.features.needs_backup is True assert client.features.unfinished_backup is False assert client.features.no_backup is False assert client.features.backup_type is backup_type secret = backup_flow(client) client.init_device() assert client.features.initialized is True assert client.features.needs_backup is False assert client.features.unfinished_backup is False assert client.features.backup_type is backup_type assert secret is not None state = client.debug.state() assert state.mnemonic_type is backup_type assert state.mnemonic_secret == secret
def reset(client: Client, strength=128, skip_backup=False): mnemonic = None def input_flow(): nonlocal mnemonic # 1. Confirm Reset # 2. Backup your seed # 3. Confirm warning yield from click_through(client.debug, screens=3, code=B.ResetDevice) # mnemonic phrases mnemonic = yield from read_and_confirm_mnemonic(client.debug) # confirm recovery seed check br = yield assert br.code == B.Success client.debug.press_yes() # confirm success br = yield assert br.code == B.Success client.debug.press_yes() os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), client: client.set_expected_responses([ messages.ButtonRequest(code=B.ResetDevice), messages.EntropyRequest(), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.Success), messages.ButtonRequest(code=B.Success), messages.Success, messages.Features, ]) client.set_input_flow(input_flow) # No PIN, no passphrase, don't display random device.reset( client, display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, label="test", language="en-US", backup_type=BackupType.Bip39, ) # Check if device is properly initialized assert client.features.initialized is True assert client.features.needs_backup is False assert client.features.pin_protection is False assert client.features.passphrase_protection is False return mnemonic
def setup_device(self, label='', passphrase=''): if self.client.features.initialized: raise DeviceAlreadyInitError( 'Device is already initialized. Use wipe first and try again') passphrase_enabled = False if self.password: passphrase_enabled = True device.reset(self.client, passphrase_protection=bool(self.password)) return {'success': True}
def test_reset_device(self): with self.client: self.client.set_expected_responses( [proto.EntropyRequest()] + [proto.ButtonRequest()] * 24 + [proto.Success(), proto.Features()]) device.reset(self.client, False, 128, True, False, "label", "english") # This must fail, because device is already initialized with pytest.raises(Exception): device.reset(self.client, False, 128, True, False, "label", "english")
def reset_device(hw_device_id: str, strength: int, passphrase_enabled: bool, pin_enabled: bool, hw_label: str) -> Tuple[str, bool]: """ Initialize device with a newly generated words. :param hw_type: app_config.HWType :param hw_device_id: id of the device selected by the user :param strength: number of bits of entropy (will have impact on number of words) :param passphrase_enbled: if True, hw will have passphrase enabled :param pin_enabled: if True, hw will have pin enabled :param hw_label: label for device (Trezor/Keepkey) :return: Tuple Ret[0]: Device id. If a device is wiped before initializing with mnemonics, a new device id is generated. It's returned to the caller. Ret[1]: False, if the user cancelled the operation. In this situation we deliberately don't raise the 'cancelled' exception, because in the case of changing of the device id (when wiping) we want to pass it back to the caller function. """ client = None try: client = connect_trezor(hw_device_id) if client: if client.features.initialized: device.wipe(client) hw_device_id = client.features.device_id device.reset(client, display_random=True, strength=strength, passphrase_protection=passphrase_enabled, pin_protection=pin_enabled, label=hw_label, language='english', u2f_counter=0, skip_backup=False) client.close() return hw_device_id, False else: raise Exception('Couldn\'t connect to Trezor device.') except CallException as e: if client: client.close() if not (len(e.args) >= 0 and str(e.args[1]) == 'Action cancelled by user'): raise else: return hw_device_id, True # cancelled by user except CancelException: if client: client.close() return hw_device_id, True # cancelled by user
def test_reset_device(self): with self.client: self.client.set_expected_responses( [proto.ButtonRequest()] + [proto.EntropyRequest()] + [proto.ButtonRequest()] * 24 + [proto.Success(), proto.Features()] ) device.reset(self.client, False, 128, True, False, "label", "english") # This must fail, because device is already initialized with pytest.raises(Exception): device.reset(self.client, False, 128, True, False, "label", "english")
def emulator(gen, tag): with EmulatorWrapper(gen, tag) as emu: # set up a passphrase-protected device device.reset( emu.client, pin_protection=False, skip_backup=True, ) resp = emu.client.call( ApplySettingsCompat(use_passphrase=True, passphrase_source=SOURCE_HOST) ) assert isinstance(resp, messages.Success) yield emu
def test_no_backup_show_entropy_fails(client): with pytest.raises( TrezorFailure, match=r".*Can't show internal entropy when backup is skipped"): device.reset( client, display_random=True, strength=128, passphrase_protection=False, pin_protection=False, label="test", language="english", no_backup=True, )
def test_skip_backup_manual(client, backup_type, backup_flow): def reset_skip_input_flow(): yield # Confirm Recovery client.debug.press_yes() yield # Skip Backup client.debug.press_no() yield # Confirm skip backup client.debug.press_no() os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), client: client.set_input_flow(reset_skip_input_flow) client.set_expected_responses( [ messages.ButtonRequest(code=B.ResetDevice), messages.EntropyRequest(), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.Success, messages.Features, ] ) device.reset( client, pin_protection=False, passphrase_protection=False, backup_type=backup_type, ) assert client.features.initialized is True assert client.features.needs_backup is True assert client.features.unfinished_backup is False assert client.features.no_backup is False assert client.features.backup_type is backup_type secret = backup_flow(client) client.init_device() assert client.features.initialized is True assert client.features.needs_backup is False assert client.features.unfinished_backup is False assert client.features.backup_type is backup_type assert secret is not None state = client.debug.state() assert state.mnemonic_type is backup_type assert state.mnemonic_secret == secret
def test_no_backup_fails(client): device.reset( client, display_random=False, strength=128, passphrase_protection=False, pin_protection=False, label="test", language="english", no_backup=True, ) assert client.features.initialized is True assert client.features.no_backup is True assert client.features.needs_backup is False # backup attempt should fail because no_backup=True with pytest.raises(TrezorFailure, match=r".*Seed already backed up"): device.backup(client)
def test_autolock_not_retained(client: Client): with client: client.use_pin_sequence([PIN4]) device.apply_settings(client, auto_lock_delay_ms=10_000) assert client.features.auto_lock_delay_ms == 10_000 device.wipe(client) assert client.features.auto_lock_delay_ms > 10_000 with client: client.use_pin_sequence([PIN4, PIN4]) device.reset(client, skip_backup=True, pin_protection=True) time.sleep(10.5) with client: # after sleeping for the pre-wipe autolock amount, Trezor must still be unlocked client.set_expected_responses([messages.Address]) get_test_address(client)
def initialize_device(hw_device_id: str, hw_device_transport_id: Any, hw_client: Any, strength: int, passphrase_enabled: bool, pin_enabled: bool, hw_label: str) -> Optional[str]: client = None try: if not hw_client: client = open_session(hw_device_id, hw_device_transport_id) else: client = hw_client if client: if client.features.initialized: device.wipe(client) hw_device_id = client.features.device_id device.reset(client, display_random=True, strength=strength, passphrase_protection=passphrase_enabled, pin_protection=pin_enabled, label=hw_label, language='english', u2f_counter=0, skip_backup=False) return hw_device_id else: raise Exception('Couldn\'t connect to Trezor device.') except TrezorFailure as e: if not (len(e.args) >= 0 and str(e.args[1]) == 'Action cancelled by user'): if e.failure.message == 'Device not initialized': raise HwNotInitialized(e.failure.message) else: raise else: raise CancelException except exceptions.Cancelled: raise CancelException finally: if client and hw_client != client: client.close()
def test_reset_device(self, client): with client: client.set_expected_responses( [proto.ButtonRequest()] + [proto.EntropyRequest()] + [proto.ButtonRequest()] * 24 + [proto.Success(), proto.Features()]) device.reset(client, False, 128, True, False, "label", "en-US") with pytest.raises(TrezorFailure): # This must fail, because device is already initialized # Using direct call because `device.reset` has its own check client.call( proto.ResetDevice( display_random=False, strength=128, passphrase_protection=True, pin_protection=False, label="label", language="en-US", ))
def reset_device(client, strength): words = STRENGTH_TO_WORDS[strength] mnemonic = None def input_flow(): nonlocal mnemonic # 1. Confirm Reset # 2. Backup your seed # 3. Confirm warning yield from click_through(client.debug, screens=3, code=B.ResetDevice) # mnemonic phrases btn_code = yield assert btn_code == B.ResetDevice mnemonic = read_and_confirm_mnemonic(client.debug, words=words) # confirm recovery seed check btn_code = yield assert btn_code == B.Success client.debug.press_yes() # confirm success btn_code = yield assert btn_code == B.Success client.debug.press_yes() os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), client: client.set_expected_responses([ proto.ButtonRequest(code=B.ResetDevice), proto.EntropyRequest(), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.Success), proto.Success(), proto.Features(), ]) client.set_input_flow(input_flow) # No PIN, no passphrase, don't display random device.reset( client, display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, label="test", language="en-US", ) # generate mnemonic locally internal_entropy = client.debug.state().reset_entropy entropy = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) # Compare that device generated proper mnemonic for given entropies assert mnemonic == expected_mnemonic # Check if device is properly initialized resp = client.call_raw(proto.Initialize()) assert resp.initialized is True assert resp.needs_backup is False assert resp.pin_protection is False assert resp.passphrase_protection is False assert resp.backup_type is proto.BackupType.Bip39 # backup attempt fails because backup was done in reset with pytest.raises(TrezorFailure, match="ProcessError: Seed already backed up"): device.backup(client)
def test_already_initialized(self, client): with pytest.raises(Exception): device.reset(client, False, 128, True, True, "label", "en-US")
def test_reset_device_pin(self, client): mnemonic = None strength = 256 # 24 words def input_flow(): nonlocal mnemonic # Confirm Reset btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # Enter new PIN yield client.debug.input("654") # Confirm PIN yield client.debug.input("654") # Confirm entropy btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # Backup your seed btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # Confirm warning btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # mnemonic phrases btn_code = yield assert btn_code == B.ResetDevice mnemonic = read_and_confirm_mnemonic(client.debug, words=24) # confirm recovery seed check btn_code = yield assert btn_code == B.Success client.debug.press_yes() # confirm success btn_code = yield assert btn_code == B.Success client.debug.press_yes() os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), client: client.set_expected_responses([ proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.PinEntry), proto.ButtonRequest(code=B.PinEntry), proto.ButtonRequest(code=B.ResetDevice), proto.EntropyRequest(), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.Success), proto.Success(), proto.Features(), ]) client.set_input_flow(input_flow) # PIN, passphrase, display random device.reset( client, display_random=True, strength=strength, passphrase_protection=True, pin_protection=True, label="test", language="en-US", ) # generate mnemonic locally internal_entropy = client.debug.state().reset_entropy entropy = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) # Compare that device generated proper mnemonic for given entropies assert mnemonic == expected_mnemonic # Check if device is properly initialized resp = client.call_raw(proto.Initialize()) assert resp.initialized is True assert resp.needs_backup is False assert resp.pin_protection is True assert resp.passphrase_protection is True
def reset(client: Client, strength=128): all_mnemonics = [] def input_flow(): # 1. Confirm Reset # 2. Backup your seed # 3. Confirm warning # 4. shares info # 5. Set & Confirm number of shares # 6. threshold info # 7. Set & confirm threshold value # 8. Confirm show seeds yield from click_through(client.debug, screens=8, code=B.ResetDevice) # show & confirm shares for _ in range(5): # mnemonic phrases mnemonic = yield from read_and_confirm_mnemonic(client.debug) all_mnemonics.append(mnemonic) # Confirm continue to next share br = yield assert br.code == B.Success client.debug.press_yes() # safety warning br = yield assert br.code == B.Success client.debug.press_yes() with client: client.set_expected_responses( [ messages.ButtonRequest(code=B.ResetDevice), messages.EntropyRequest(), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), ] + [ # individual mnemonic messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.Success), ] * 5 # number of shares + [ messages.ButtonRequest(code=B.Success), messages.Success, messages.Features, ] ) client.set_input_flow(input_flow) # No PIN, no passphrase, don't display random device.reset( client, display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, label="test", language="en-US", backup_type=BackupType.Slip39_Basic, ) # Check if device is properly initialized assert client.features.initialized is True assert client.features.needs_backup is False assert client.features.pin_protection is False assert client.features.passphrase_protection is False return all_mnemonics
def test_reset_device(self): words = [] strength = 128 def input_flow(): # Confirm Reset btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # Backup your seed btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # mnemonic phrases btn_code = yield assert btn_code == B.ResetDevice # 12 words, 3 pages for i in range(3): time.sleep(1) words.extend(self.client.debug.state().reset_word.split()) if i < 2: self.client.debug.swipe_down() else: # last page is confirmation self.client.debug.press_yes() # check backup words for _ in range(2): time.sleep(1) index = self.client.debug.state().reset_word_pos self.client.debug.input(words[index]) # safety warning btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), self.client: self.client.set_expected_responses([ proto.ButtonRequest(code=B.ResetDevice), proto.EntropyRequest(), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.Success(), proto.Features(), ]) self.client.set_input_flow(input_flow) # No PIN, no passphrase, don't display random device.reset( self.client, display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, label="test", language="english", ) # generate mnemonic locally internal_entropy = self.client.debug.state().reset_entropy entropy = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) # Compare that device generated proper mnemonic for given entropies assert " ".join(words) == expected_mnemonic # Check if device is properly initialized resp = self.client.call_raw(proto.Initialize()) assert resp.initialized is True assert resp.needs_backup is False assert resp.pin_protection is False assert resp.passphrase_protection is False
def test_reset_device_slip39_basic(self, client): strength = 128 member_threshold = 3 all_mnemonics = [] def input_flow(): # 1. Confirm Reset # 2. Backup your seed # 3. Confirm warning # 4. shares info # 5. Set & Confirm number of shares # 6. threshold info # 7. Set & confirm threshold value # 8. Confirm show seeds yield from click_through(client.debug, screens=8, code=B.ResetDevice) # show & confirm shares for h in range(5): # mnemonic phrases btn_code = yield assert btn_code == B.ResetDevice mnemonic = read_and_confirm_mnemonic(client.debug, words=20) all_mnemonics.append(mnemonic) # Confirm continue to next share btn_code = yield assert btn_code == B.Success client.debug.press_yes() # safety warning btn_code = yield assert btn_code == B.Success client.debug.press_yes() os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), client: client.set_expected_responses([ proto.ButtonRequest(code=B.ResetDevice), proto.EntropyRequest(), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.Success), proto.Success(), proto.Features(), ]) client.set_input_flow(input_flow) # No PIN, no passphrase, don't display random device.reset( client, display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, label="test", language="en-US", backup_type=BackupType.Slip39_Basic, ) # generate secret locally internal_entropy = client.debug.state().reset_entropy secret = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) # validate that all combinations will result in the correct master secret validate_mnemonics(all_mnemonics, member_threshold, secret) # Check if device is properly initialized assert client.features.initialized is True assert client.features.needs_backup is False assert client.features.pin_protection is False assert client.features.passphrase_protection is False assert client.features.backup_type is BackupType.Slip39_Basic # backup attempt fails because backup was done in reset with pytest.raises(TrezorFailure, match="ProcessError: Seed already backed up"): device.backup(client)
def reset(client, strength=128): all_mnemonics = [] # per SLIP-39: strength in bits, rounded up to nearest multiple of 10, plus 70 bits # of metadata, split into 10-bit words word_count = ((strength + 9) // 10) + 7 def input_flow(): # 1. Confirm Reset # 2. Backup your seed # 3. Confirm warning # 4. shares info # 5. Set & Confirm number of shares # 6. threshold info # 7. Set & confirm threshold value # 8. Confirm show seeds yield from click_through(client.debug, screens=8, code=B.ResetDevice) # show & confirm shares for h in range(5): # mnemonic phrases btn_code = yield assert btn_code == B.ResetDevice mnemonic = read_and_confirm_mnemonic(client.debug, words=word_count) all_mnemonics.append(mnemonic) # Confirm continue to next share btn_code = yield assert btn_code == B.Success client.debug.press_yes() # safety warning btn_code = yield assert btn_code == B.Success client.debug.press_yes() with client: client.set_expected_responses([ messages.ButtonRequest(code=B.ResetDevice), messages.EntropyRequest(), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.Success), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.Success), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.Success), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.Success), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.Success), messages.ButtonRequest(code=B.Success), messages.Success(), messages.Features(), ]) client.set_input_flow(input_flow) # No PIN, no passphrase, don't display random device.reset( client, display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, label="test", language="english", backup_type=BackupType.Slip39_Basic, ) # Check if device is properly initialized assert client.features.initialized is True assert client.features.needs_backup is False assert client.features.pin_protection is False assert client.features.passphrase_protection is False return all_mnemonics
def test_reset_device(self): words = [] strength = 128 def input_flow(): # Confirm Reset btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # Backup your seed btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # mnemonic phrases btn_code = yield assert btn_code == B.ResetDevice # 12 words, 3 pages for i in range(3): time.sleep(1) words.extend(self.client.debug.state().reset_word.split()) if i < 2: self.client.debug.swipe_down() else: # last page is confirmation self.client.debug.press_yes() # check backup words for _ in range(2): time.sleep(1) index = self.client.debug.state().reset_word_pos self.client.debug.input(words[index]) # safety warning btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), self.client: self.client.set_expected_responses( [ proto.ButtonRequest(code=B.ResetDevice), proto.EntropyRequest(), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.Success(), proto.Features(), ] ) self.client.set_input_flow(input_flow) # No PIN, no passphrase, don't display random device.reset( self.client, display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, label="test", language="english", ) # generate mnemonic locally internal_entropy = self.client.debug.state().reset_entropy entropy = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) expected_mnemonic = Mnemonic("english").to_mnemonic(entropy) # Compare that device generated proper mnemonic for given entropies assert " ".join(words) == expected_mnemonic # Check if device is properly initialized resp = self.client.call_raw(proto.Initialize()) assert resp.initialized is True assert resp.needs_backup is False assert resp.pin_protection is False assert resp.passphrase_protection is False
def reset(client, strength=128): all_mnemonics = [] def input_flow(): # 1. Confirm Reset # 2. Backup your seed # 3. Confirm warning # 4. shares info # 5. Set & Confirm number of groups # 6. threshold info # 7. Set & confirm group threshold value # 8-17: for each of 5 groups: # 1. Set & Confirm number of shares # 2. Set & confirm share threshold value # 18. Confirm show seeds yield from click_through(client.debug, screens=18, code=B.ResetDevice) # show & confirm shares for all groups for _g in range(5): for _h in range(5): # mnemonic phrases mnemonic = yield from read_and_confirm_mnemonic(client.debug) all_mnemonics.append(mnemonic) # Confirm continue to next share br = yield assert br.code == B.Success client.debug.press_yes() # safety warning br = yield assert br.code == B.Success client.debug.press_yes() os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), client: client.set_expected_responses( [ messages.ButtonRequest(code=B.ResetDevice), messages.EntropyRequest(), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), # group #1 counts messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), # group #2 counts messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), # group #3 counts messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), # group #4 counts messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), # group #5 counts messages.ButtonRequest(code=B.ResetDevice), ] + [ # individual mnemonic messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.Success), ] * (5 * 5) # groups * shares + [ messages.ButtonRequest(code=B.Success), messages.Success, messages.Features, ] ) client.set_input_flow(input_flow) # No PIN, no passphrase, don't display random device.reset( client, display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, label="test", language="en-US", backup_type=BackupType.Slip39_Advanced, ) # Check if device is properly initialized assert client.features.initialized is True assert client.features.needs_backup is False assert client.features.pin_protection is False assert client.features.passphrase_protection is False return all_mnemonics
def test_already_initialized(self): self.setup_mnemonic_nopin_nopassphrase() with pytest.raises(Exception): device.reset(self.client, False, 128, True, True, "label", "english")
def test_reset_device_slip39_advanced(self, client): strength = 128 word_count = 20 member_threshold = 3 all_mnemonics = [] def input_flow(): # 1. Confirm Reset # 2. Backup your seed # 3. Confirm warning # 4. shares info # 5. Set & Confirm number of groups # 6. threshold info # 7. Set & confirm group threshold value # 8-17: for each of 5 groups: # 1. Set & Confirm number of shares # 2. Set & confirm share threshold value # 18. Confirm show seeds yield from click_through(client.debug, screens=18, code=B.ResetDevice) # show & confirm shares for all groups for g in range(5): for h in range(5): # mnemonic phrases btn_code = yield assert btn_code == B.ResetDevice mnemonic = read_and_confirm_mnemonic(client.debug, words=word_count) all_mnemonics.append(mnemonic) # Confirm continue to next share btn_code = yield assert btn_code == B.Success client.debug.press_yes() # safety warning btn_code = yield assert btn_code == B.Success client.debug.press_yes() os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), client: client.set_expected_responses([ proto.ButtonRequest(code=B.ResetDevice), proto.EntropyRequest(), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), # group #1 counts proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), # group #2 counts proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), # group #3 counts proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), # group #4 counts proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), # group #5 counts proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), # show seeds proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Success), # show seeds ends here proto.ButtonRequest(code=B.Success), proto.Success(), proto.Features(), ]) client.set_input_flow(input_flow) # No PIN, no passphrase, don't display random device.reset( client, display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, label="test", language="english", backup_type=BackupType.Slip39_Advanced, ) # generate secret locally internal_entropy = client.debug.state().reset_entropy secret = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) # validate that all combinations will result in the correct master secret validate_mnemonics(all_mnemonics, member_threshold, secret) # Check if device is properly initialized assert client.features.initialized is True assert client.features.needs_backup is False assert client.features.pin_protection is False assert client.features.passphrase_protection is False assert client.features.backup_type is BackupType.Slip39_Advanced
def test_reset_device_shamir(self): strength = 128 member_threshold = 3 def input_flow(): # Confirm Reset btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # Backup your seed btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # Confirm warning btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # shares info btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # Set & Confirm number of shares btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # threshold info btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # Set & confirm threshold value btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # Confirm show seeds btn_code = yield assert btn_code == B.ResetDevice self.client.debug.press_yes() # show & confirm shares all_mnemonics = [] for h in range(5): words = [] btn_code = yield assert btn_code == B.Other # mnemonic phrases # 20 word over 6 pages for strength 128, 33 words over 9 pages for strength 256 for i in range(6): words.extend(self.client.debug.read_reset_word().split()) if i < 5: self.client.debug.swipe_down() else: # last page is confirmation self.client.debug.press_yes() # check share for _ in range(3): index = self.client.debug.read_reset_word_pos() self.client.debug.input(words[index]) all_mnemonics.extend([" ".join(words)]) # Confirm continue to next share btn_code = yield assert btn_code == B.Success self.client.debug.press_yes() # generate secret locally internal_entropy = self.client.debug.state().reset_entropy secret = generate_entropy(strength, internal_entropy, EXTERNAL_ENTROPY) # validate that all combinations will result in the correct master secret validate_mnemonics(all_mnemonics, member_threshold, secret) # safety warning btn_code = yield assert btn_code == B.Success self.client.debug.press_yes() os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY) with mock.patch("os.urandom", os_urandom), self.client: self.client.set_expected_responses([ proto.ButtonRequest(code=B.ResetDevice), proto.EntropyRequest(), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.ResetDevice), proto.ButtonRequest(code=B.Other), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.Other), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.Other), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.Other), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.Other), proto.ButtonRequest(code=B.Success), proto.ButtonRequest(code=B.Success), proto.Success(), proto.Features(), ]) self.client.set_input_flow(input_flow) # No PIN, no passphrase, don't display random device.reset( self.client, display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, label="test", language="english", backup_type=ResetDeviceBackupType.Slip39_Single_Group, ) # Check if device is properly initialized resp = self.client.call_raw(proto.Initialize()) assert resp.initialized is True assert resp.needs_backup is False assert resp.pin_protection is False assert resp.passphrase_protection is False
def reset(client, strength=128): all_mnemonics = [] def input_flow(): # Confirm Reset btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # Backup your seed btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # Confirm warning btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # shares info btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # Set & Confirm number of shares btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # threshold info btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # Set & confirm threshold value btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # Confirm show seeds btn_code = yield assert btn_code == B.ResetDevice client.debug.press_yes() # show & confirm shares for h in range(5): words = [] btn_code = yield assert btn_code == B.Other # mnemonic phrases # 20 word over 6 pages for strength 128, 33 words over 9 pages for strength 256 for i in range(6): words.extend(client.debug.read_reset_word().split()) if i < 5: client.debug.swipe_down() else: # last page is confirmation client.debug.press_yes() # check share for _ in range(3): index = client.debug.read_reset_word_pos() client.debug.input(words[index]) all_mnemonics.extend([" ".join(words)]) # Confirm continue to next share btn_code = yield assert btn_code == B.Success client.debug.press_yes() # safety warning btn_code = yield assert btn_code == B.Success client.debug.press_yes() with client: client.set_expected_responses( [ messages.ButtonRequest(code=B.ResetDevice), messages.EntropyRequest(), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.Other), messages.ButtonRequest(code=B.Success), messages.ButtonRequest(code=B.Other), messages.ButtonRequest(code=B.Success), messages.ButtonRequest(code=B.Other), messages.ButtonRequest(code=B.Success), messages.ButtonRequest(code=B.Other), messages.ButtonRequest(code=B.Success), messages.ButtonRequest(code=B.Other), messages.ButtonRequest(code=B.Success), messages.ButtonRequest(code=B.Success), messages.Success(), messages.Features(), ] ) client.set_input_flow(input_flow) # No PIN, no passphrase, don't display random device.reset( client, display_random=False, strength=strength, passphrase_protection=False, pin_protection=False, label="test", language="english", backup_type=ResetDeviceBackupType.Slip39_Single_Group, ) client.set_input_flow(None) # Check if device is properly initialized assert client.features.initialized is True assert client.features.needs_backup is False assert client.features.pin_protection is False assert client.features.passphrase_protection is False return all_mnemonics