def test_apply_settings(self):
     with self.client:
         self.setup_mnemonic_pin_passphrase()
         self.client.set_expected_responses(
             [
                 proto.PinMatrixRequest(),
                 proto.ButtonRequest(),
                 proto.Success(),
                 proto.Features(),
             ]
         )  # TrezorClient reinitializes device
         device.apply_settings(self.client, label="nazdar")
Exemple #2
0
 def _setup_mnemonic(self, mnemonic=None, pin="", passphrase=False, lock=True):
     if mnemonic is None:
         mnemonic = TrezorTest.mnemonic12
     debuglink.load_device_by_mnemonic(
         self.client,
         mnemonic=mnemonic,
         pin=pin,
         passphrase_protection=passphrase,
         label="test",
         language="english",
     )
     if conftest.TREZOR_VERSION == 1 and lock:
         # remove cached PIN (introduced via load_device)
         self.client.clear_session()
     if conftest.TREZOR_VERSION > 1 and passphrase:
         device.apply_settings(self.client, passphrase_source=PASSPHRASE_ON_HOST)
def test_autolock_not_retained(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)
Exemple #4
0
def test_invalid_path_prompt(client: Client):
    inp1 = messages.TxInputType(
        address_n=parse_path("m/44h/0h/0h/0/0"),
        amount=390_000,
        prev_hash=PREV_HASH,
        prev_index=0,
    )

    # address is converted from 1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1 by changing the version
    out1 = messages.TxOutputType(
        address="LfWz9wLHmqU9HoDkMg9NqbRosrHvEixeVZ",
        amount=390_000 - 10_000,
        script_type=messages.OutputScriptType.PAYTOADDRESS,
    )

    device.apply_settings(
        client, safety_checks=messages.SafetyCheckLevel.PromptTemporarily)

    btc.sign_tx(client, "Litecoin", [inp1], [out1], prev_txes=PREV_TXES)
    def test_apply_auto_lock_delay(self):
        self.setup_mnemonic_pin_passphrase()

        with self.client:
            self.client.set_expected_responses(EXPECTED_RESPONSES_PIN)
            device.apply_settings(self.client,
                                  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_cache(client: Client):
    # disable safety checks to access non-standard paths
    device.apply_settings(client,
                          safety_checks=SafetyCheckLevel.PromptTemporarily)

    start = time.time()
    for x in range(10):
        btc.get_address(client, "Bitcoin", [x, 2, 3, 4, 5, 6, 7, 8])
    nocache_time = time.time() - start

    start = time.time()
    for x in range(10):
        btc.get_address(client, "Bitcoin", [1, 2, 3, 4, 5, 6, 7, x])
    cache_time = time.time() - start

    print("NOCACHE TIME", nocache_time)
    print("CACHED TIME", cache_time)

    # Cached time expected to be at least 2x faster
    assert cache_time <= nocache_time / 2.0
Exemple #7
0
def test_passphrase_reporting(client: Client, passphrase):
    """On TT, passphrase_protection is a private setting, so a locked device should
    report passphrase_protection=None.
    """
    with client:
        client.use_pin_sequence([PIN4])
        device.apply_settings(client, use_passphrase=passphrase)

    client.lock()

    # on a locked device, passphrase_protection should be None
    assert client.features.unlocked is False
    assert client.features.passphrase_protection is None

    # on an unlocked device, protection should be reported accurately
    _assert_protection(client, pin=True, passphrase=passphrase)

    # after re-locking, the setting should be hidden again
    client.lock()
    assert client.features.unlocked is False
    assert client.features.passphrase_protection is None
Exemple #8
0
 def _setup_mnemonic(self,
                     mnemonic=None,
                     pin="",
                     passphrase=False,
                     lock=True):
     if mnemonic is None:
         mnemonic = TrezorTest.mnemonic12
     debuglink.load_device_by_mnemonic(
         self.client,
         mnemonic=mnemonic,
         pin=pin,
         passphrase_protection=passphrase,
         label="test",
         language="english",
     )
     if conftest.TREZOR_VERSION == 1 and lock:
         # remove cached PIN (introduced via load_device)
         self.client.clear_session()
     if conftest.TREZOR_VERSION > 1 and passphrase:
         device.apply_settings(self.client,
                               passphrase_source=PASSPHRASE_ON_HOST)
    def test_load_device_2(self, client):
        debuglink.load_device_by_mnemonic(
            client,
            mnemonic=MNEMONIC12,
            pin="1234",
            passphrase_protection=True,
            label="test",
        )
        if client.features.model == "T":
            device.apply_settings(client, passphrase_source=PASSPHRASE_ON_HOST)
        client.set_passphrase("passphrase")
        state = client.debug.state()
        assert state.mnemonic_secret == MNEMONIC12.encode()

        if client.features.model == "1":
            # we do not send PIN in DebugLinkState in Core
            assert state.pin == "1234"
        assert state.passphrase_protection is True

        address = btc.get_address(client, "Bitcoin", [])
        assert address == "15fiTDFwZd2kauHYYseifGi9daH2wniDHH"
Exemple #10
0
    def test_apply_settings_passphrase(self):
        self.setup_mnemonic_pin_nopassphrase()

        assert self.client.features.passphrase_protection is False

        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, use_passphrase=True)

        assert self.client.features.passphrase_protection is True

        with self.client:
            self.client.set_expected_responses(
                [proto.ButtonRequest(),
                 proto.Success(),
                 proto.Features()])
            device.apply_settings(self.client, use_passphrase=False)

        assert self.client.features.passphrase_protection is False

        with self.client:
            self.client.set_expected_responses(
                [proto.ButtonRequest(),
                 proto.Success(),
                 proto.Features()])
            device.apply_settings(self.client, use_passphrase=True)

        assert self.client.features.passphrase_protection is True
Exemple #11
0
    def test_experimental_features(self, client):
        def experimental_call():
            btc.authorize_coinjoin(
                client,
                coordinator="www.example.com",
                max_total_fee=10010,
                fee_per_anonymity=5000000,  # 0.005 %
                n=parse_path("m/84'/1'/0'"),
                coin_name="Testnet",
                script_type=messages.InputScriptType.SPENDWITNESS,
            )

        assert client.features.experimental_features is None

        # unlock
        with client:
            _set_expected_responses(client)
            device.apply_settings(client, label="new label")

        assert client.features.experimental_features

        with client:
            client.set_expected_responses([
                messages.ButtonRequest, messages.ButtonRequest,
                messages.Success
            ])
            experimental_call()

        with client:
            client.set_expected_responses(
                [messages.Success, messages.Features])
            device.apply_settings(client, experimental_features=False)

        assert not client.features.experimental_features

        with pytest.raises(exceptions.TrezorFailure,
                           match="DataError"), client:
            client.set_expected_responses([messages.Failure])
            experimental_call()
def test_invalid_path_prompt(client):
    # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882
    # input 0: 0.0039 BTC

    inp1 = messages.TxInputType(
        address_n=parse_path("44h/0h/0h/0/0"),
        amount=390000,
        prev_hash=TXHASH_d5f65e,
        prev_index=0,
    )

    # address is converted from 1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1 by changing the version
    out1 = messages.TxOutputType(
        address="LfWz9wLHmqU9HoDkMg9NqbRosrHvEixeVZ",
        amount=390000 - 10000,
        script_type=messages.OutputScriptType.PAYTOADDRESS,
    )

    device.apply_settings(
        client, safety_checks=messages.SafetyCheckLevel.PromptTemporarily)

    btc.sign_tx(client, "Litecoin", [inp1], [out1], prev_txes=TX_CACHE_MAINNET)
def test_cardano_sign_tx(client, parameters, result):
    inputs = [cardano.parse_input(i) for i in parameters["inputs"]]
    outputs = [cardano.parse_output(o) for o in parameters["outputs"]]
    certificates = [
        cardano.parse_certificate(c) for c in parameters["certificates"]
    ]
    withdrawals = [
        cardano.parse_withdrawal(w) for w in parameters["withdrawals"]
    ]
    auxiliary_data = cardano.parse_auxiliary_data(parameters["auxiliary_data"])

    input_flow = parameters.get("input_flow", ())

    if parameters.get("security_checks") == "prompt":
        device.apply_settings(
            client, safety_checks=messages.SafetyCheckLevel.PromptTemporarily)
    else:
        device.apply_settings(client,
                              safety_checks=messages.SafetyCheckLevel.Strict)

    with client:
        client.set_input_flow(_to_device_actions(client, input_flow))

        response = cardano.sign_tx(
            client=client,
            inputs=inputs,
            outputs=outputs,
            fee=parameters["fee"],
            ttl=parameters.get("ttl"),
            validity_interval_start=parameters.get("validity_interval_start"),
            certificates=certificates,
            withdrawals=withdrawals,
            protocol_magic=parameters["protocol_magic"],
            network_id=parameters["network_id"],
            auxiliary_data=auxiliary_data,
        )
        assert response.tx_hash.hex() == result["tx_hash"]
        assert response.serialized_tx.hex() == result["serialized_tx"]
Exemple #14
0
    def test_safety_checks(self, client):
        def get_bad_address():
            btc.get_address(client,
                            "Bitcoin",
                            parse_path("m/44'"),
                            show_display=True)

        assert client.features.safety_checks == messages.SafetyCheckLevel.Strict

        with pytest.raises(exceptions.TrezorFailure,
                           match="Forbidden key path"), client:
            client.set_expected_responses([messages.Failure])
            get_bad_address()

        if client.features.model != "1":
            with client:
                client.set_expected_responses(EXPECTED_RESPONSES_NOPIN)
                device.apply_settings(
                    client,
                    safety_checks=messages.SafetyCheckLevel.PromptAlways)

            assert (client.features.safety_checks ==
                    messages.SafetyCheckLevel.PromptAlways)

            with client:
                client.set_expected_responses([
                    messages.ButtonRequest, messages.ButtonRequest,
                    messages.Address
                ])
                get_bad_address()

        with client:
            client.set_expected_responses(EXPECTED_RESPONSES_NOPIN)
            device.apply_settings(
                client, safety_checks=messages.SafetyCheckLevel.Strict)

        assert client.features.safety_checks == messages.SafetyCheckLevel.Strict

        with pytest.raises(exceptions.TrezorFailure,
                           match="Forbidden key path"), client:
            client.set_expected_responses([messages.Failure])
            get_bad_address()

        with client:
            client.set_expected_responses(EXPECTED_RESPONSES_NOPIN)
            device.apply_settings(
                client,
                safety_checks=messages.SafetyCheckLevel.PromptTemporarily)

        assert (client.features.safety_checks ==
                messages.SafetyCheckLevel.PromptTemporarily)

        with client:
            client.set_expected_responses([
                messages.ButtonRequest, messages.ButtonRequest,
                messages.Address
            ])
            get_bad_address()
Exemple #15
0
def client(request):
    client = get_device()
    wipe_device(client)

    client.open()

    # fmt: off
    setup_params = dict(
        uninitialized=False,
        mnemonic=" ".join(["all"] * 12),
        pin=None,
        passphrase=False,
    )
    # fmt: on

    marker = request.node.get_closest_marker("setup_client")
    if marker:
        setup_params.update(marker.kwargs)

    if not setup_params["uninitialized"]:
        if setup_params["pin"] is True:
            setup_params["pin"] = "1234"

        debuglink.load_device_by_mnemonic(
            client,
            mnemonic=setup_params["mnemonic"],
            pin=setup_params["pin"],
            passphrase_protection=setup_params["passphrase"],
            label="test",
            language="english",
        )
        client.clear_session()
        if setup_params["passphrase"] and client.features.model != "1":
            apply_settings(client, passphrase_source=PASSPHRASE_ON_HOST)

    yield client
    client.close()
Exemple #16
0
def test_unknown_path_tt(client):
    UNKNOWN_PATH = parse_path("m/44'/9'/0'/0/0")
    with pytest.raises(TrezorFailure, match="Forbidden key path"):
        # account number is too high
        btc.get_address(client, "Bitcoin", UNKNOWN_PATH)

    # disable safety checks
    device.apply_settings(client,
                          safety_checks=SafetyCheckLevel.PromptTemporarily)

    with client:
        client.set_expected_responses([
            messages.ButtonRequest(
                code=messages.ButtonRequestType.UnknownDerivationPath),
            messages.ButtonRequest(code=messages.ButtonRequestType.Address),
            messages.Address,
        ])
        # try again with a warning
        btc.get_address(client, "Bitcoin", UNKNOWN_PATH, show_display=True)

    with client:
        # no warning is displayed when the call is silent
        client.set_expected_responses([messages.Address])
        btc.get_address(client, "Bitcoin", UNKNOWN_PATH, show_display=False)
Exemple #17
0
def test_apply_settings_passphrase(client: Client):
    with client:
        _set_expected_responses(client)
        device.apply_settings(client, use_passphrase=True)

    assert client.features.passphrase_protection is True

    with client:
        client.set_expected_responses(EXPECTED_RESPONSES_NOPIN)
        device.apply_settings(client, use_passphrase=False)

    assert client.features.passphrase_protection is False

    with client:
        client.set_expected_responses(EXPECTED_RESPONSES_NOPIN)
        device.apply_settings(client, use_passphrase=True)

    assert client.features.passphrase_protection is True
    def test_apply_settings_passphrase(self):
        self.setup_mnemonic_pin_nopassphrase()

        assert self.client.features.passphrase_protection is False

        with self.client:
            self.client.set_expected_responses(EXPECTED_RESPONSES)
            device.apply_settings(self.client, use_passphrase=True)

        assert self.client.features.passphrase_protection is True

        with self.client:
            self.client.set_expected_responses(EXPECTED_RESPONSES_NOPIN)
            device.apply_settings(self.client, use_passphrase=False)

        assert self.client.features.passphrase_protection is False

        with self.client:
            self.client.set_expected_responses(EXPECTED_RESPONSES_NOPIN)
            device.apply_settings(self.client, use_passphrase=True)

        assert self.client.features.passphrase_protection is True
    yield
    client.debug.input(new_pin)


if __name__ == "__main__":
    wirelink = get_device()
    client = TrezorClientDebugLink(wirelink)
    client.open()

    i = 0

    last_pin = None

    while True:
        # set private field
        device.apply_settings(client, use_passphrase=True)
        assert client.features.passphrase_protection is True
        device.apply_settings(client, use_passphrase=False)
        assert client.features.passphrase_protection is False

        # set public field
        label = "".join(
            random.choices(string.ascii_uppercase + string.digits, k=17))
        device.apply_settings(client, label=label)
        assert client.features.label == label

        # change PIN
        new_pin = "".join(
            random.choices(string.digits, k=random.randint(6, 10)))
        client.set_input_flow(pin_input_flow(client, last_pin, new_pin))
        device.change_pin(client)
Exemple #20
0
def client(request):
    """Client fixture.

    Every test function that requires a client instance will get it from here.
    If we can't connect to a debuggable device, the test will fail.
    If 'skip_t2' is used and TT is connected, the test is skipped. Vice versa with T1
    and 'skip_t1'.

    The client instance is wiped and preconfigured with "all all all..." mnemonic, no
    password and no pin. It is possible to customize this with the `setup_client`
    marker.

    To specify a custom mnemonic and/or custom pin and/or enable passphrase:

    @pytest.mark.setup_client(mnemonic=MY_MNEMONIC, pin="9999", passphrase=True)

    To receive a client instance that was not initialized:

    @pytest.mark.setup_client(uninitialized=True)
    """
    try:
        client = get_device()
    except RuntimeError:
        pytest.fail("No debuggable Trezor is available")

    if request.node.get_closest_marker(
            "skip_t2") and client.features.model == "T":
        pytest.skip("Test excluded on Trezor T")
    if request.node.get_closest_marker(
            "skip_t1") and client.features.model == "1":
        pytest.skip("Test excluded on Trezor 1")

    if (request.node.get_closest_marker("sd_card")
            and not client.features.sd_card_present):
        raise RuntimeError("This test requires SD card.\n"
                           "To skip all such tests, run:\n"
                           "  pytest -m 'not sd_card' <test path>")

    wipe_device(client)

    # fmt: off
    setup_params = dict(
        uninitialized=False,
        mnemonic=" ".join(["all"] * 12),
        pin=None,
        passphrase=False,
    )
    # fmt: on

    marker = request.node.get_closest_marker("setup_client")
    if marker:
        setup_params.update(marker.kwargs)

    if not setup_params["uninitialized"]:
        if setup_params["pin"] is True:
            setup_params["pin"] = "1234"

        debuglink.load_device_by_mnemonic(
            client,
            mnemonic=setup_params["mnemonic"],
            pin=setup_params["pin"],
            passphrase_protection=setup_params["passphrase"],
            label="test",
            language="english",
        )
        client.clear_session()
        if setup_params["passphrase"] and client.features.model != "1":
            apply_settings(client, passphrase_source=PASSPHRASE_ON_HOST)

    client.open()
    yield client
    client.close()
    def test_load_device_utf(self, client):
        words_nfkd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a"
        words_nfc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f"
        words_nfkc = u"P\u0159\xed\u0161ern\u011b \u017elu\u0165ou\u010dk\xfd k\u016f\u0148 \xfap\u011bl \u010f\xe1belsk\xe9 \xf3dy z\xe1ke\u0159n\xfd u\u010de\u0148 b\u011b\u017e\xed pod\xe9l z\xf3ny \xfal\u016f"
        words_nfd = u"Pr\u030ci\u0301s\u030cerne\u030c z\u030clut\u030couc\u030cky\u0301 ku\u030an\u030c u\u0301pe\u030cl d\u030ca\u0301belske\u0301 o\u0301dy za\u0301ker\u030cny\u0301 uc\u030cen\u030c be\u030cz\u030ci\u0301 pode\u0301l zo\u0301ny u\u0301lu\u030a"

        passphrase_nfkd = (
            u"Neuve\u030cr\u030citelne\u030c bezpec\u030cne\u0301 hesli\u0301c\u030cko"
        )
        passphrase_nfc = (
            u"Neuv\u011b\u0159iteln\u011b bezpe\u010dn\xe9 hesl\xed\u010dko")
        passphrase_nfkc = (
            u"Neuv\u011b\u0159iteln\u011b bezpe\u010dn\xe9 hesl\xed\u010dko")
        passphrase_nfd = (
            u"Neuve\u030cr\u030citelne\u030c bezpec\u030cne\u0301 hesli\u0301c\u030cko"
        )

        device.wipe(client)
        debuglink.load_device_by_mnemonic(
            client,
            mnemonic=words_nfkd,
            pin="",
            passphrase_protection=True,
            label="test",
            language="english",
            skip_checksum=True,
        )
        if client.features.model == "T":
            device.apply_settings(client, passphrase_source=PASSPHRASE_ON_HOST)
        client.set_passphrase(passphrase_nfkd)
        address_nfkd = btc.get_address(client, "Bitcoin", [])

        device.wipe(client)
        debuglink.load_device_by_mnemonic(
            client,
            mnemonic=words_nfc,
            pin="",
            passphrase_protection=True,
            label="test",
            language="english",
            skip_checksum=True,
        )
        if client.features.model == "T":
            device.apply_settings(client, passphrase_source=PASSPHRASE_ON_HOST)
        client.set_passphrase(passphrase_nfc)
        address_nfc = btc.get_address(client, "Bitcoin", [])

        device.wipe(client)
        debuglink.load_device_by_mnemonic(
            client,
            mnemonic=words_nfkc,
            pin="",
            passphrase_protection=True,
            label="test",
            language="english",
            skip_checksum=True,
        )
        if client.features.model == "T":
            device.apply_settings(client, passphrase_source=PASSPHRASE_ON_HOST)
        client.set_passphrase(passphrase_nfkc)
        address_nfkc = btc.get_address(client, "Bitcoin", [])

        device.wipe(client)
        debuglink.load_device_by_mnemonic(
            client,
            mnemonic=words_nfd,
            pin="",
            passphrase_protection=True,
            label="test",
            language="english",
            skip_checksum=True,
        )
        if client.features.model == "T":
            device.apply_settings(client, passphrase_source=PASSPHRASE_ON_HOST)
        client.set_passphrase(passphrase_nfd)
        address_nfd = btc.get_address(client, "Bitcoin", [])

        assert address_nfkd == address_nfc
        assert address_nfkd == address_nfkc
        assert address_nfkd == address_nfd
Exemple #22
0
def call_sign_tx(client: Client, parameters, input_flow=None):
    client.init_device(new_session=True, derive_cardano=True)

    signing_mode = messages.CardanoTxSigningMode.__members__[
        parameters["signing_mode"]]
    inputs = [cardano.parse_input(i) for i in parameters["inputs"]]
    outputs = [cardano.parse_output(o) for o in parameters["outputs"]]
    certificates = [
        cardano.parse_certificate(c) for c in parameters["certificates"]
    ]
    withdrawals = [
        cardano.parse_withdrawal(w) for w in parameters["withdrawals"]
    ]
    auxiliary_data = cardano.parse_auxiliary_data(parameters["auxiliary_data"])
    mint = cardano.parse_mint(parameters["mint"])
    script_data_hash = cardano.parse_script_data_hash(
        parameters["script_data_hash"])
    collateral_inputs = [
        cardano.parse_collateral_input(i)
        for i in parameters["collateral_inputs"]
    ]
    required_signers = [
        cardano.parse_required_signer(s)
        for s in parameters["required_signers"]
    ]
    collateral_return = (cardano.parse_output(parameters["collateral_return"])
                         if parameters["collateral_return"] is not None else
                         None)
    reference_inputs = [
        cardano.parse_reference_input(i)
        for i in parameters["reference_inputs"]
    ]
    additional_witness_requests = [
        cardano.parse_additional_witness_request(p)
        for p in parameters["additional_witness_requests"]
    ]

    if parameters.get("security_checks") == "prompt":
        device.apply_settings(
            client, safety_checks=messages.SafetyCheckLevel.PromptTemporarily)
    else:
        device.apply_settings(client,
                              safety_checks=messages.SafetyCheckLevel.Strict)

    with client:
        if input_flow is not None:
            client.watch_layout()
            client.set_input_flow(input_flow(client))

        return cardano.sign_tx(
            client=client,
            signing_mode=signing_mode,
            inputs=inputs,
            outputs=outputs,
            fee=parameters["fee"],
            ttl=parameters["ttl"],
            validity_interval_start=parameters["validity_interval_start"],
            certificates=certificates,
            withdrawals=withdrawals,
            protocol_magic=parameters["protocol_magic"],
            network_id=parameters["network_id"],
            auxiliary_data=auxiliary_data,
            mint=mint,
            script_data_hash=script_data_hash,
            collateral_inputs=collateral_inputs,
            required_signers=required_signers,
            collateral_return=collateral_return,
            total_collateral=parameters["total_collateral"],
            reference_inputs=reference_inputs,
            additional_witness_requests=additional_witness_requests,
            include_network_id=parameters["include_network_id"],
        )
Exemple #23
0
def client(request):
    """Client fixture.

    Every test function that requires a client instance will get it from here.
    If we can't connect to a debuggable device, the test will fail.
    If 'skip_t2' is used and TT is connected, the test is skipped. Vice versa with T1
    and 'skip_t1'.

    The client instance is wiped and preconfigured with "all all all..." mnemonic, no
    password and no pin. It is possible to customize this with the `setup_client`
    marker.

    To specify a custom mnemonic and/or custom pin and/or enable passphrase:

    @pytest.mark.setup_client(mnemonic=MY_MNEMONIC, pin="9999", passphrase=True)

    To receive a client instance that was not initialized:

    @pytest.mark.setup_client(uninitialized=True)
    """
    try:
        client = get_device()
    except RuntimeError:
        pytest.fail("No debuggable Trezor is available")

    if request.node.get_closest_marker(
            "skip_t2") and client.features.model == "T":
        pytest.skip("Test excluded on Trezor T")
    if request.node.get_closest_marker(
            "skip_t1") and client.features.model == "1":
        pytest.skip("Test excluded on Trezor 1")

    if (request.node.get_closest_marker("sd_card")
            and not client.features.sd_card_present):
        raise RuntimeError("This test requires SD card.\n"
                           "To skip all such tests, run:\n"
                           "  pytest -m 'not sd_card' <test path>")

    test_ui = request.config.getoption("ui")
    if test_ui not in ("", "record", "test"):
        raise ValueError("Invalid ui option.")
    run_ui_tests = not request.node.get_closest_marker("skip_ui") and test_ui

    client.open()
    if run_ui_tests:
        # we need to reseed before the wipe
        client.debug.reseed(0)

    wipe_device(client)

    setup_params = dict(
        uninitialized=False,
        mnemonic=" ".join(["all"] * 12),
        pin=None,
        passphrase=False,
        needs_backup=False,
        no_backup=False,
    )

    marker = request.node.get_closest_marker("setup_client")
    if marker:
        setup_params.update(marker.kwargs)

    if not setup_params["uninitialized"]:
        if setup_params["pin"] is True:
            setup_params["pin"] = "1234"

        debuglink.load_device(
            client,
            mnemonic=setup_params["mnemonic"],
            pin=setup_params["pin"],
            passphrase_protection=setup_params["passphrase"],
            label="test",
            language="en-US",
            needs_backup=setup_params["needs_backup"],
            no_backup=setup_params["no_backup"],
        )
        if setup_params["passphrase"] and client.features.model != "1":
            apply_settings(client, passphrase_source=PASSPHRASE_ON_HOST)

        if setup_params["pin"]:
            # ClearSession locks the device. We only do that if the PIN is set.
            client.clear_session()

    if run_ui_tests:
        with ui_tests.screen_recording(client, request):
            yield client
    else:
        yield client

    client.close()
Exemple #24
0
def enable_passphrase(hw_session: HwSessionInfo, passphrase_enabled):
    try:
        device.apply_settings(hw_session.hw_client,
                              use_passphrase=passphrase_enabled)
    except exceptions.Cancelled:
        pass
Exemple #25
0
    yield
    client.debug.input(new_pin)


if __name__ == "__main__":
    wirelink = get_device()
    client = TrezorClientDebugLink(wirelink)
    client.open()

    i = 0

    last_pin = None

    while True:
        # set private field
        device.apply_settings(client, use_passphrase=True)
        assert client.features.passphrase_protection is True
        device.apply_settings(client, use_passphrase=False)
        assert client.features.passphrase_protection is False

        # set public field
        label = "".join(random.choices(string.ascii_uppercase + string.digits, k=17))
        device.apply_settings(client, label=label)
        assert client.features.label == label

        # change PIN
        new_pin = "".join(random.choices(string.digits, k=random.randint(6, 10)))
        client.set_input_flow(pin_input_flow(client, last_pin, new_pin))
        device.change_pin(client)
        client.set_input_flow(None)
        last_pin = new_pin
Exemple #26
0
        yield
        client.debug.input(old_pin)
    # enter new pin
    yield
    client.debug.input(new_pin)
    # repeat new pin
    yield
    client.debug.input(new_pin)


if __name__ == "__main__":
    wirelink = get_device()
    client = TrezorClientDebugLink(wirelink)
    client.open()

    i = 0

    last_pin = None

    while True:
        # set private field
        device.apply_settings(client, auto_lock_delay_ms=(i % 10 + 10) * 1000)

        # set public field
        label = "".join(random.choices(string.ascii_uppercase + string.digits, k=17))
        device.apply_settings(client, label=label)
        assert client.features.label == label

        print("iteration %d" % i)
        i = i + 1
Exemple #27
0
    def test_2of5_pin_passphrase(self):
        # 256 bits security, 2 of 5
        mnemonics = [
            "hobo romp academic axis august founder knife legal recover alien expect emphasis loan kitchen involve teacher capture rebuild trial numb spider forward ladle lying voter typical security quantity hawk legs idle leaves gasoline",
            "hobo romp academic agency ancestor industry argue sister scene midst graduate profile numb paid headset airport daisy flame express scene usual welcome quick silent downtown oral critical step remove says rhythm venture aunt",
        ]
        word_count = len(mnemonics[0].split(" "))

        ret = self.client.call_raw(
            proto.RecoveryDevice(passphrase_protection=True,
                                 pin_protection=True,
                                 label="label"))

        # Confirm Recovery
        assert isinstance(ret, proto.ButtonRequest)
        self.client.debug.press_yes()
        ret = self.client.call_raw(proto.ButtonAck())

        # Enter word count
        assert ret == proto.ButtonRequest(
            code=proto.ButtonRequestType.MnemonicWordCount)
        self.client.debug.input(str(word_count))
        ret = self.client.call_raw(proto.ButtonAck())

        # Confirm T9 keyboard
        assert isinstance(ret, proto.ButtonRequest)
        self.client.debug.press_yes()
        ret = self.client.call_raw(proto.ButtonAck())

        # Enter shares
        for mnemonic in mnemonics:
            # Enter mnemonic words
            assert ret == proto.ButtonRequest(
                code=proto.ButtonRequestType.MnemonicInput)
            self.client.transport.write(proto.ButtonAck())
            for word in mnemonic.split(" "):
                time.sleep(1)
                self.client.debug.input(word)
            ret = self.client.transport.read()

            if mnemonic != mnemonics[-1]:
                # Confirm status
                assert isinstance(ret, proto.ButtonRequest)
                self.client.debug.press_yes()
                ret = self.client.call_raw(proto.ButtonAck())

        # Enter PIN for first time
        assert ret == proto.ButtonRequest(code=proto.ButtonRequestType.Other)
        self.client.debug.input("654")
        ret = self.client.call_raw(proto.ButtonAck())

        # Enter PIN for second time
        assert ret == proto.ButtonRequest(code=proto.ButtonRequestType.Other)
        self.client.debug.input("654")
        ret = self.client.call_raw(proto.ButtonAck())

        # Confirm success
        assert isinstance(ret, proto.ButtonRequest)
        self.client.debug.press_yes()
        ret = self.client.call_raw(proto.ButtonAck())

        # Workflow succesfully ended
        assert ret == proto.Success(message="Device recovered")

        # Check mnemonic
        self.client.init_device()
        assert (
            self.client.debug.read_mnemonic_secret().hex() ==
            "b770e0da1363247652de97a39bdbf2463be087848d709ecbf28e84508e31202a")

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

        device.apply_settings(self.client,
                              passphrase_source=PASSPHRASE_ON_HOST)

        # BIP32 Root Key for empty passphrase
        # provided by Andrew, address calculated using T1
        # xprv9s21ZrQH143K2kP9RYJE5AFggTHLs8PbDaaTYtvh238THxDyXqyqQV6H1QpFr3aaQ7CFusFMYyGZ6VcK7aLADyCaCJrszovxtzVZmnRfca4
        address = btc.get_address(self.client, "Bitcoin", [])
        assert address == "1BmqXKM8M1gWA4bgkbPeCtJruRnrY2qYKP"
def test_attack_path_segwit(client):
    # Scenario: The attacker falsely claims that the transaction uses Testnet paths to
    # avoid the path warning dialog, but in step6_sign_segwit_inputs() uses Bitcoin paths
    # to get a valid signature.

    device.apply_settings(
        client, safety_checks=messages.SafetyCheckLevel.PromptTemporarily)

    inp1 = messages.TxInputType(
        # The actual input that the attcker wants to get signed.
        address_n=parse_path("84'/0'/0'/0/0"),
        amount=9426,
        prev_hash=TXHASH_fa80a9,
        prev_index=0,
        script_type=messages.InputScriptType.SPENDWITNESS,
    )
    inp2 = messages.TxInputType(
        # The actual input that the attcker wants to get signed.
        # We need this one to be from a different account, so that the match checker
        # allows the transaction to pass.
        address_n=parse_path("84'/0'/1'/0/1"),
        amount=7086,
        prev_hash=TXHASH_5dfd1b,
        prev_index=0,
        script_type=messages.InputScriptType.SPENDWITNESS,
    )

    out1 = messages.TxOutputType(
        # Attacker's Mainnet address encoded as Testnet.
        address="tb1q694ccp5qcc0udmfwgp692u2s2hjpq5h407urtu",
        script_type=messages.OutputScriptType.PAYTOADDRESS,
        amount=9426 + 7086 - 500,
    )

    attack_count = 6

    def attack_processor(msg):
        nonlocal attack_count
        # Make the inputs look like they are coming from Testnet paths until we reach the
        # signing phase.
        if attack_count > 0 and msg.tx.inputs and msg.tx.inputs[0] in (inp1,
                                                                       inp2):
            attack_count -= 1
            msg.tx.inputs[0].address_n[1] = H_(1)

        return msg

    with client:
        client.set_filter(messages.TxAck, attack_processor)
        client.set_expected_responses([
            # Step: process inputs
            request_input(0),
            # Attacker bypasses warning about non-standard path.
            request_input(1),
            # Attacker bypasses warning about non-standard path.
            # Step: approve outputs
            request_output(0),
            messages.ButtonRequest(code=B.ConfirmOutput),
            messages.ButtonRequest(code=B.SignTx),
            # Step: verify inputs
            request_input(0),
            request_meta(TXHASH_fa80a9),
            request_input(0, TXHASH_fa80a9),
            request_output(0, TXHASH_fa80a9),
            request_output(1, TXHASH_fa80a9),
            request_input(1),
            request_meta(TXHASH_5dfd1b),
            request_input(0, TXHASH_5dfd1b),
            request_output(0, TXHASH_5dfd1b),
            request_output(1, TXHASH_5dfd1b),
            # Step: serialize inputs
            request_input(0),
            request_input(1),
            # Step: serialize outputs
            request_output(0),
            # Step: sign segwit inputs
            request_input(0),
            # Trezor must warn about non-standard path before signing.
            messages.ButtonRequest(code=B.UnknownDerivationPath),
            request_input(1),
            # Trezor must warn about non-standard path before signing.
            messages.ButtonRequest(code=B.UnknownDerivationPath),
            request_finished(),
        ])

        btc.sign_tx(client,
                    "Testnet", [inp1, inp2], [out1],
                    prev_txes=TX_CACHE_MAINNET)
    def test_apply_homescreen(self, client):
        img = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\x00\x00\x00\x00\x04\x80\x00\x00\x00\x00\x00\x00\x00\x00\x04\x88\x02\x00\x00\x00\x02\x91\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x90@\x00\x11@\x00\x00\x00\x00\x00\x00\x08\x00\x10\x92\x12\x04\x00\x00\x05\x12D\x00\x00\x00\x00\x00 \x00\x00\x08\x00Q\x00\x00\x02\xc0\x00\x00\x00\x00\x00\x00\x00\x10\x02 \x01\x04J\x00)$\x00\x00\x00\x00\x80\x00\x00\x00\x00\x08\x10\xa1\x00\x00\x02\x81 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\tP\x00\x00\x00\x00\x00\x00 \x00\x00\xa0\x00\xa0R \x12\x84\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x08\x00\tP\x00\x00\x00\x00 \x00\x04 \x00\x80\x02\x00@\x02T\xc2 \x00\x00\x00\x00\x00\x00\x00\x10@\x00)\t@\n\xa0\x80\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x80@\x14\xa9H\x04\x00\x00\x88@\x00\x00\x00\x00\x00\x02\x02$\x00\x15B@\x00\nP\x00\x00\x00\x00\x00\x80\x00\x00\x91\x01UP\x00\x00 \x02\x00\x00\x00\x00\x00\x00\x02\x08@ Z\xa5 \x00\x00\x80\x00\x00\x00\x00\x00\x00\x08\xa1%\x14*\xa0\x00\x00\x02\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00@\xaa\x91 \x00\x05E\x80\x00\x00\x00\x00\x00\x02*T\x05-D\x00\x00\x05 @\x00\x00\x00\x00\x00%@\x80\x11V\xa0\x88\x00\x05@\xb0\x00\x00\x00\x00\x00\x818$\x04\xabD \x00\x06\xa1T\x00\x00\x00\x00\x02\x03\xb8\x01R\xd5\x01\x00\x00\x05AP\x00\x00\x00\x00\x08\xadT\x00\x05j\xa4@\x00\x87ah\x00\x00\x00\x00\x02\x8d\xb8\x08\x00.\x01\x00\x00\x02\xa5\xa8\x10\x00\x00\x00*\xc1\xec \n\xaa\x88 \x02@\xf6\xd0\x02\x00\x00\x00\x0bB\xb6\x14@U"\x80\x00\x01{`\x00\x00\x00\x00M\xa3\xf8 \x15*\x00\x00\x00\x10n\xc0\x04\x00\x00\x02\x06\xc2\xa8)\x00\x96\x84\x80\x00\x00\x1b\x00\x00\x80@\x10\x87\xa7\xf0\x84\x10\xaa\x10\x00\x00D\x00\x00\x02 \x00\x8a\x06\xfa\xe0P\n-\x02@\x00\x12\x00\x00\x00\x00\x10@\x83\xdf\xa0\x00\x08\xaa@\x00\x00\x01H\x00\x05H\x04\x12\x01\xf7\x81P\x02T\t\x00\x00\x00 \x00\x00\x84\x10\x00\x00z\x00@)* \x00\x00\x01\n\xa0\x02 \x05\n\x00\x00\x05\x10\x84\xa8\x84\x80\x00\x00@\x14\x00\x92\x10\x80\x00\x04\x11@\tT\x00\x00\x00\x00\n@\x00\x08\x84@$\x00H\x00\x12Q\x02\x00\x00\x00\x00\x90\x02A\x12\xa8\n\xaa\x92\x10\x04\xa8\x10@\x00\x00\x04\x04\x00\x04I\x00\x04\x14H\x80"R\x01\x00\x00\x00!@\x00\x00$\xa0EB\x80\x08\x95hH\x00\x00\x00\x84\x10 \x05Z\x00\x00(\x00\x02\x00\xa1\x01\x00\x00\x04\x00@\x82\x00\xadH*\x92P\x00\xaaP\x00\x00\x00\x00\x11\x02\x01*\xad\x01\x00\x01\x01"\x11D\x08\x00\x00\x10\x80 \x00\x81W\x80J\x94\x04\x08\xa5 !\x00\x00\x00\x02\x00B*\xae\xa1\x00\x80\x10\x01\x08\xa4\x00\x00\x00\x00\x00\x84\x00\t[@"HA\x04E\x00\x84\x00\x00\x00\x10\x00\x01J\xd5\x82\x90\x02\x00!\x02\xa2\x00\x00\x00\x00\x00\x00\x00\x05~\xa0\x00 \x10\n)\x00\x11\x00\x00\x00\x00\x00\x00!U\x80\xa8\x88\x82\x80\x01\x00\x00\x00\x00\x00\x00H@\x11\xaa\xc0\x82\x00 *\n\x00\x00\x00\x00\x00\x00\x00\x00\n\xabb@ \x04\x00! \x84\x00\x00\x00\x00\x02@\xa5\x15A$\x04\x81(\n\x00\x00\x00\x00\x00\x00 \x01\x10\x02\xe0\x91\x02\x00\x00\x04\x00\x00\x00\x00\x00\x00\x01 \xa9\tQH@\x91 P\x00\x00\x00\x00\x00\x00\x08\x00\x00\xa0T\xa5\x00@\x80\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\x00\x00\x00\x00\xa2\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00 T\xa0\t\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00@\x02\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00*\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x10\x00\x00\x10\x02\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00@\x04\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x08@\x10\x00\x00\x00\x00'

        with client:
            _set_expected_responses(client)
            device.apply_settings(client, homescreen=img)
Exemple #30
0
        client.debug.input(old_pin)
    # enter new pin
    yield
    client.debug.input(new_pin)
    # repeat new pin
    yield
    client.debug.input(new_pin)


if __name__ == "__main__":
    wirelink = get_device()
    client = TrezorClientDebugLink(wirelink)
    client.open()

    i = 0

    last_pin = None

    while True:
        # set private field
        device.apply_settings(client, auto_lock_delay_ms=(i % 10 + 10) * 1000)

        # set public field
        label = "".join(
            random.choices(string.ascii_uppercase + string.digits, k=17))
        device.apply_settings(client, label=label)
        assert client.features.label == label

        print("iteration %d" % i)
        i = i + 1
Exemple #31
0
def test_attack_path_segwit(client: Client):
    # Scenario: The attacker falsely claims that the transaction uses Testnet paths to
    # avoid the path warning dialog, but in step6_sign_segwit_inputs() uses Bitcoin paths
    # to get a valid signature.

    device.apply_settings(
        client, safety_checks=messages.SafetyCheckLevel.PromptTemporarily)

    # Generate keys
    address_a = btc.get_address(
        client,
        "Testnet",
        parse_path("m/84h/0h/0h/0/0"),
        script_type=messages.InputScriptType.SPENDWITNESS,
    )
    address_b = btc.get_address(
        client,
        "Testnet",
        parse_path("m/84h/0h/1h/0/1"),
        script_type=messages.InputScriptType.SPENDWITNESS,
    )
    prev_hash, prev_tx = forge_prevtx([(address_a, 9_426), (address_b, 7_086)],
                                      network="testnet")

    inp1 = messages.TxInputType(
        # The actual input that the attacker wants to get signed.
        address_n=parse_path("m/84h/0h/0h/0/0"),
        amount=9_426,
        prev_hash=prev_hash,
        prev_index=0,
        script_type=messages.InputScriptType.SPENDWITNESS,
    )
    inp2 = messages.TxInputType(
        # The actual input that the attacker wants to get signed.
        # We need this one to be from a different account, so that the match checker
        # allows the transaction to pass.
        address_n=parse_path("m/84h/0h/1h/0/1"),
        amount=7_086,
        prev_hash=prev_hash,
        prev_index=1,
        script_type=messages.InputScriptType.SPENDWITNESS,
    )

    out1 = messages.TxOutputType(
        # Attacker's Mainnet address encoded as Testnet.
        address="tb1q694ccp5qcc0udmfwgp692u2s2hjpq5h407urtu",
        script_type=messages.OutputScriptType.PAYTOADDRESS,
        amount=9_426 + 7_086 - 500,
    )

    attack_count = 6

    def attack_processor(msg):
        nonlocal attack_count
        # Make the inputs look like they are coming from Testnet paths until we reach the
        # signing phase.
        if attack_count > 0 and msg.tx.inputs and msg.tx.inputs[0] in (inp1,
                                                                       inp2):
            attack_count -= 1
            msg.tx.inputs[0].address_n[1] = H_(1)

        return msg

    with client:
        client.set_filter(messages.TxAck, attack_processor)
        with pytest.raises(TrezorFailure):
            btc.sign_tx(client,
                        "Testnet", [inp1, inp2], [out1],
                        prev_txes={prev_hash: prev_tx})
Exemple #32
0
def test_apply_homescreen_toif_fail(client: Client, toif_data):
    with pytest.raises(exceptions.TrezorFailure), client:
        client.use_pin_sequence([PIN4])
        device.apply_settings(client, homescreen=toif_data)
Exemple #33
0
def client(request, _raw_client):
    """Client fixture.

    Every test function that requires a client instance will get it from here.
    If we can't connect to a debuggable device, the test will fail.
    If 'skip_t2' is used and TT is connected, the test is skipped. Vice versa with T1
    and 'skip_t1'.

    The client instance is wiped and preconfigured with "all all all..." mnemonic, no
    password and no pin. It is possible to customize this with the `setup_client`
    marker.

    To specify a custom mnemonic and/or custom pin and/or enable passphrase:

    @pytest.mark.setup_client(mnemonic=MY_MNEMONIC, pin="9999", passphrase=True)

    To receive a client instance that was not initialized:

    @pytest.mark.setup_client(uninitialized=True)
    """
    if request.node.get_closest_marker(
            "skip_t2") and _raw_client.features.model == "T":
        pytest.skip("Test excluded on Trezor T")
    if request.node.get_closest_marker(
            "skip_t1") and _raw_client.features.model == "1":
        pytest.skip("Test excluded on Trezor 1")

    sd_marker = request.node.get_closest_marker("sd_card")
    if sd_marker and not _raw_client.features.sd_card_present:
        raise RuntimeError("This test requires SD card.\n"
                           "To skip all such tests, run:\n"
                           "  pytest -m 'not sd_card' <test path>")

    test_ui = request.config.getoption("ui")
    run_ui_tests = not request.node.get_closest_marker("skip_ui") and test_ui

    _raw_client.reset_debug_features()
    _raw_client.open()
    try:
        _raw_client.init_device()
    except Exception:
        request.session.shouldstop = "Failed to communicate with Trezor"
        pytest.fail("Failed to communicate with Trezor")

    if run_ui_tests:
        # we need to reseed before the wipe
        _raw_client.debug.reseed(0)

    if sd_marker:
        should_format = sd_marker.kwargs.get("formatted", True)
        _raw_client.debug.erase_sd_card(format=should_format)

    wipe_device(_raw_client)

    setup_params = dict(
        uninitialized=False,
        mnemonic=" ".join(["all"] * 12),
        pin=None,
        passphrase=False,
        needs_backup=False,
        no_backup=False,
    )

    marker = request.node.get_closest_marker("setup_client")
    if marker:
        setup_params.update(marker.kwargs)

    use_passphrase = setup_params["passphrase"] is True or isinstance(
        setup_params["passphrase"], str)

    if not setup_params["uninitialized"]:
        debuglink.load_device(
            _raw_client,
            mnemonic=setup_params["mnemonic"],
            pin=setup_params["pin"],
            passphrase_protection=use_passphrase,
            label="test",
            language="en-US",
            needs_backup=setup_params["needs_backup"],
            no_backup=setup_params["no_backup"],
        )

        if _raw_client.features.model == "T":
            apply_settings(_raw_client, experimental_features=True)

        if use_passphrase and isinstance(setup_params["passphrase"], str):
            _raw_client.use_passphrase(setup_params["passphrase"])

        _raw_client.clear_session()

    if run_ui_tests:
        with ui_tests.screen_recording(_raw_client, request):
            yield _raw_client
    else:
        yield _raw_client

    _raw_client.close()
Exemple #34
0
def test_label_too_long(client: Client):
    with pytest.raises(exceptions.TrezorFailure), client:
        client.set_expected_responses([messages.Failure])
        device.apply_settings(client, label="A" * 33)