示例#1
0
def test_pin_fail(client: Client):
    ret = client.call_raw(
        messages.RecoveryDevice(
            word_count=12,
            passphrase_protection=True,
            pin_protection=True,
            label="label",
            language="en-US",
            enforce_wordlist=True,
        )
    )

    # click through confirmation
    assert isinstance(ret, messages.ButtonRequest)
    client.debug.press_yes()
    ret = client.call_raw(messages.ButtonAck())

    assert isinstance(ret, messages.PinMatrixRequest)

    # Enter PIN for first time
    pin_encoded = client.debug.encode_pin(PIN4)
    ret = client.call_raw(messages.PinMatrixAck(pin=pin_encoded))
    assert isinstance(ret, messages.PinMatrixRequest)

    # Enter PIN for second time, but different one
    pin_encoded = client.debug.encode_pin(PIN6)
    ret = client.call_raw(messages.PinMatrixAck(pin=pin_encoded))

    # Failure should be raised
    assert isinstance(ret, messages.Failure)
示例#2
0
def test_passphrase_always_on_device(client: Client):
    # Let's start the communication by calling Initialize.
    session_id = _init_session(client)

    # Force passphrase entry on Trezor.
    response = client.call(messages.ApplySettings(passphrase_always_on_device=True))
    assert isinstance(response, messages.Success)

    # Since we enabled the always_on_device setting, Trezor will send ButtonRequests and ask for it on the device.
    response = client.call_raw(XPUB_REQUEST)
    assert isinstance(response, messages.ButtonRequest)
    client.debug.input("")  # Input empty passphrase.
    response = client.call_raw(messages.ButtonAck())
    assert isinstance(response, messages.PublicKey)
    assert response.xpub == XPUB_PASSPHRASE_NONE

    # Passphrase will not be prompted. The session id stays the same and the passphrase is cached.
    _init_session(client, session_id=session_id)
    response = client.call_raw(XPUB_REQUEST)
    assert isinstance(response, messages.PublicKey)
    assert response.xpub == XPUB_PASSPHRASE_NONE

    # In case we want to add a new passphrase we need to send session_id = None.
    _init_session(client)
    response = client.call_raw(XPUB_REQUEST)
    assert isinstance(response, messages.ButtonRequest)
    client.debug.input("A")  # Input non-empty passphrase.
    response = client.call_raw(messages.ButtonAck())
    assert isinstance(response, messages.PublicKey)
    assert response.xpub == XPUB_PASSPHRASES["A"]
示例#3
0
def test_word_fail(client: Client):
    ret = client.call_raw(
        messages.RecoveryDevice(
            word_count=12,
            passphrase_protection=False,
            pin_protection=False,
            label="label",
            language="en-US",
            enforce_wordlist=True,
        )
    )

    # click through confirmation
    assert isinstance(ret, messages.ButtonRequest)
    client.debug.press_yes()
    ret = client.call_raw(messages.ButtonAck())

    assert isinstance(ret, messages.WordRequest)
    for _ in range(int(12 * 2)):
        (word, pos) = client.debug.read_recovery_word()
        if pos != 0:
            ret = client.call_raw(messages.WordAck(word="kwyjibo"))
            assert isinstance(ret, messages.Failure)
            break
        else:
            client.call_raw(messages.WordAck(word=word))
示例#4
0
def test_pin_passphrase(client: Client):
    mnemonic = MNEMONIC12.split(" ")
    ret = client.call_raw(
        messages.RecoveryDevice(
            word_count=12,
            passphrase_protection=True,
            pin_protection=True,
            label="label",
            language="en-US",
            enforce_wordlist=True,
        )
    )

    # click through confirmation
    assert isinstance(ret, messages.ButtonRequest)
    client.debug.press_yes()
    ret = client.call_raw(messages.ButtonAck())

    assert isinstance(ret, messages.PinMatrixRequest)

    # Enter PIN for first time
    pin_encoded = client.debug.encode_pin(PIN6)
    ret = client.call_raw(messages.PinMatrixAck(pin=pin_encoded))
    assert isinstance(ret, messages.PinMatrixRequest)

    # Enter PIN for second time
    pin_encoded = client.debug.encode_pin(PIN6)
    ret = client.call_raw(messages.PinMatrixAck(pin=pin_encoded))

    fakes = 0
    for _ in range(int(12 * 2)):
        assert isinstance(ret, messages.WordRequest)
        (word, pos) = client.debug.read_recovery_word()

        if pos != 0:
            ret = client.call_raw(messages.WordAck(word=mnemonic[pos - 1]))
            mnemonic[pos - 1] = None
        else:
            ret = client.call_raw(messages.WordAck(word=word))
            fakes += 1

    # Workflow succesfully ended
    assert isinstance(ret, messages.Success)

    # 12 expected fake words and all words of mnemonic are used
    assert fakes == 12
    assert mnemonic == [None] * 12

    # Mnemonic is the same
    client.init_device()
    assert client.debug.state().mnemonic_secret == MNEMONIC12.encode()

    assert client.features.pin_protection is True
    assert client.features.passphrase_protection is True

    # Do passphrase-protected action, PassphraseRequest should be raised
    resp = client.call_raw(messages.GetAddress(address_n=parse_path("m/44'/0'/0'/0/0")))
    assert isinstance(resp, messages.PassphraseRequest)
    client.call_raw(messages.Cancel())
示例#5
0
def test_passphrase_missing(client: Client):
    response = client.call_raw(XPUB_REQUEST)
    assert isinstance(response, messages.PassphraseRequest)
    response = client.call_raw(messages.PassphraseAck(passphrase=None))
    assert isinstance(response, messages.Failure)
    assert response.code == FailureType.DataError

    response = client.call_raw(XPUB_REQUEST)
    assert isinstance(response, messages.PassphraseRequest)
    response = client.call_raw(messages.PassphraseAck(passphrase=None, on_device=False))
    assert isinstance(response, messages.Failure)
    assert response.code == FailureType.DataError
示例#6
0
def test_enter_invalid(client: Client, invalid_pin):
    assert client.features.pin_protection is True

    # use an invalid PIN
    ret = client.call_raw(messages.GetAddress())

    # Send a PIN containing an invalid digit
    assert isinstance(ret, messages.PinMatrixRequest)
    ret = client.call_raw(messages.PinMatrixAck(pin=invalid_pin))

    # Ensure the invalid PIN is detected
    assert isinstance(ret, messages.Failure)
示例#7
0
def test_passphrase_on_device_not_possible_on_t1(client: Client):
    # This setting makes no sense on T1.
    response = client.call_raw(messages.ApplySettings(passphrase_always_on_device=True))
    assert isinstance(response, messages.Failure)
    assert response.code == FailureType.DataError

    # T1 should not accept on_device request
    response = client.call_raw(XPUB_REQUEST)
    assert isinstance(response, messages.PassphraseRequest)
    response = client.call_raw(messages.PassphraseAck(on_device=True))
    assert isinstance(response, messages.Failure)
    assert response.code == FailureType.DataError
示例#8
0
def test_pin(client: Client):
    resp = client.call_raw(messages.GetAddress())
    assert isinstance(resp, messages.PinMatrixRequest)

    state = client.debug.state()
    assert state.pin == "1234"
    assert state.matrix != ""

    pin_encoded = client.debug.encode_pin("1234")
    resp = client.call_raw(messages.PinMatrixAck(pin=pin_encoded))
    assert isinstance(resp, messages.PassphraseRequest)

    resp = client.call_raw(messages.PassphraseAck(passphrase=""))
    assert isinstance(resp, messages.Address)
示例#9
0
def test_cancel_on_paginated(client: Client):
    """Check that device is responsive on paginated screen. See #1708."""
    # In #1708, the device would ignore USB (or UDP) events while waiting for the user
    # to page through the screen. This means that this testcase, instead of failing,
    # would get stuck waiting for the _raw_read result.
    # I'm not spending the effort to modify the testcase to cause a _failure_ if that
    # happens again. Just be advised that this should not get stuck.
    message = m.SignMessage(
        message=b"hello" * 64,
        address_n=TEST_ADDRESS_N,
        coin_name="Testnet",
    )
    resp = client.call_raw(message)
    assert isinstance(resp, m.ButtonRequest)
    client._raw_write(m.ButtonAck())
    client.debug.press_yes()

    resp = client._raw_read()
    assert isinstance(resp, m.ButtonRequest)
    assert resp.pages is not None
    client._raw_write(m.ButtonAck())

    client._raw_write(m.Cancel())
    resp = client._raw_read()
    assert isinstance(resp, m.Failure)
    assert resp.code == m.FailureType.ActionCancelled
示例#10
0
def test_already_initialized(client: Client):
    with pytest.raises(RuntimeError):
        device.recover(client, 12, False, False, "label", "en-US",
                       client.mnemonic_callback)

    ret = client.call_raw(
        messages.RecoveryDevice(
            word_count=12, type=messages.RecoveryDeviceType.ScrambledWords))
    assert isinstance(ret, messages.Failure)
    assert "Device is already initialized" in ret.message
示例#11
0
def test_cancel_message_via_initialize(client: Client, message):
    resp = client.call_raw(message)
    assert isinstance(resp, m.ButtonRequest)

    client._raw_write(m.ButtonAck())
    client._raw_write(m.Initialize())

    resp = client._raw_read()

    assert isinstance(resp, m.Features)
示例#12
0
def _get_xpub_cardano(client: Client, passphrase):
    msg = messages.CardanoGetPublicKey(
        address_n=parse_path("m/44h/1815h/0h/0/0"),
        derivation_type=messages.CardanoDerivationType.ICARUS,
    )
    response = client.call_raw(msg)
    if passphrase is not None:
        assert isinstance(response, messages.PassphraseRequest)
        response = client.call(messages.PassphraseAck(passphrase=passphrase))
    assert isinstance(response, messages.CardanoPublicKey)
    return response.xpub
示例#13
0
def test_reset_device_skip_backup_show_entropy_fail(client: Client):
    ret = client.call_raw(
        messages.ResetDevice(
            display_random=True,
            strength=STRENGTH,
            passphrase_protection=False,
            pin_protection=False,
            language="en-US",
            label="test",
            skip_backup=True,
        ))
    assert isinstance(ret, messages.Failure)
def test_set_wipe_code_invalid(client: Client, invalid_wipe_code):
    # Let's set the wipe code
    ret = client.call_raw(messages.ChangeWipeCode())
    assert isinstance(ret, messages.ButtonRequest)

    # Confirm
    client.debug.press_yes()
    ret = client.call_raw(messages.ButtonAck())

    # Enter a wipe code containing an invalid digit
    assert isinstance(ret, messages.PinMatrixRequest)
    assert ret.type == PinType.WipeCodeFirst
    ret = client.call_raw(messages.PinMatrixAck(pin=invalid_wipe_code))

    # Ensure the invalid wipe code is detected
    assert isinstance(ret, messages.Failure)

    # Check that there's still no wipe code protection.
    client.init_device()
    client.ensure_unlocked()
    assert client.features.wipe_code_protection is False
示例#15
0
def test_reset_device_skip_backup_break(client: Client):
    ret = client.call_raw(
        messages.ResetDevice(
            display_random=False,
            strength=STRENGTH,
            passphrase_protection=False,
            pin_protection=False,
            language="en-US",
            label="test",
            skip_backup=True,
        ))

    assert isinstance(ret, messages.ButtonRequest)
    client.debug.press_yes()
    ret = client.call_raw(messages.ButtonAck())

    # Provide entropy
    assert isinstance(ret, messages.EntropyRequest)
    ret = client.call_raw(messages.EntropyAck(entropy=EXTERNAL_ENTROPY))
    assert isinstance(ret, messages.Success)

    # Check if device is properly initialized
    ret = client.call_raw(messages.Initialize())
    assert ret.initialized is True
    assert ret.needs_backup is True
    assert ret.unfinished_backup is False
    assert ret.no_backup is False

    # start Backup workflow
    ret = client.call_raw(messages.BackupDevice())

    # send Initialize -> break workflow
    ret = client.call_raw(messages.Initialize())
    assert isinstance(ret, messages.Features)
    assert ret.initialized is True
    assert ret.needs_backup is False
    assert ret.unfinished_backup is True
    assert ret.no_backup is False

    # start backup again - should fail
    ret = client.call_raw(messages.BackupDevice())
    assert isinstance(ret, messages.Failure)

    # read Features again
    ret = client.call_raw(messages.Initialize())
    assert isinstance(ret, messages.Features)
    assert ret.initialized is True
    assert ret.needs_backup is False
    assert ret.unfinished_backup is True
    assert ret.no_backup is False
示例#16
0
def test_passphrase_on_device(client: Client):
    _init_session(client)

    # try to get xpub with passphrase on host:
    response = client.call_raw(XPUB_REQUEST)
    assert isinstance(response, messages.PassphraseRequest)
    # using `client.call` to auto-skip subsequent ButtonRequests for "show passphrase"
    response = client.call(messages.PassphraseAck(passphrase="A", on_device=False))

    assert isinstance(response, messages.PublicKey)
    assert response.xpub == XPUB_PASSPHRASES["A"]

    # try to get xpub again, passphrase should be cached
    response = client.call_raw(XPUB_REQUEST)
    assert isinstance(response, messages.PublicKey)
    assert response.xpub == XPUB_PASSPHRASES["A"]

    # make a new session
    _init_session(client)

    # try to get xpub with passphrase on device:
    response = client.call_raw(XPUB_REQUEST)
    assert isinstance(response, messages.PassphraseRequest)
    response = client.call_raw(messages.PassphraseAck(on_device=True))
    # no "show passphrase" here
    assert isinstance(response, messages.ButtonRequest)
    client.debug.input("A")
    response = client.call_raw(messages.ButtonAck())
    assert isinstance(response, messages.PublicKey)
    assert response.xpub == XPUB_PASSPHRASES["A"]

    # try to get xpub again, passphrase should be cached
    response = client.call_raw(XPUB_REQUEST)
    assert isinstance(response, messages.PublicKey)
    assert response.xpub == XPUB_PASSPHRASES["A"]
示例#17
0
def test_set_invalid(client: Client, invalid_pin):
    assert client.features.pin_protection is False

    # Let's set an invalid PIN
    ret = client.call_raw(messages.ChangePin())
    assert isinstance(ret, messages.ButtonRequest)

    # Press button
    client.debug.press_yes()
    ret = client.call_raw(messages.ButtonAck())

    # Send a PIN containing an invalid digit
    assert isinstance(ret, messages.PinMatrixRequest)
    ret = client.call_raw(messages.PinMatrixAck(pin=invalid_pin))

    # Ensure the invalid PIN is detected
    assert isinstance(ret, messages.Failure)

    # Check that there's still no PIN protection now
    client.init_device()
    assert client.features.pin_protection is False
    _check_no_pin(client)
def test_interrupt_backup_fails(client: Client):
    client.ensure_unlocked()
    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_failed_pin(client: Client):
    # external_entropy = b'zlutoucky kun upel divoke ody' * 2
    strength = 128
    ret = client.call_raw(
        messages.ResetDevice(strength=strength,
                             pin_protection=True,
                             label="test"))

    # Confirm Reset
    assert isinstance(ret, messages.ButtonRequest)
    client.debug.press_yes()
    ret = client.call_raw(messages.ButtonAck())

    # Enter PIN for first time
    assert isinstance(ret, messages.ButtonRequest)
    client.debug.input("654")
    ret = client.call_raw(messages.ButtonAck())

    # Enter PIN for second time
    assert isinstance(ret, messages.ButtonRequest)
    client.debug.input("456")
    ret = client.call_raw(messages.ButtonAck())

    assert isinstance(ret, messages.ButtonRequest)
示例#20
0
def test_autolock_cancels_ui(client: Client):
    set_autolock_delay(client, 10 * 1000)

    resp = client.call_raw(
        messages.GetAddress(
            coin_name="Testnet",
            address_n=TEST_ADDRESS_N,
            show_display=True,
            script_type=messages.InputScriptType.SPENDADDRESS,
        ))
    assert isinstance(resp, messages.ButtonRequest)

    # send an ack, do not read response
    client._raw_write(messages.ButtonAck())
    # sleep more than auto-lock delay
    time.sleep(10.5)
    resp = client._raw_read()

    assert isinstance(resp, messages.Failure)
    assert resp.code == messages.FailureType.ActionCancelled
def test_set_pin_to_wipe_code(client: Client):
    # Set wipe code.
    _set_wipe_code(client, None, WIPE_CODE4)

    # Try to set the PIN to the current wipe code value.
    with client:
        client.use_pin_sequence([WIPE_CODE4, WIPE_CODE4])
        client.set_expected_responses([
            messages.ButtonRequest(),
            messages.PinMatrixRequest(type=PinType.NewFirst),
            messages.PinMatrixRequest(type=PinType.NewSecond),
            messages.Failure(code=messages.FailureType.ProcessError),
        ])
        with pytest.raises(exceptions.TrezorFailure):
            device.change_pin(client)

    # Check that there is no PIN protection.
    client.init_device()
    assert client.features.pin_protection is False
    resp = client.call_raw(messages.GetAddress())
    assert isinstance(resp, messages.Address)
示例#22
0
def test_failed_pin(client: Client):
    # external_entropy = b'zlutoucky kun upel divoke ody' * 2
    strength = 128

    ret = client.call_raw(
        messages.ResetDevice(
            display_random=True,
            strength=strength,
            passphrase_protection=True,
            pin_protection=True,
            language="en-US",
            label="test",
        ))

    # Do you want ... ?
    assert isinstance(ret, messages.ButtonRequest)
    client.debug.press_yes()
    ret = client.call_raw(messages.ButtonAck())

    # Entropy screen #1
    assert isinstance(ret, messages.ButtonRequest)
    client.debug.press_yes()
    ret = client.call_raw(messages.ButtonAck())

    # Entropy screen #2
    assert isinstance(ret, messages.ButtonRequest)
    client.debug.press_yes()
    ret = client.call_raw(messages.ButtonAck())

    assert isinstance(ret, messages.PinMatrixRequest)

    # Enter PIN for first time
    pin_encoded = client.debug.encode_pin("1234")
    ret = client.call_raw(messages.PinMatrixAck(pin=pin_encoded))
    assert isinstance(ret, messages.PinMatrixRequest)

    # Enter PIN for second time
    pin_encoded = client.debug.encode_pin("6789")
    ret = client.call_raw(messages.PinMatrixAck(pin=pin_encoded))

    assert isinstance(ret, messages.Failure)
示例#23
0
def test_reset_device_256_pin(client: Client):
    external_entropy = b"zlutoucky kun upel divoke ody" * 2
    strength = 256

    ret = client.call_raw(
        messages.ResetDevice(
            display_random=True,
            strength=strength,
            passphrase_protection=True,
            pin_protection=True,
            language="en-US",
            label="test",
        ))

    # Do you want ... ?
    assert isinstance(ret, messages.ButtonRequest)
    client.debug.press_yes()
    ret = client.call_raw(messages.ButtonAck())

    # Entropy screen #1
    assert isinstance(ret, messages.ButtonRequest)
    client.debug.press_yes()
    ret = client.call_raw(messages.ButtonAck())

    # Entropy screen #2
    assert isinstance(ret, messages.ButtonRequest)
    client.debug.press_yes()
    ret = client.call_raw(messages.ButtonAck())

    assert isinstance(ret, messages.PinMatrixRequest)

    # Enter PIN for first time
    pin_encoded = client.debug.encode_pin("654")
    ret = client.call_raw(messages.PinMatrixAck(pin=pin_encoded))
    assert isinstance(ret, messages.PinMatrixRequest)

    # Enter PIN for second time
    pin_encoded = client.debug.encode_pin("654")
    ret = client.call_raw(messages.PinMatrixAck(pin=pin_encoded))

    # Provide entropy
    assert isinstance(ret, messages.EntropyRequest)
    internal_entropy = client.debug.state().reset_entropy
    ret = client.call_raw(messages.EntropyAck(entropy=external_entropy))

    # Generate mnemonic locally
    entropy = generate_entropy(strength, internal_entropy, external_entropy)
    expected_mnemonic = Mnemonic("english").to_mnemonic(entropy)

    mnemonic = []
    for _ in range(strength // 32 * 3):
        assert isinstance(ret, messages.ButtonRequest)
        mnemonic.append(client.debug.read_reset_word())
        client.debug.press_yes()
        client.call_raw(messages.ButtonAck())

    mnemonic = " ".join(mnemonic)

    # Compare that device generated proper mnemonic for given entropies
    assert mnemonic == expected_mnemonic

    mnemonic = []
    for _ in range(strength // 32 * 3):
        assert isinstance(ret, messages.ButtonRequest)
        mnemonic.append(client.debug.read_reset_word())
        client.debug.press_yes()
        resp = client.call_raw(messages.ButtonAck())

    assert isinstance(resp, messages.Success)

    mnemonic = " ".join(mnemonic)

    # Compare that second pass printed out the same mnemonic once again
    assert mnemonic == expected_mnemonic

    # Check if device is properly initialized
    resp = client.call_raw(messages.Initialize())
    assert resp.initialized is True
    assert resp.needs_backup is False
    assert resp.pin_protection is True
    assert resp.passphrase_protection is True

    # Do passphrase-protected action, PassphraseRequest should be raised
    resp = client.call_raw(messages.GetAddress())
    assert isinstance(resp, messages.PassphraseRequest)
    client.call_raw(messages.Cancel())
示例#24
0
def test_passphrase_ack_mismatch(client: Client):
    response = client.call_raw(XPUB_REQUEST)
    assert isinstance(response, messages.PassphraseRequest)
    response = client.call_raw(messages.PassphraseAck(passphrase="A", on_device=True))
    assert isinstance(response, messages.Failure)
    assert response.code == FailureType.DataError
示例#25
0
def test_reset_device_skip_backup(client: Client):
    ret = client.call_raw(
        messages.ResetDevice(
            display_random=False,
            strength=STRENGTH,
            passphrase_protection=False,
            pin_protection=False,
            language="en-US",
            label="test",
            skip_backup=True,
        ))

    assert isinstance(ret, messages.ButtonRequest)
    client.debug.press_yes()
    ret = client.call_raw(messages.ButtonAck())

    # Provide entropy
    assert isinstance(ret, messages.EntropyRequest)
    internal_entropy = client.debug.state().reset_entropy
    ret = client.call_raw(messages.EntropyAck(entropy=EXTERNAL_ENTROPY))
    assert isinstance(ret, messages.Success)

    # Check if device is properly initialized
    ret = client.call_raw(messages.Initialize())
    assert ret.initialized is True
    assert ret.needs_backup is True
    assert ret.unfinished_backup is False
    assert ret.no_backup is False

    # Generate mnemonic locally
    entropy = generate_entropy(STRENGTH, internal_entropy, EXTERNAL_ENTROPY)
    expected_mnemonic = Mnemonic("english").to_mnemonic(entropy)

    # start Backup workflow
    ret = client.call_raw(messages.BackupDevice())

    mnemonic = []
    for _ in range(STRENGTH // 32 * 3):
        assert isinstance(ret, messages.ButtonRequest)
        mnemonic.append(client.debug.read_reset_word())
        client.debug.press_yes()
        client.call_raw(messages.ButtonAck())

    mnemonic = " ".join(mnemonic)

    # Compare that device generated proper mnemonic for given entropies
    assert mnemonic == expected_mnemonic

    mnemonic = []
    for _ in range(STRENGTH // 32 * 3):
        assert isinstance(ret, messages.ButtonRequest)
        mnemonic.append(client.debug.read_reset_word())
        client.debug.press_yes()
        ret = client.call_raw(messages.ButtonAck())

    assert isinstance(ret, messages.Success)

    mnemonic = " ".join(mnemonic)

    # Compare that second pass printed out the same mnemonic once again
    assert mnemonic == expected_mnemonic

    # start backup again - should fail
    ret = client.call_raw(messages.BackupDevice())
    assert isinstance(ret, messages.Failure)
示例#26
0
def reset_device(client: Client, strength):
    # No PIN, no passphrase
    external_entropy = b"zlutoucky kun upel divoke ody" * 2

    ret = client.call_raw(
        messages.ResetDevice(
            display_random=False,
            strength=strength,
            passphrase_protection=False,
            pin_protection=False,
            language="en-US",
            label="test",
        ))

    assert isinstance(ret, messages.ButtonRequest)
    client.debug.press_yes()
    ret = client.call_raw(messages.ButtonAck())

    # Provide entropy
    assert isinstance(ret, messages.EntropyRequest)
    internal_entropy = client.debug.state().reset_entropy
    ret = client.call_raw(messages.EntropyAck(entropy=external_entropy))

    # Generate mnemonic locally
    entropy = generate_entropy(strength, internal_entropy, external_entropy)
    expected_mnemonic = Mnemonic("english").to_mnemonic(entropy)

    mnemonic = []
    for _ in range(strength // 32 * 3):
        assert isinstance(ret, messages.ButtonRequest)
        mnemonic.append(client.debug.read_reset_word())
        client.debug.press_yes()
        client.call_raw(messages.ButtonAck())

    mnemonic = " ".join(mnemonic)

    # Compare that device generated proper mnemonic for given entropies
    assert mnemonic == expected_mnemonic

    mnemonic = []
    for _ in range(strength // 32 * 3):
        assert isinstance(ret, messages.ButtonRequest)
        mnemonic.append(client.debug.read_reset_word())
        client.debug.press_yes()
        resp = client.call_raw(messages.ButtonAck())

    assert isinstance(resp, messages.Success)

    mnemonic = " ".join(mnemonic)

    # Compare that second pass printed out the same mnemonic once again
    assert mnemonic == expected_mnemonic

    # Check if device is properly initialized
    resp = client.call_raw(messages.Initialize())
    assert resp.initialized is True
    assert resp.needs_backup is False
    assert resp.pin_protection is False
    assert resp.passphrase_protection is False

    # Do pin & passphrase-protected action, PassphraseRequest should NOT be raised
    resp = client.call_raw(messages.GetAddress())
    assert isinstance(resp, messages.Address)
示例#27
0
def test_initialized_device_backup_fail(client: Client):
    ret = client.call_raw(messages.BackupDevice())
    assert isinstance(ret, messages.Failure)
def reset_device(client: Client, 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
        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",
        )

    # 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(messages.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 messages.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_failed_check(client: Client):
    mnemonic = None
    strength = 256  # 24 words

    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, wrong answer
        mnemonic = yield from read_and_confirm_mnemonic(client.debug,
                                                        choose_wrong=True)

        # warning screen
        br = yield
        assert br.code == B.ResetDevice
        client.debug.press_yes()

        # 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.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)

        # PIN, passphrase, 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(messages.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 messages.BackupType.Bip39