1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-22 07:28:10 +00:00

remove ping.passphrase/pin

This commit is contained in:
Tomas Susanka 2020-01-21 09:05:48 +00:00 committed by Pavol Rusnak
parent 48fe192103
commit a3f3d4fcdb
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
17 changed files with 128 additions and 290 deletions

View File

@ -173,8 +173,6 @@ message SdProtect {
message Ping {
optional string message = 1; // message to send back in Success message
optional bool button_protection = 2; // ask for button press
optional bool pin_protection = 3; // ask for PIN if set in device
optional bool passphrase_protection = 4; // ask for passphrase if set in device
}
/**

View File

@ -104,10 +104,6 @@ async def handle_Ping(ctx: wire.Context, msg: Ping) -> Success:
from trezor.ui.text import Text
await require_confirm(ctx, Text("Confirm"), ProtectCall)
if msg.passphrase_protection: # TODO
from apps.common import passphrase
await passphrase.get(ctx)
return Success(message=msg.message)

View File

@ -17,19 +17,13 @@ class Ping(p.MessageType):
self,
message: str = None,
button_protection: bool = None,
pin_protection: bool = None,
passphrase_protection: bool = None,
) -> None:
self.message = message
self.button_protection = button_protection
self.pin_protection = pin_protection
self.passphrase_protection = passphrase_protection
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('message', p.UnicodeType, 0),
2: ('button_protection', p.BoolType, 0),
3: ('pin_protection', p.BoolType, 0),
4: ('passphrase_protection', p.BoolType, 0),
}

View File

@ -122,19 +122,6 @@ void fsm_msgPing(const Ping *msg) {
}
}
if (msg->has_pin_protection && msg->pin_protection) {
CHECK_PIN
}
if (msg->has_passphrase_protection && msg->passphrase_protection) {
char dummy[51];
if (!protectPassphrase(dummy)) {
fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL);
return;
}
memzero(&dummy, sizeof(dummy));
}
if (msg->has_message) {
resp->has_message = true;
memcpy(&(resp->message), &(msg->message), sizeof(resp->message));

View File

@ -221,17 +221,10 @@ def version():
@cli.command()
@click.argument("message")
@click.option("-b", "--button-protection", is_flag=True)
@click.option("-p", "--pin-protection", is_flag=True)
@click.option("-r", "--passphrase-protection", is_flag=True)
@click.pass_obj
def ping(connect, message, button_protection, pin_protection, passphrase_protection):
def ping(connect, message, button_protection):
"""Send ping message."""
return connect().ping(
message,
button_protection=button_protection,
pin_protection=pin_protection,
passphrase_protection=passphrase_protection,
)
return connect().ping(message, button_protection=button_protection,)
@cli.command()

View File

@ -266,17 +266,13 @@ class TrezorClient:
@tools.expect(messages.Success, field="message")
def ping(
self,
msg,
button_protection=False,
pin_protection=False,
passphrase_protection=False,
self, msg, button_protection=False,
):
# We would like ping to work on any valid TrezorClient instance, but
# due to the protection modes, we need to go through self.call, and that will
# raise an exception if the firmware is too old.
# So we short-circuit the simplest variant of ping with call_raw.
if not button_protection and not pin_protection and not passphrase_protection:
if not button_protection:
# XXX this should be: `with self:`
try:
self.open()
@ -284,12 +280,7 @@ class TrezorClient:
finally:
self.close()
msg = messages.Ping(
message=msg,
button_protection=button_protection,
pin_protection=pin_protection,
passphrase_protection=passphrase_protection,
)
msg = messages.Ping(message=msg, button_protection=button_protection,)
return self.call(msg)
def get_device_id(self):

View File

@ -17,19 +17,13 @@ class Ping(p.MessageType):
self,
message: str = None,
button_protection: bool = None,
pin_protection: bool = None,
passphrase_protection: bool = None,
) -> None:
self.message = message
self.button_protection = button_protection
self.pin_protection = pin_protection
self.passphrase_protection = passphrase_protection
@classmethod
def get_fields(cls) -> Dict:
return {
1: ('message', p.UnicodeType, 0),
2: ('button_protection', p.BoolType, 0),
3: ('pin_protection', p.BoolType, 0),
4: ('passphrase_protection', p.BoolType, 0),
}

View File

@ -34,7 +34,7 @@ class TestDebuglink:
@pytest.mark.setup_client(mnemonic=MNEMONIC12, pin="1234", passphrase=True)
def test_pin(self, client):
resp = client.call_raw(messages.Ping(message="test", pin_protection=True))
resp = client.call_raw(messages.GetAddress(address_n=[], coin_name="Testnet"))
assert isinstance(resp, messages.PinMatrixRequest)
pin, matrix = client.debug.read_pin()
@ -43,4 +43,7 @@ class TestDebuglink:
pin_encoded = client.debug.read_pin_encoded()
resp = client.call_raw(messages.PinMatrixAck(pin=pin_encoded))
assert isinstance(resp, messages.Success)
assert isinstance(resp, messages.PassphraseRequest)
resp = client.call_raw(messages.PassphraseAck(passphrase=""))
assert isinstance(resp, messages.Address)

View File

@ -18,7 +18,7 @@ import time
import pytest
from trezorlib import device, messages as proto
from trezorlib import btc, device, messages as proto
EXPECTED_RESPONSES_NOPIN = [proto.ButtonRequest(), proto.Success(), proto.Features()]
EXPECTED_RESPONSES_PIN = [proto.PinMatrixRequest()] + EXPECTED_RESPONSES_NOPIN
@ -91,13 +91,13 @@ class TestMsgApplysettings:
time.sleep(0.1) # sleep less than auto-lock delay
with client:
# No PIN protection is required.
client.set_expected_responses([proto.Success()])
client.ping(msg="", pin_protection=True)
client.set_expected_responses([proto.Address()])
btc.get_address(client, "Testnet", [0])
time.sleep(10.1) # sleep more than auto-lock delay
with client:
client.set_expected_responses([proto.PinMatrixRequest(), proto.Success()])
client.ping(msg="", pin_protection=True)
client.set_expected_responses([proto.PinMatrixRequest(), proto.Address()])
btc.get_address(client, "Testnet", [0])
@pytest.mark.skip_t2
def test_apply_minimal_auto_lock_delay(self, client):
@ -114,16 +114,16 @@ class TestMsgApplysettings:
time.sleep(0.1) # sleep less than auto-lock delay
with client:
# No PIN protection is required.
client.set_expected_responses([proto.Success()])
client.ping(msg="", pin_protection=True)
client.set_expected_responses([proto.Address()])
btc.get_address(client, "Testnet", [0])
time.sleep(2) # sleep less than the minimal auto-lock delay
with client:
# No PIN protection is required.
client.set_expected_responses([proto.Success()])
client.ping(msg="", pin_protection=True)
client.set_expected_responses([proto.Address()])
btc.get_address(client, "Testnet", [0])
time.sleep(10.1) # sleep more than the minimal auto-lock delay
with client:
client.set_expected_responses([proto.PinMatrixRequest(), proto.Success()])
client.ping(msg="", pin_protection=True)
client.set_expected_responses([proto.PinMatrixRequest(), proto.Address()])
btc.get_address(client, "Testnet", [0])

View File

@ -225,5 +225,5 @@ def test_set_pin_to_wipe_code(client):
# Check that there is no PIN protection.
client.init_device()
assert client.features.pin_protection is False
ret = client.call_raw(messages.Ping(pin_protection=True))
assert isinstance(ret, messages.Success)
resp = client.call_raw(messages.GetAddress())
assert isinstance(resp, messages.Address)

View File

@ -29,8 +29,8 @@ class TestMsgChangepin:
assert features.pin_protection is False
# Check that there's no PIN protection
ret = client.call_raw(proto.Ping(pin_protection=True))
assert isinstance(ret, proto.Success)
ret = client.call_raw(proto.GetAddress())
assert isinstance(ret, proto.Address)
# Let's set new PIN
ret = client.call_raw(proto.ChangePin())
@ -66,7 +66,7 @@ class TestMsgChangepin:
assert features.pin_protection is True
# Check that there's PIN protection
ret = client.call_raw(proto.Ping(pin_protection=True))
ret = client.call_raw(proto.GetAddress())
assert isinstance(ret, proto.PinMatrixRequest)
client.call_raw(proto.Cancel())
@ -112,7 +112,7 @@ class TestMsgChangepin:
assert features.pin_protection is True
# Check that there's PIN protection
ret = client.call_raw(proto.Ping(pin_protection=True))
ret = client.call_raw(proto.GetAddress())
assert isinstance(ret, proto.PinMatrixRequest)
client.call_raw(proto.Cancel())
@ -135,16 +135,16 @@ class TestMsgChangepin:
# Check that there's no PIN protection now
features = client.call_raw(proto.Initialize())
assert features.pin_protection is False
ret = client.call_raw(proto.Ping(pin_protection=True))
assert isinstance(ret, proto.Success)
ret = client.call_raw(proto.GetAddress())
assert isinstance(ret, proto.Address)
def test_set_failed(self, client):
features = client.call_raw(proto.Initialize())
assert features.pin_protection is False
# Check that there's no PIN protection
ret = client.call_raw(proto.Ping(pin_protection=True))
assert isinstance(ret, proto.Success)
ret = client.call_raw(proto.GetAddress())
assert isinstance(ret, proto.Address)
# Let's set new PIN
ret = client.call_raw(proto.ChangePin())
@ -170,8 +170,8 @@ class TestMsgChangepin:
# Check that there's still no PIN protection now
features = client.call_raw(proto.Initialize())
assert features.pin_protection is False
ret = client.call_raw(proto.Ping(pin_protection=True))
assert isinstance(ret, proto.Success)
ret = client.call_raw(proto.GetAddress())
assert isinstance(ret, proto.Address)
@pytest.mark.setup_client(pin=True)
def test_set_failed_2(self, client):
@ -211,8 +211,8 @@ class TestMsgChangepin:
def check_pin(self, client, pin):
client.clear_session()
ret = client.call_raw(proto.Ping(pin_protection=True))
ret = client.call_raw(proto.GetAddress())
assert isinstance(ret, proto.PinMatrixRequest)
pin_encoded = client.debug.encode_pin(pin)
ret = client.call_raw(proto.PinMatrixAck(pin=pin_encoded))
assert isinstance(ret, proto.Success)
assert isinstance(ret, proto.Address)

View File

@ -17,77 +17,64 @@
import pytest
from trezorlib import messages as proto
from trezorlib.btc import get_public_node
from trezorlib.tools import parse_path
@pytest.mark.skip_t2
class TestMsgClearsession:
@pytest.mark.setup_client(pin=True, passphrase=True)
def test_clearsession(self, client):
with client:
client.set_expected_responses(
[
proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall),
proto.PinMatrixRequest(),
proto.PassphraseRequest(),
proto.Success(),
]
)
res = client.ping(
"random data",
button_protection=True,
pin_protection=True,
passphrase_protection=True,
)
assert res == "random data"
@pytest.mark.skip_ui
@pytest.mark.setup_client(pin=True, passphrase=True)
def test_clear_session(client):
if client.features.model == "1":
init_responses = [
proto.PinMatrixRequest(),
proto.PassphraseRequest(),
]
else:
init_responses = [
proto.PassphraseRequest(),
]
cached_responses = [
proto.ButtonRequest(code=proto.ButtonRequestType.PublicKey),
proto.PublicKey(),
]
with client:
# pin and passphrase are cached
client.set_expected_responses(
[
proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall),
proto.Success(),
]
)
res = client.ping(
"random data",
button_protection=True,
pin_protection=True,
passphrase_protection=True,
)
assert res == "random data"
with client:
client.set_expected_responses(init_responses + cached_responses)
assert (
get_public_node(
client, parse_path("44'/0'/0'"), show_display=True
).node.public_key.hex()
== "03c8166eb40ac84088b618ec07c7cebadacee31c5f5b04a1e8c2a2f3e748eb2cdd"
)
client.clear_session()
with client:
# pin and passphrase are cached
client.set_expected_responses(cached_responses)
assert (
get_public_node(
client, parse_path("44'/0'/0'"), show_display=True
).node.public_key.hex()
== "03c8166eb40ac84088b618ec07c7cebadacee31c5f5b04a1e8c2a2f3e748eb2cdd"
)
# session cache is cleared
with client:
client.set_expected_responses(
[
proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall),
proto.PinMatrixRequest(),
proto.PassphraseRequest(),
proto.Success(),
]
)
res = client.ping(
"random data",
button_protection=True,
pin_protection=True,
passphrase_protection=True,
)
assert res == "random data"
client.clear_session()
with client:
# pin and passphrase are cached
client.set_expected_responses(
[
proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall),
proto.Success(),
]
)
res = client.ping(
"random data",
button_protection=True,
pin_protection=True,
passphrase_protection=True,
)
assert res == "random data"
# session cache is cleared
with client:
client.set_expected_responses(init_responses + cached_responses)
assert (
get_public_node(
client, parse_path("44'/0'/0'"), show_display=True
).node.public_key.hex()
== "03c8166eb40ac84088b618ec07c7cebadacee31c5f5b04a1e8c2a2f3e748eb2cdd"
)
with client:
# pin and passphrase are cached
client.set_expected_responses(cached_responses)
assert (
get_public_node(
client, parse_path("44'/0'/0'"), show_display=True
).node.public_key.hex()
== "03c8166eb40ac84088b618ec07c7cebadacee31c5f5b04a1e8c2a2f3e748eb2cdd"
)

View File

@ -19,8 +19,8 @@ import pytest
from trezorlib import messages as proto
@pytest.mark.skip_t2
class TestMsgPing:
@pytest.mark.skip_ui
@pytest.mark.setup_client(pin=True, passphrase=True)
def test_ping(self, client):
with client:
@ -37,48 +37,3 @@ class TestMsgPing:
)
res = client.ping("random data", button_protection=True)
assert res == "random data"
with client:
client.set_expected_responses([proto.PinMatrixRequest(), proto.Success()])
res = client.ping("random data", pin_protection=True)
assert res == "random data"
with client:
client.set_expected_responses([proto.PassphraseRequest(), proto.Success()])
res = client.ping("random data", passphrase_protection=True)
assert res == "random data"
@pytest.mark.setup_client(pin=True, passphrase=True)
def test_ping_caching(self, client):
with client:
client.set_expected_responses(
[
proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall),
proto.PinMatrixRequest(),
proto.PassphraseRequest(),
proto.Success(),
]
)
res = client.ping(
"random data",
button_protection=True,
pin_protection=True,
passphrase_protection=True,
)
assert res == "random data"
with client:
# pin and passphrase are cached
client.set_expected_responses(
[
proto.ButtonRequest(code=proto.ButtonRequestType.ProtectCall),
proto.Success(),
]
)
res = client.ping(
"random data",
button_protection=True,
pin_protection=True,
passphrase_protection=True,
)
assert res == "random data"

View File

@ -85,7 +85,7 @@ class TestMsgRecoverydevice:
assert client.features.passphrase_protection is True
# Do passphrase-protected action, PassphraseRequest should be raised
resp = client.call_raw(proto.Ping(passphrase_protection=True))
resp = client.call_raw(proto.GetAddress(address_n=[], coin_name="Testnet"))
assert isinstance(resp, proto.PassphraseRequest)
client.call_raw(proto.Cancel())
@ -136,13 +136,9 @@ class TestMsgRecoverydevice:
assert client.features.pin_protection is False
assert client.features.passphrase_protection is False
# Do passphrase-protected action, PassphraseRequest should NOT be raised
resp = client.call_raw(proto.Ping(passphrase_protection=True))
assert isinstance(resp, proto.Success)
# Do PIN-protected action, PinRequest should NOT be raised
resp = client.call_raw(proto.Ping(pin_protection=True))
assert isinstance(resp, proto.Success)
# Do pin & passphrase-protected action, PassphraseRequest should NOT be raised
resp = client.call_raw(proto.GetAddress(address_n=[], coin_name="Testnet"))
assert isinstance(resp, proto.Address)
@pytest.mark.setup_client(uninitialized=True)
def test_word_fail(self, client):

View File

@ -87,13 +87,9 @@ class TestMsgResetDevice:
assert resp.pin_protection is False
assert resp.passphrase_protection is False
# Do passphrase-protected action, PassphraseRequest should NOT be raised
resp = client.call_raw(proto.Ping(passphrase_protection=True))
assert isinstance(resp, proto.Success)
# Do PIN-protected action, PinRequest should NOT be raised
resp = client.call_raw(proto.Ping(pin_protection=True))
assert isinstance(resp, proto.Success)
# Do pin & passphrase-protected action, PassphraseRequest should NOT be raised
resp = client.call_raw(proto.GetAddress(address_n=[], coin_name="Testnet"))
assert isinstance(resp, proto.Address)
@pytest.mark.setup_client(uninitialized=True)
def test_reset_device_pin(self, client):
@ -180,7 +176,7 @@ class TestMsgResetDevice:
assert resp.passphrase_protection is True
# Do passphrase-protected action, PassphraseRequest should be raised
resp = client.call_raw(proto.Ping(passphrase_protection=True))
resp = client.call_raw(proto.GetAddress(address_n=[], coin_name="Testnet"))
assert isinstance(resp, proto.PassphraseRequest)
client.call_raw(proto.Cancel())

View File

@ -18,7 +18,7 @@ import time
import pytest
from trezorlib import messages as proto
from trezorlib import btc, messages as proto
from trezorlib.exceptions import PinException
# FIXME TODO Add passphrase tests
@ -26,84 +26,45 @@ from trezorlib.exceptions import PinException
@pytest.mark.skip_t2
class TestProtectCall:
def _some_protected_call(self, client, button, pin, passphrase):
def _some_protected_call(self, client):
# This method perform any call which have protection in the device
res = client.ping(
"random data",
button_protection=button,
pin_protection=pin,
passphrase_protection=passphrase,
)
assert res == "random data"
res = btc.get_address(client, "Testnet", [0])
assert res == "mndoQDWatQhfeQbprzZxD43mZ75Z94D6vz"
@pytest.mark.setup_client(pin="1234", passphrase=True)
def test_expected_responses(self, client):
# This is low-level test of set_expected_responses()
# feature of debugging client
with pytest.raises(AssertionError), client:
# Scenario 1 - Received unexpected message
client.set_expected_responses([])
self._some_protected_call(client, True, True, True)
with pytest.raises(AssertionError), client:
# Scenario 2 - Received other than expected message
client.set_expected_responses([proto.Success()])
self._some_protected_call(client, True, True, True)
with pytest.raises(AssertionError), client:
# Scenario 3 - Not received expected message
client.set_expected_responses(
[proto.ButtonRequest(), proto.Success(), proto.Success()]
) # This is expected, but not received
self._some_protected_call(client, True, False, False)
with pytest.raises(AssertionError), client:
with client:
# Scenario 4 - Received what expected
client.set_expected_responses(
[
proto.ButtonRequest(),
proto.PinMatrixRequest(),
proto.PassphraseRequest(),
proto.Success(message="random data"),
]
[proto.PinMatrixRequest(), proto.PassphraseRequest(), proto.Address()]
)
self._some_protected_call(client, True, True, True)
with pytest.raises(AssertionError), client:
# Scenario 5 - Failed message by field filter
client.set_expected_responses(
[proto.ButtonRequest(), proto.Success(message="wrong data")]
)
self._some_protected_call(client, True, True, True)
self._some_protected_call(client)
def test_no_protection(self, client):
with client:
assert client.debug.read_pin()[0] is None
client.set_expected_responses([proto.Success()])
self._some_protected_call(client, False, True, True)
client.set_expected_responses([proto.Address()])
self._some_protected_call(client)
@pytest.mark.setup_client(pin="1234", passphrase=True)
@pytest.mark.setup_client(pin="1234")
def test_pin(self, client):
with client:
assert client.debug.read_pin()[0] == "1234"
client.setup_debuglink(button=True, pin_correct=True)
client.set_expected_responses(
[proto.ButtonRequest(), proto.PinMatrixRequest(), proto.Success()]
)
self._some_protected_call(client, True, True, False)
client.set_expected_responses([proto.PinMatrixRequest(), proto.Address()])
self._some_protected_call(client)
@pytest.mark.setup_client(pin="1234", passphrase=True)
@pytest.mark.setup_client(pin="1234")
def test_incorrect_pin(self, client):
client.setup_debuglink(button=True, pin_correct=False)
with pytest.raises(PinException):
self._some_protected_call(client, False, True, False)
self._some_protected_call(client)
@pytest.mark.setup_client(pin="1234", passphrase=True)
@pytest.mark.setup_client(pin="1234")
def test_cancelled_pin(self, client):
client.setup_debuglink(button=True, pin_correct=False) # PIN cancel
with pytest.raises(PinException):
self._some_protected_call(client, False, True, False)
self._some_protected_call(client)
@pytest.mark.setup_client(pin="1234", passphrase=True)
def test_exponential_backoff_with_reboot(self, client):
@ -126,5 +87,5 @@ class TestProtectCall:
for attempt in range(1, 4):
start = time.time()
with pytest.raises(PinException):
self._some_protected_call(client, False, True, False)
self._some_protected_call(client)
test_backoff(attempt, start)

View File

@ -63,18 +63,11 @@ class TestProtectionLevels:
)
device.change_pin(client)
@pytest.mark.setup_client(pin=True, passphrase=True)
@pytest.mark.setup_client()
def test_ping(self, client):
with client:
client.set_expected_responses(
[
proto.ButtonRequest(),
proto.PinMatrixRequest(),
proto.PassphraseRequest(),
proto.Success(),
]
)
client.ping("msg", True, True, True)
client.set_expected_responses([proto.ButtonRequest(), proto.Success()])
client.ping("msg", True)
@pytest.mark.setup_client(pin=True, passphrase=True)
def test_get_entropy(self, client):
@ -270,28 +263,22 @@ class TestProtectionLevels:
with client:
client.set_expected_responses(
[proto.ButtonRequest(), proto.PinMatrixRequest(), proto.Success()]
[proto.PinMatrixRequest(), proto.ButtonRequest(), proto.Address()]
)
client.ping("msg", True, True, True)
btc.get_address(client, "Bitcoin", [], show_display=True)
client.init_device()
assert client.features.pin_cached is True
with client:
client.set_expected_responses([proto.ButtonRequest(), proto.Success()])
client.ping("msg", True, True, True)
client.set_expected_responses([proto.ButtonRequest(), proto.Address()])
btc.get_address(client, "Bitcoin", [], show_display=True)
@pytest.mark.setup_client(passphrase=True)
def test_passphrase_cached(self, client):
assert client.features.passphrase_cached is False
with client:
client.set_expected_responses([proto.PassphraseRequest(), proto.Address()])
btc.get_address(client, "Bitcoin", [])
with client:
client.set_expected_responses(
[proto.ButtonRequest(), proto.PassphraseRequest(), proto.Success()]
)
client.ping("msg", True, True, True)
features = client.call(proto.GetFeatures())
assert features.passphrase_cached is True
with client:
client.set_expected_responses([proto.ButtonRequest(), proto.Success()])
client.ping("msg", True, True, True)
client.set_expected_responses([proto.Address()])
btc.get_address(client, "Bitcoin", [])