def test_safety_checks(self, client):
        BAD_ADDRESS = parse_path("m/0")

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

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

        with client:
            client.set_expected_responses(
                [messages.ButtonRequest(),
                 messages.Address()])
            btc.get_address(client, "Bitcoin", BAD_ADDRESS)

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

        with pytest.raises(exceptions.TrezorFailure,
                           match="Forbidden key path"), client:
            client.set_expected_responses([messages.Failure()])
            btc.get_address(client, "Bitcoin", BAD_ADDRESS)
示例#2
0
    def test_safety_checks(self, client):
        def get_bad_address():
            btc.get_address(client, "Bitcoin", parse_path("m/0"))

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

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

        with client:
            client.set_expected_responses(
                [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.Address()]
            )
            get_bad_address()
示例#3
0
    def test_nonzero_opreturn(self, client):
        inp1 = proto.TxInputType(
            address_n=parse_path("44'/0'/10'/0/5"),
            amount=390000,
            prev_hash=TXHASH_d5f65e,
            prev_index=0,
        )

        out1 = proto.TxOutputType(
            op_return_data=b"test of the op_return data",
            amount=10000,
            script_type=proto.OutputScriptType.PAYTOOPRETURN,
        )

        with client:
            client.set_expected_responses(
                [request_input(0),
                 request_output(0),
                 proto.Failure()])

            with pytest.raises(TrezorFailure,
                               match="OP_RETURN output with non-zero amount"):
                btc.sign_tx(client,
                            "Bitcoin", [inp1], [out1],
                            prev_txes=TX_API)
    def test_attack_amount(self):
        self.setup_mnemonic_allallall()
        self.client.set_tx_api(TxApiBitcoinCash)
        inp1 = proto.TxInputType(
            address_n=self.client.expand_path("44'/145'/0'/1/0"),
            # 1HADRPJpgqBzThepERpVXNi6qRgiLQRNoE
            amount=1896050 - 1,
            prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
            prev_index=0,
            script_type=proto.InputScriptType.SPENDADDRESS,
        )
        inp2 = proto.TxInputType(
            address_n=self.client.expand_path("44'/145'/0'/0/1"),
            # 1LRspCZNFJcbuNKQkXgHMDucctFRQya5a3
            amount=73452,
            prev_hash=unhexlify('502e8577b237b0152843a416f8f1ab0c63321b1be7a8cad7bf5c5c216fcf062c'),
            prev_index=1,
            script_type=proto.InputScriptType.SPENDADDRESS,
        )
        out1 = proto.TxOutputType(
            address='15pnEDZJo3ycPUamqP3tEDnEju1oW5fBCz',
            amount=1934960,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )

        global run_attack
        run_attack = True

        def attack_processor(req, msg):
            import sys
            global run_attack

            if req.details.tx_hash is not None:
                return msg

            if req.request_type != proto.RequestType.TXINPUT:
                return msg

            if req.details.request_index != 0:
                return msg

            if not run_attack:
                return msg

            msg.inputs[0].amount = 1896050
            run_attack = False
            return msg

        with self.client:
            self.client.set_expected_responses([
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=1)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
                proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.Failure(code=proto.FailureType.ProcessError),
            ])
            with pytest.raises(CallException):
                self.client.sign_tx('Bcash', [inp1, inp2], [out1], debug_processor=attack_processor)
def test_change_failed(client):
    assert client.features.pin_protection is True

    # Check current PIN value
    _check_pin(client, PIN4)

    # Let's set new PIN
    def input_flow():
        yield  # do you want to change pin?
        client.debug.press_yes()
        yield  # enter current pin
        client.debug.input(PIN4)
        yield  # enter new pin
        client.debug.input("457891")
        yield  # enter new pin again (but different)
        client.debug.input("381847")

        # failed retry
        yield  # enter current pin again
        client.cancel()

    with client, pytest.raises(Cancelled):
        client.set_expected_responses([messages.ButtonRequest()] * 5 +
                                      [messages.Failure()])
        client.set_input_flow(input_flow)

        device.change_pin(client)

    # Check that there's still old PIN protection
    client.init_device()
    assert client.features.pin_protection is True
    _check_pin(client, PIN4)
def test_invalid_path_fail_asap(client):
    inp1 = messages.TxInputType(
        address_n=parse_path("0"),
        amount=4977040,
        prev_hash=TXHASH_a5cd2a,
        prev_index=0,
        script_type=messages.InputScriptType.SPENDWITNESS,
        sequence=4294967293,
    )

    out1 = messages.TxOutputType(
        address_n=parse_path("84h/0h/0h/1/0"),
        amount=4977040,
        script_type=messages.OutputScriptType.PAYTOWITNESS,
    )

    with client:
        client.set_expected_responses([
            request_input(0),
            messages.Failure(code=messages.FailureType.DataError)
        ])
        try:
            btc.sign_tx(client,
                        "Testnet", [inp1], [out1],
                        prev_txes=TX_CACHE_TESTNET)
        except TrezorFailure:
            pass
示例#7
0
def test_set_wipe_code_mismatch(client):
    # Let's set a wipe code.
    def input_flow():
        yield  # do you want to set the wipe code?
        client.debug.press_yes()
        yield  # enter new wipe code
        client.debug.input(WIPE_CODE4)
        yield  # enter new wipe code again (but different)
        client.debug.input(WIPE_CODE6)

        # failed retry
        yield  # enter new wipe code
        client.cancel()

    with client, pytest.raises(Cancelled):
        client.set_expected_responses(
            [messages.ButtonRequest()] * 4 + [messages.Failure()]
        )
        client.set_input_flow(input_flow)

        device.change_wipe_code(client)

    # Check that there's still no wipe code protection now
    client.init_device()
    assert client.features.wipe_code_protection is False
示例#8
0
    def test_opreturn_address(self, client):
        inp1 = proto.TxInputType(
            address_n=parse_path("44'/0'/0'/0/2"),
            amount=390000,
            prev_hash=TXHASH_d5f65e,
            prev_index=0,
        )

        out1 = proto.TxOutputType(
            address_n=parse_path("44'/0'/0'/1/2"),
            amount=0,
            op_return_data=b"OMNI TRANSACTION GOES HERE",
            script_type=proto.OutputScriptType.PAYTOOPRETURN,
        )

        with client:
            client.set_expected_responses(
                [request_input(0), request_output(0), proto.Failure()]
            )
            with pytest.raises(
                TrezorFailure, match="Output's address_n provided but not expected."
            ):
                _, serialized_tx = btc.sign_tx(
                    client, "Bitcoin", [inp1], [out1], prev_txes=TX_API
                )
    def test_not_enough_funds(self, client):
        # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882
        # input 0: 0.0039 BTC

        inp1 = proto.TxInputType(
            address_n=[0],  # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e
            # amount=390000,
            prev_hash=TXHASH_d5f65e,
            prev_index=0,
        )

        out1 = proto.TxOutputType(
            address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1",
            amount=400000,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )

        trezor_core = client.features.model != "1"
        with client:
            client.set_expected_responses([
                request_input(0),
                (trezor_core,
                 proto.ButtonRequest(code=B.UnknownDerivationPath)),
                request_meta(TXHASH_d5f65e),
                request_input(0, TXHASH_d5f65e),
                request_input(1, TXHASH_d5f65e),
                request_output(0, TXHASH_d5f65e),
                request_output(0),
                proto.ButtonRequest(code=B.ConfirmOutput),
                proto.Failure(code=proto.FailureType.NotEnoughFunds),
            ])
            with pytest.raises(TrezorFailure, match="NotEnoughFunds"):
                btc.sign_tx(client,
                            "Bitcoin", [inp1], [out1],
                            prev_txes=TX_CACHE_MAINNET)
示例#10
0
    def test_not_enough_funds(self, 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,
        )

        out1 = messages.TxOutputType(
            address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1",
            amount=400000,
            script_type=messages.OutputScriptType.PAYTOADDRESS,
        )

        with client:
            client.set_expected_responses([
                request_input(0),
                request_meta(TXHASH_d5f65e),
                request_input(0, TXHASH_d5f65e),
                request_input(1, TXHASH_d5f65e),
                request_output(0, TXHASH_d5f65e),
                request_output(0),
                messages.ButtonRequest(code=B.ConfirmOutput),
                messages.Failure(code=messages.FailureType.NotEnoughFunds),
            ])
            with pytest.raises(TrezorFailure, match="NotEnoughFunds"):
                btc.sign_tx(client,
                            "Bitcoin", [inp1], [out1],
                            prev_txes=TX_CACHE_MAINNET)
示例#11
0
def test_invalid_path_fail_asap(client: Client):
    inp1 = messages.TxInputType(
        address_n=parse_path("m/0"),
        amount=1_000_000,
        prev_hash=b"\x42" * 32,
        prev_index=0,
        script_type=messages.InputScriptType.SPENDWITNESS,
        sequence=4_294_967_293,
    )

    out1 = messages.TxOutputType(
        address_n=parse_path("m/84h/0h/0h/1/0"),
        amount=1_000_000,
        script_type=messages.OutputScriptType.PAYTOWITNESS,
    )

    with client:
        client.set_expected_responses([
            request_input(0),
            messages.Failure(code=messages.FailureType.DataError),
        ])
        try:
            btc.sign_tx(client, "Testnet", [inp1], [out1])
        except TrezorFailure:
            pass
def test_set_failed(client):
    assert client.features.pin_protection is False

    # Check that there's no PIN protection
    _check_no_pin(client)

    # Let's set new PIN
    def input_flow():
        yield  # do you want to set pin?
        client.debug.press_yes()
        yield  # enter new pin
        client.debug.input(PIN4)
        yield  # enter new pin again (but different)
        client.debug.input(PIN6)

        # failed retry
        yield  # enter new pin
        client.cancel()

    with client, pytest.raises(Cancelled):
        client.set_expected_responses([messages.ButtonRequest()] * 4 +
                                      [messages.Failure()])
        client.set_input_flow(input_flow)

        device.change_pin(client)

    # 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_cardano_sign_tx_failed(client, parameters, result):
    inputs = [cardano.create_input(i) for i in parameters["inputs"]]
    outputs = [cardano.create_output(o) for o in parameters["outputs"]]
    certificates = [
        cardano.create_certificate(c) for c in parameters["certificates"]
    ]
    withdrawals = [
        cardano.create_withdrawal(w) for w in parameters["withdrawals"]
    ]

    expected_responses = [messages.PassphraseRequest(), messages.Failure()]

    with client:
        client.set_expected_responses(expected_responses)

        with pytest.raises(TrezorFailure, match=result["error_message"]):
            cardano.sign_tx(
                client=client,
                inputs=inputs,
                outputs=outputs,
                fee=parameters["fee"],
                ttl=parameters["ttl"],
                certificates=certificates,
                withdrawals=withdrawals,
                metadata=bytes.fromhex(parameters["metadata"]),
                protocol_magic=parameters["protocol_magic"],
                network_id=parameters["network_id"],
            )
def test_p2wpkh_with_false_proof(client: Client):
    inp1 = messages.TxInputType(
        # tb1qkvwu9g3k2pdxewfqr7syz89r3gj557l3uuf9r9
        address_n=parse_path("m/84h/1h/0h/0/0"),
        prev_hash=TXHASH_70f987,
        prev_index=0,
        amount=100_000,
        script_type=messages.InputScriptType.SPENDWITNESS,
    )

    inp2 = messages.TxInputType(
        # tb1qldlynaqp0hy4zc2aag3pkenzvxy65saesxw3wd
        # address_n=parse_path("m/84h/1h/0h/0/1"),
        prev_hash=TXHASH_65b768,
        prev_index=0,
        amount=10_000,
        script_type=messages.InputScriptType.EXTERNAL,
        script_pubkey=bytes.fromhex("0014fb7e49f4017dc951615dea221b66626189aa43b9"),
        ownership_proof=bytes.fromhex(
            "534c00190001b0b66657a824e41c063299fb4435dc70a6fd2e9db4c87e3c26a7ab7c0283547b000247304402206e285291aa955cb60b16acd69332eaada67ec5192d361fe4e2b384553e7e80c6022023470cfcb9c3251a136c26eb1637142206785a3d91b98583e5a1d6ab64fa91ed012103dcf3bc936ecb2ec57b8f468050abce8c8756e75fd74273c9977744b1a0be7d03"
        ),
    )

    out1 = messages.TxOutputType(
        address="tb1qnspxpr2xj9s2jt6qlhuvdnxw6q55jvygcf89r2",
        amount=50_000,
        script_type=messages.OutputScriptType.PAYTOWITNESS,
    )

    with client:
        client.set_expected_responses(
            [
                request_input(0),
                request_input(1),
                request_output(0),
                messages.ButtonRequest(code=B.ConfirmOutput),
                messages.ButtonRequest(code=B.SignTx),
                request_input(0),
                request_meta(TXHASH_70f987),
                request_input(0, TXHASH_70f987),
                request_output(0, TXHASH_70f987),
                request_output(1, TXHASH_70f987),
                request_input(1),
                request_meta(TXHASH_65b768),
                request_input(0, TXHASH_65b768),
                request_output(0, TXHASH_65b768),
                request_output(1, TXHASH_65b768),
                messages.Failure(code=messages.FailureType.DataError),
            ]
        )

        with pytest.raises(TrezorFailure, match="Invalid external input"):
            btc.sign_tx(
                client,
                "Testnet",
                [inp1, inp2],
                [out1],
                prev_txes=TX_CACHE_TESTNET,
            )
示例#15
0
    def test_nonzero_opreturn(self):
        self.setup_mnemonic_allallall()

        inp1 = proto.TxInputType(
            address_n=parse_path("44'/0'/10'/0/5"),
            prev_hash=TXHASH_d5f65e,
            prev_index=0,
        )

        out1 = proto.TxOutputType(
            op_return_data=b"test of the op_return data",
            amount=10000,
            script_type=proto.OutputScriptType.PAYTOOPRETURN,
        )

        with self.client:
            self.client.set_expected_responses([
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXMETA,
                    details=proto.TxRequestDetailsType(tx_hash=TXHASH_d5f65e),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0,
                                                       tx_hash=TXHASH_d5f65e),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=1,
                                                       tx_hash=TXHASH_d5f65e),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0,
                                                       tx_hash=TXHASH_d5f65e),
                ),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0),
                ),
                proto.Failure(),
            ])

            with pytest.raises(CallException) as exc:
                btc.sign_tx(self.client,
                            "Bitcoin", [inp1], [out1],
                            prev_txes=TX_API)

            if TREZOR_VERSION == 1:
                assert exc.value.args[0] == proto.FailureType.ProcessError
                assert exc.value.args[1].endswith("Failed to compile output")
            else:
                assert exc.value.args[0] == proto.FailureType.DataError
                assert exc.value.args[1].endswith(
                    "OP_RETURN output with non-zero amount")
示例#16
0
def test_p2wpkh_with_false_proof(client):
    inp1 = messages.TxInputType(
        # tb1qkvwu9g3k2pdxewfqr7syz89r3gj557l3uuf9r9
        address_n=parse_path("m/84h/1h/0h/0/0"),
        prev_hash=TXHASH_70f987,
        prev_index=0,
        amount=100000,
        script_type=messages.InputScriptType.SPENDWITNESS,
    )

    inp2 = messages.TxInputType(
        # tb1qldlynaqp0hy4zc2aag3pkenzvxy65saesxw3wd
        # address_n=parse_path("m/84h/1h/0h/0/1"),
        prev_hash=TXHASH_65b768,
        prev_index=0,
        amount=10000,
        script_type=messages.InputScriptType.EXTERNAL,
        script_pubkey=bytes.fromhex(
            "0014fb7e49f4017dc951615dea221b66626189aa43b9"),
        ownership_proof=bytes.fromhex(
            "534c00190001b0b66657a824e41c063299fb4435dc70a6fd2e9db4c87e3c26a7ab7c0283547b0002473044022060bf60380142ed54fa907c82cb5ab438bfec22ebf8b5a92971fe104b7e3dd41002206f3fc4ac2f9c1a4a12255b5f678b6e57a088816051faea5a65a66951b394c150012103dcf3bc936ecb2ec57b8f468050abce8c8756e75fd74273c9977744b1a0be7d03"
        ),
    )

    out1 = messages.TxOutputType(
        address="tb1qnspxpr2xj9s2jt6qlhuvdnxw6q55jvygcf89r2",
        amount=50000,
        script_type=messages.OutputScriptType.PAYTOWITNESS,
    )

    with client:
        client.set_expected_responses([
            request_input(0),
            request_input(1),
            request_output(0),
            messages.ButtonRequest(code=B.ConfirmOutput),
            messages.ButtonRequest(code=B.SignTx),
            request_input(0),
            request_meta(TXHASH_70f987),
            request_input(0, TXHASH_70f987),
            request_output(0, TXHASH_70f987),
            request_output(1, TXHASH_70f987),
            request_input(1),
            request_meta(TXHASH_65b768),
            request_input(0, TXHASH_65b768),
            request_output(0, TXHASH_65b768),
            request_output(1, TXHASH_65b768),
            messages.Failure(code=messages.FailureType.DataError),
        ])

        with pytest.raises(TrezorFailure, match="Invalid external input"):
            btc.sign_tx(
                client,
                "Testnet",
                [inp1, inp2],
                [out1],
                prev_txes=TX_CACHE_TESTNET,
            )
示例#17
0
def test_cancel_message_via_cancel(client, message):
    def input_flow():
        yield
        client.cancel()

    with client, pytest.raises(Cancelled):
        client.set_expected_responses([m.ButtonRequest(), m.Failure()])
        client.set_input_flow(input_flow)
        client.call(message)
示例#18
0
def _check_wipe_code(client, pin, wipe_code):
    client.init_device()
    assert client.features.wipe_code_protection is True

    # Try to change the PIN to the current wipe code value. The operation should fail.
    with client, pytest.raises(TrezorFailure):
        client.use_pin_sequence([pin, wipe_code, wipe_code])
        client.set_expected_responses(
            [messages.ButtonRequest()] * 5 +
            [messages.Failure(code=messages.FailureType.PinInvalid)])
        device.change_pin(client)
    def test_attack_change_input(self):
        self.setup_mnemonic_allallall()
        self.client.set_tx_api(TxApiBitcoinGold)
        inp1 = proto.TxInputType(
            address_n=self.client.expand_path("44'/156'/1000'/0/0"),
            # 1MH9KKcvdCTY44xVDC2k3fjBbX5Cz29N1q
            amount=1995344,
            prev_hash=unhexlify('25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985'),
            prev_index=0,
            script_type=proto.InputScriptType.SPENDADDRESS,
        )
        out1 = proto.TxOutputType(
            address_n=self.client.expand_path("44'/156'/1000'/1/0"),
            amount=1896050,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )
        out2 = proto.TxOutputType(
            address='GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe',
            amount=73452,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )

        global attack_ctr
        attack_ctr = 0

        def attack_processor(req, msg):
            import sys
            global attack_ctr

            if req.details.tx_hash is not None:
                return msg

            if req.request_type != proto.RequestType.TXINPUT:
                return msg

            attack_ctr += 1
            if attack_ctr <= 1:
                return msg

            msg.inputs[0].address_n[2] = 1 + 0x80000000
            return msg

        with self.client:
            self.client.set_expected_responses([
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)),
                proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
                proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.Failure(code=proto.FailureType.ProcessError),
            ])
            with pytest.raises(CallException):
                self.client.sign_tx('Bitcoin Gold', [inp1], [out1, out2], debug_processor=attack_processor)
    def test_attack_change_input(self):
        self.setup_mnemonic_allallall()
        self.client.set_tx_api(TxApiBitcoinCash)
        inp1 = proto.TxInputType(
            address_n=self.client.expand_path("44'/145'/1000'/0/0"),
            # 1MH9KKcvdCTY44xVDC2k3fjBbX5Cz29N1q
            amount=1995344,
            prev_hash=unhexlify('bc37c28dfb467d2ecb50261387bf752a3977d7e5337915071bb4151e6b711a78'),
            prev_index=0,
            script_type=proto.InputScriptType.SPENDADDRESS,
        )
        out1 = proto.TxOutputType(
            address_n=self.client.expand_path("44'/145'/1000'/1/0"),
            amount=1896050,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )
        out2 = proto.TxOutputType(
            address='1LRspCZNFJcbuNKQkXgHMDucctFRQya5a3',
            amount=73452,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )

        global attack_ctr
        attack_ctr = 0

        def attack_processor(req, msg):
            import sys
            global attack_ctr

            if req.details.tx_hash is not None:
                return msg

            if req.request_type != proto.RequestType.TXINPUT:
                return msg

            attack_ctr += 1
            if attack_ctr <= 1:
                return msg

            msg.inputs[0].address_n[2] = 1 + 0x80000000
            return msg

        with self.client:
            self.client.set_expected_responses([
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT, details=proto.TxRequestDetailsType(request_index=1)),
                proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
                proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
                proto.TxRequest(request_type=proto.RequestType.TXINPUT, details=proto.TxRequestDetailsType(request_index=0)),
                proto.Failure(code=proto.FailureType.ProcessError),
            ])
            with pytest.raises(CallException):
                self.client.sign_tx('Bcash', [inp1], [out1, out2], debug_processor=attack_processor)
示例#21
0
def test_attack_change_input(client: Client):
    # NOTE: fake input tx used

    inp1 = messages.TxInputType(
        address_n=parse_path("m/44h/156h/0h/0/0"),
        amount=1_252_382_934,
        prev_hash=FAKE_TXHASH_6f0398,
        prev_index=0,
        script_type=messages.InputScriptType.SPENDADDRESS,
    )
    out1 = messages.TxOutputType(
        address_n=parse_path("m/44h/156h/0h/1/0"),
        amount=1_896_050,
        script_type=messages.OutputScriptType.PAYTOADDRESS,
    )
    out2 = messages.TxOutputType(
        address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
        amount=1_252_382_934 - 1_896_050 - 1_000,
        script_type=messages.OutputScriptType.PAYTOADDRESS,
    )

    attack_count = 2

    def attack_processor(msg):
        nonlocal attack_count

        if msg.tx.inputs and msg.tx.inputs[0] == inp1:
            if attack_count > 0:
                attack_count -= 1
            else:
                msg.tx.inputs[0].address_n[2] = H_(1)

        return msg

    with client:
        client.set_filter(messages.TxAck, attack_processor)
        client.set_expected_responses([
            request_input(0),
            request_output(0),
            request_output(1),
            messages.ButtonRequest(code=B.ConfirmOutput),
            messages.ButtonRequest(code=B.SignTx),
            request_input(0),
            request_meta(FAKE_TXHASH_6f0398),
            request_input(0, FAKE_TXHASH_6f0398),
            request_output(0, FAKE_TXHASH_6f0398),
            request_output(1, FAKE_TXHASH_6f0398),
            request_input(0),
            messages.Failure(code=messages.FailureType.ProcessError),
        ])
        with pytest.raises(TrezorFailure):
            btc.sign_tx(client,
                        "Bgold", [inp1], [out1, out2],
                        prev_txes=TX_API)
示例#22
0
def test_apply_auto_lock_delay_out_of_range(client, seconds):
    with client:
        client.use_pin_sequence([PIN4])
        client.set_expected_responses([
            pin_request(client),
            messages.Failure(code=messages.FailureType.ProcessError),
        ])

        delay = seconds * 1000
        with pytest.raises(TrezorFailure):
            device.apply_settings(client, auto_lock_delay_ms=delay)
示例#23
0
def test_attack_change_input(client: Client):
    # NOTE: fake input tx used

    inp1 = messages.TxInputType(
        address_n=parse_path("m/44h/145h/10h/0/0"),
        amount=1_995_344,
        prev_hash=FAKE_TXHASH_bd32ff,
        prev_index=0,
        script_type=messages.InputScriptType.SPENDADDRESS,
    )
    out1 = messages.TxOutputType(
        address_n=parse_path("m/44h/145h/10h/1/0"),
        amount=1_896_050,
        script_type=messages.OutputScriptType.PAYTOADDRESS,
    )
    out2 = messages.TxOutputType(
        address="bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4",
        amount=73_452,
        script_type=messages.OutputScriptType.PAYTOADDRESS,
    )

    attack_count = 2

    def attack_processor(msg):
        nonlocal attack_count

        if msg.tx.inputs and msg.tx.inputs[0] == inp1:
            if attack_count > 0:
                attack_count -= 1
            else:
                msg.tx.inputs[0].address_n[2] = H_(1)

        return msg

    with client:
        client.set_filter(messages.TxAck, attack_processor)
        client.set_expected_responses([
            request_input(0),
            request_output(0),
            request_output(1),
            messages.ButtonRequest(code=B.ConfirmOutput),
            messages.ButtonRequest(code=B.SignTx),
            request_input(0),
            request_meta(FAKE_TXHASH_bd32ff),
            request_input(0, FAKE_TXHASH_bd32ff),
            request_output(0, FAKE_TXHASH_bd32ff),
            request_input(0),
            messages.Failure(code=messages.FailureType.ProcessError),
        ])
        with pytest.raises(TrezorFailure):
            btc.sign_tx(client,
                        "Bcash", [inp1], [out1, out2],
                        prev_txes=TX_API)
示例#24
0
def _check_wipe_code(client, pin, wipe_code):
    client.clear_session()
    assert client.features.wipe_code_protection is True

    # Try to change the PIN to the current wipe code value. The operation should fail.
    with client, pytest.raises(TrezorFailure):
        client.set_expected_responses(
            [messages.ButtonRequest()] * 5
            + [messages.Failure(code=messages.FailureType.PinInvalid)]
        )
        client.set_input_flow(_input_flow_change_pin(client.debug, pin, wipe_code))
        device.change_pin(client)
示例#25
0
    def test_attack_change_input(self, client):
        inp1 = proto.TxInputType(
            address_n=parse_path("44'/156'/11'/0/0"),
            amount=1252382934,
            prev_hash=TXHASH_25526b,
            prev_index=0,
            script_type=proto.InputScriptType.SPENDADDRESS,
        )
        out1 = proto.TxOutputType(
            address_n=parse_path("44'/156'/11'/1/0"),
            amount=1896050,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )
        out2 = proto.TxOutputType(
            address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
            amount=1252382934 - 1896050 - 1000,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )

        attack_count = 2

        def attack_processor(msg):
            nonlocal attack_count

            if msg.tx.inputs and msg.tx.inputs[0] == inp1:
                if attack_count > 0:
                    attack_count -= 1
                else:
                    msg.tx.inputs[0].address_n[2] = H_(1)

            return msg

        client.set_filter(proto.TxAck, attack_processor)
        with client:
            client.set_expected_responses([
                request_input(0),
                request_output(0),
                request_output(1),
                proto.ButtonRequest(code=B.ConfirmOutput),
                proto.ButtonRequest(code=B.SignTx),
                request_input(0),
                request_meta(TXHASH_25526b),
                request_input(0, TXHASH_25526b),
                request_output(0, TXHASH_25526b),
                request_output(1, TXHASH_25526b),
                request_input(0),
                proto.Failure(code=proto.FailureType.ProcessError),
            ])
            with pytest.raises(TrezorFailure):
                btc.sign_tx(client,
                            "Bgold", [inp1], [out1, out2],
                            prev_txes=TX_API)
示例#26
0
    def test_attack_change_input(self, client):
        inp1 = proto.TxInputType(
            address_n=parse_path("44'/145'/10'/0/0"),
            amount=1995344,
            prev_hash=TXHASH_bc37c2,
            prev_index=0,
            script_type=proto.InputScriptType.SPENDADDRESS,
        )
        out1 = proto.TxOutputType(
            address_n=parse_path("44'/145'/10'/1/0"),
            amount=1896050,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )
        out2 = proto.TxOutputType(
            address="bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4",
            amount=73452,
            script_type=proto.OutputScriptType.PAYTOADDRESS,
        )

        attack_count = 2

        def attack_processor(msg):
            nonlocal attack_count

            if msg.tx.inputs and msg.tx.inputs[0] == inp1:
                if attack_count > 0:
                    attack_count -= 1
                else:
                    msg.tx.inputs[0].address_n[2] = H_(1)

            return msg

        client.set_filter(proto.TxAck, attack_processor)

        with client:
            client.set_expected_responses([
                request_input(0),
                request_output(0),
                request_output(1),
                proto.ButtonRequest(code=B.ConfirmOutput),
                proto.ButtonRequest(code=B.SignTx),
                request_input(0),
                request_meta(TXHASH_bc37c2),
                request_input(0, TXHASH_bc37c2),
                request_output(0, TXHASH_bc37c2),
                request_input(0),
                proto.Failure(code=proto.FailureType.ProcessError),
            ])
            with pytest.raises(TrezorFailure):
                btc.sign_tx(client,
                            "Bcash", [inp1], [out1, out2],
                            prev_txes=TX_API)
示例#27
0
    def test_nonzero_opreturn(self):
        self.setup_mnemonic_nopin_nopassphrase()

        # tx: d5f65ee80147b4bcc70b75e4bbf2d7382021b871bd8867ef8fa525ef50864882
        # input 0: 0.0039 BTC

        inp1 = proto.TxInputType(
            address_n=[0],  # 14LmW5k4ssUrtbAB4255zdqv3b4w1TuX9e
            # amount=390000,
            prev_hash=TXHASH_d5f65e,
            prev_index=0,
        )

        out1 = proto.TxOutputType(
            op_return_data=b'test of the op_return data',
            amount=10000,
            script_type=proto.OutputScriptType.PAYTOOPRETURN,
        )

        with self.client:
            self.client.set_expected_responses([
                proto.TxRequest(
                    request_type=proto.RequestType.TXINPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXMETA,
                    details=proto.TxRequestDetailsType(tx_hash=TXHASH_d5f65e)),
                proto.TxRequest(request_type=proto.RequestType.TXINPUT,
                                details=proto.TxRequestDetailsType(
                                    request_index=0, tx_hash=TXHASH_d5f65e)),
                proto.TxRequest(request_type=proto.RequestType.TXINPUT,
                                details=proto.TxRequestDetailsType(
                                    request_index=1, tx_hash=TXHASH_d5f65e)),
                proto.TxRequest(request_type=proto.RequestType.TXOUTPUT,
                                details=proto.TxRequestDetailsType(
                                    request_index=0, tx_hash=TXHASH_d5f65e)),
                proto.TxRequest(
                    request_type=proto.RequestType.TXOUTPUT,
                    details=proto.TxRequestDetailsType(request_index=0)),
                proto.Failure()
            ])

            with pytest.raises(CallException) as exc:
                self.client.sign_tx('Bitcoin', [inp1], [out1])

            if TREZOR_VERSION == 1:
                assert exc.value.args[0] == proto.FailureType.ProcessError
                assert exc.value.args[1].endswith("Failed to compile output")
            else:
                assert exc.value.args[0] == proto.FailureType.DataError
                assert exc.value.args[1].endswith(
                    'OP_RETURN output with non-zero amount')
示例#28
0
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_cardano_sign_tx_validation(client, protocol_magic, inputs, outputs,
                                    transactions, expected_error_message):
    inputs = [cardano.create_input(i) for i in inputs]
    outputs = [cardano.create_output(o) for o in outputs]

    expected_responses = [
        messages.CardanoTxRequest(tx_index=i) for i in range(len(transactions))
    ]
    expected_responses += [messages.Failure()]

    with client:
        client.set_expected_responses(expected_responses)

        with pytest.raises(TrezorFailure, match=expected_error_message):
            cardano.sign_tx(client, inputs, outputs, transactions,
                            protocol_magic)
示例#30
0
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.set_input_flow(_input_flow_set_wipe_code(client.debug, None, 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.set_input_flow(_input_flow_set_pin(client.debug, WIPE_CODE4))
        device.change_pin(client)