def test_apply_settings(self): self.setup_mnemonic_pin_passphrase() assert self.client.features.label == "test" with self.client: self.client.set_expected_responses([ proto.PinMatrixRequest(), proto.ButtonRequest(), proto.Success(), proto.Features(), ]) if self.client.features.major_version >= 2: self.client.expected_responses.pop(0) # skip PinMatrixRequest device.apply_settings(self.client, label="new label") assert self.client.features.label == "new label"
def test_set_pin_to_wipe_code(client): # Set wipe code. with client: client.set_expected_responses( [messages.ButtonRequest()] * 4 + [messages.Success(), messages.Features()]) client.use_pin_sequence([WIPE_CODE4, WIPE_CODE4]) device.change_wipe_code(client) # Try to set the PIN to the current wipe code value. with client, pytest.raises(TrezorFailure): client.set_expected_responses( [messages.ButtonRequest()] * 4 + [messages.Failure(code=messages.FailureType.PinInvalid)]) client.use_pin_sequence([WIPE_CODE4, WIPE_CODE4]) device.change_pin(client)
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_set_pin(client): assert client.features.pin_protection is False # Check that there's no PIN protection _check_no_pin(client) # Let's set new PIN with client: client.use_pin_sequence([PIN6, PIN6]) client.set_expected_responses( [messages.ButtonRequest()] * 4 + [messages.Success(), messages.Features()]) device.change_pin(client) client.init_device() assert client.features.pin_protection is True _check_pin(client, PIN6)
def backup_flow_slip39_basic(client): mnemonics = [] def input_flow(): # 1. Checklist # 2. Number of shares (5) # 3. Checklist # 4. Threshold (3) # 5. Checklist # 6. Confirm show seeds yield from click_through(client.debug, screens=6, code=B.ResetDevice) # Mnemonic phrases for _ in range(5): yield # Phrase screen mnemonic = read_and_confirm_mnemonic(client.debug, words=20) mnemonics.append(mnemonic) yield # Confirm continue to next client.debug.press_yes() # Confirm backup yield client.debug.press_yes() with client: client.set_input_flow(input_flow) client.set_expected_responses( [messages.ButtonRequest(code=B.ResetDevice)] * 6 # intro screens + [ messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.Success), ] * 5 # individual shares + [ messages.ButtonRequest(code=B.Success), messages.Success(), messages.Features(), ]) device.backup(client) mnemonics = mnemonics[:3] ms = shamir.combine_mnemonics(mnemonics) identifier, iteration_exponent, _, _, _ = shamir._decode_mnemonics( mnemonics) secret = shamir._encrypt(ms, b"", iteration_exponent, identifier) return secret
def test_remove_pin(client): assert client.features.pin_protection is True # Check current PIN value _check_pin(client, PIN4) # Let's remove PIN with client: client.use_pin_sequence([PIN4]) client.set_expected_responses( [messages.ButtonRequest()] * 3 + [messages.Success(), messages.Features()]) device.change_pin(client, remove=True) # Check that there's no PIN protection now client.init_device() assert client.features.pin_protection is False _check_no_pin(client)
def test_change_pin(client): assert client.features.pin_protection is True # Check current PIN value _check_pin(client, PIN4) # Let's change PIN with client: client.use_pin_sequence([PIN4, PIN6, PIN6]) client.set_expected_responses( [messages.ButtonRequest()] * 5 + [messages.Success(), messages.Features()]) device.change_pin(client) # Check that there's still PIN protection now client.init_device() assert client.features.pin_protection is True # Check that the PIN is correct _check_pin(client, PIN6)
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 test_remove_pin(client): assert client.features.pin_protection is True # Check that there's PIN protection _check_pin(client, PIN4) # Let's remove PIN with client: client.use_pin_sequence([PIN4]) client.set_expected_responses([ messages.ButtonRequest( code=messages.ButtonRequestType.ProtectCall), messages.PinMatrixRequest(), messages.Success(), messages.Features(), ]) device.change_pin(client, remove=True) # Check that there's no PIN protection now assert client.features.pin_protection is False _check_no_pin(client)
def test_apply_auto_lock_delay(self): self.setup_mnemonic_pin_passphrase() with self.client: self.client.set_expected_responses([proto.PinMatrixRequest(), proto.ButtonRequest(), proto.Success(), proto.Features()]) self.client.apply_settings(auto_lock_delay_ms=int(10e3)) # 10 secs time.sleep(0.1) # sleep less than auto-lock delay with self.client: # No PIN protection is required. self.client.set_expected_responses([proto.Success()]) self.client.ping(msg='', pin_protection=True) time.sleep(10.1) # sleep more than auto-lock delay with self.client: self.client.set_expected_responses([proto.PinMatrixRequest(), proto.Success()]) self.client.ping(msg='', pin_protection=True)
def test_recovery_device(self, client): client.set_mnemonic(MNEMONIC12) with client: client.set_expected_responses( [proto.ButtonRequest()] + [proto.WordRequest()] * 24 + [proto.Success(), proto.Features()]) device.recover(client, 12, False, False, "label", "en-US", client.mnemonic_callback) 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.RecoveryDevice( word_count=12, passphrase_protection=False, pin_protection=False, label="label", language="en-US", ))
def test_load_device(self): with self.client: self.client.set_expected_responses( [proto.ButtonRequest(), proto.Success(), proto.Features()]) self.client.load_device_by_mnemonic('this is mnemonic', '1234', True, 'label', 'english', skip_checksum=True) # This must fail, because device is already initialized with pytest.raises(Exception): self.client.load_device_by_mnemonic('this is mnemonic', '1234', True, 'label', 'english', skip_checksum=True)
def recover(client, mnemonic): debug = client.debug words = mnemonic.split(" ") def input_flow(): yield # Confirm recovery debug.press_yes() yield # Homescreen debug.press_yes() yield # Enter word count debug.input(str(len(words))) yield # Homescreen debug.press_yes() yield # Enter words for word in words: debug.input(word) yield # confirm success debug.press_yes() with client: client.set_input_flow(input_flow) client.set_expected_responses([ messages.ButtonRequest(code=B.ProtectCall), messages.ButtonRequest(code=B.RecoveryHomepage), messages.ButtonRequest(code=B.MnemonicWordCount), messages.ButtonRequest(code=B.RecoveryHomepage), messages.ButtonRequest(code=B.MnemonicInput), messages.ButtonRequest(code=B.Success), messages.Success(), messages.Features(), ]) ret = device.recover(client, pin_protection=False, label="label") # Workflow successfully ended assert ret == messages.Success(message="Device recovered") assert client.features.pin_protection is False assert client.features.passphrase_protection is False
def _set_wipe_code(client, pin, wipe_code): # Set/change wipe code. with client: if client.features.pin_protection: pins = [pin, wipe_code, wipe_code] pin_matrices = [ messages.PinMatrixRequest(type=PinType.Current), messages.PinMatrixRequest(type=PinType.WipeCodeFirst), messages.PinMatrixRequest(type=PinType.WipeCodeSecond), ] else: pins = [wipe_code, wipe_code] pin_matrices = [ messages.PinMatrixRequest(type=PinType.WipeCodeFirst), messages.PinMatrixRequest(type=PinType.WipeCodeSecond), ] client.use_pin_sequence(pins) client.set_expected_responses( [messages.ButtonRequest()] + pin_matrices + [messages.Success(), messages.Features()]) device.change_wipe_code(client)
def test_change_pin(client): assert client.features.pin_protection is True # Check that there's PIN protection _check_pin(client, PIN4) # Let's change PIN with client: client.use_pin_sequence([PIN4, PIN6, PIN6]) client.set_expected_responses([ messages.ButtonRequest( code=messages.ButtonRequestType.ProtectCall), messages.PinMatrixRequest(), messages.PinMatrixRequest(), messages.PinMatrixRequest(), messages.Success(), messages.Features(), ]) device.change_pin(client) # Check that there's still PIN protection now assert client.features.pin_protection is True # Check that the PIN is correct _check_pin(client, PIN6)
def test_wipe_code_activate(client): import time device_id = client.features.device_id # Set wipe code. with client: client.set_expected_responses( [messages.ButtonRequest()] * 5 + [messages.Success(), messages.Features()]) client.set_input_flow( _input_flow_set_wipe_code(client.debug, PIN4, WIPE_CODE4)) device.change_wipe_code(client) # Try to change the PIN. ret = client.call_raw(messages.ChangePin(remove=False)) # Confirm change PIN. assert isinstance(ret, messages.ButtonRequest) client.debug.press_yes() ret = client.call_raw(messages.ButtonAck()) # Enter the wipe code instead of the current PIN assert ret == messages.ButtonRequest(code=messages.ButtonRequestType.Other) client.debug.input(WIPE_CODE4) client._raw_write(messages.ButtonAck()) # Allow the device to display wipe code popup and restart. time.sleep(7) # Check that the device has been wiped. client.init_device() assert client.features.initialized is False assert client.features.pin_protection is False assert client.features.wipe_code_protection is False assert client.features.device_id != device_id
def backup_flow_bip39(client): mnemonic = None def input_flow(): nonlocal mnemonic # 1. Confirm Reset yield from click_through(client.debug, screens=1, code=B.ResetDevice) # mnemonic phrases btn_code = yield assert btn_code == B.ResetDevice mnemonic = read_and_confirm_mnemonic(client.debug, words=12) # 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.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.Success), messages.ButtonRequest(code=B.Success), messages.Success(), messages.Features(), ]) client.set_input_flow(input_flow) device.backup(client) return mnemonic.encode()
def test_backup_bip39(client): assert client.features.needs_backup is True mnemonic = None def input_flow(): nonlocal mnemonic yield # Confirm Backup client.debug.press_yes() yield # Mnemonic phrases mnemonic = read_and_confirm_mnemonic(client.debug, words=12) yield # Confirm success client.debug.press_yes() yield # Backup is done client.debug.press_yes() with client: client.set_input_flow(input_flow) client.set_expected_responses( [ messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.ResetDevice), messages.ButtonRequest(code=B.Success), messages.ButtonRequest(code=B.Success), messages.Success(), messages.Features(), ] ) device.backup(client) assert mnemonic == MNEMONIC12 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.no_backup is False assert client.features.backup_type is messages.BackupType.Bip39
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 test_initialize(self, client): with client: client.set_expected_responses([proto.Features()]) client.init_device()
def test_backup_slip39_advanced(client): assert client.features.needs_backup is True mnemonics = [] def input_flow(): # 1. Checklist # 2. Set and confirm group count # 3. Checklist # 4. Set and confirm group threshold # 5. Checklist # 6-15: for each of 5 groups: # 1. Set & Confirm number of shares # 2. Set & confirm share threshold value # 16. Confirm show seeds yield from click_through(client.debug, screens=16, code=B.ResetDevice) # Mnemonic phrases for _ in range(5): for _ in range(5): yield # Phrase screen mnemonic = read_and_confirm_mnemonic(client.debug, words=20) mnemonics.append(mnemonic) yield # Confirm continue to next client.debug.press_yes() # Confirm backup yield client.debug.press_yes() with client: client.set_input_flow(input_flow) client.set_expected_responses([ 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), messages.ButtonRequest(code=B.ResetDevice), # show seeds 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.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.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.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.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), # show seeds ends here messages.ButtonRequest(code=B.Success), messages.Success(), messages.Features(), ]) device.backup(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.no_backup is False assert client.features.backup_type is messages.BackupType.Slip39_Advanced expected_ms = shamir.combine_mnemonics(MNEMONIC_SLIP39_ADVANCED_20) actual_ms = shamir.combine_mnemonics(mnemonics[:3] + mnemonics[5:8] + mnemonics[10:13]) assert expected_ms == actual_ms
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_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_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 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
# # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the License along with this library. # If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>. import pytest from trezorlib import device, messages as proto EXPECTED_RESPONSES_NOPIN = [ proto.ButtonRequest(), proto.Success(), proto.Features() ] EXPECTED_RESPONSES_PIN_T1 = [proto.PinMatrixRequest() ] + EXPECTED_RESPONSES_NOPIN EXPECTED_RESPONSES_PIN_TT = [proto.ButtonRequest()] + EXPECTED_RESPONSES_NOPIN PIN4 = "1234" def _set_expected_responses(client): client.use_pin_sequence([PIN4]) if client.features.model == "1": client.set_expected_responses(EXPECTED_RESPONSES_PIN_T1) else: client.set_expected_responses(EXPECTED_RESPONSES_PIN_TT)
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 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
def test_initialize(self): with self.client: self.setup_mnemonic_pin_passphrase() self.client.set_expected_responses([proto.Features()]) self.client.init_device()
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