mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-05-24 09:48:45 +00:00
tests: expand on multi-session tests
This commit is contained in:
parent
f93f6e445b
commit
8fed67de08
@ -14,6 +14,8 @@
|
|||||||
# You should have received a copy of the License along with this library.
|
# You should have received a copy of the License along with this library.
|
||||||
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
|
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from trezorlib import messages
|
from trezorlib import messages
|
||||||
@ -88,61 +90,122 @@ def test_session_with_passphrase(client):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip_ui
|
@pytest.mark.skip_ui
|
||||||
|
@pytest.mark.timeout(300)
|
||||||
@pytest.mark.setup_client(passphrase=True)
|
@pytest.mark.setup_client(passphrase=True)
|
||||||
def test_multiple_sessions(client):
|
def test_multiple_sessions(client):
|
||||||
|
# start SESSIONS_STORED sessions
|
||||||
session_ids = []
|
session_ids = []
|
||||||
|
for _ in range(SESSIONS_STORED):
|
||||||
|
session_ids.append(_init_session(client))
|
||||||
|
|
||||||
|
# Resume each session
|
||||||
|
for session_id in session_ids:
|
||||||
|
new_session_id = _init_session(client, session_id)
|
||||||
|
assert session_id == new_session_id
|
||||||
|
|
||||||
|
# Creating a new session replaces the least-recently-used session
|
||||||
|
_init_session(client)
|
||||||
|
|
||||||
|
# Resuming session 1 through SESSIONS_STORED will still work
|
||||||
|
for session_id in session_ids[1:]:
|
||||||
|
new_session_id = _init_session(client, session_id)
|
||||||
|
assert session_id == new_session_id
|
||||||
|
|
||||||
|
# Resuming session 0 will not work
|
||||||
|
new_session_id = _init_session(client, session_ids[0])
|
||||||
|
assert new_session_id != session_ids[0]
|
||||||
|
|
||||||
|
# New session bumped out the least-recently-used anonymous session.
|
||||||
|
# Resuming session 1 through SESSIONS_STORED will still work
|
||||||
|
for session_id in session_ids[1:]:
|
||||||
|
new_session_id = _init_session(client, session_id)
|
||||||
|
assert session_id == new_session_id
|
||||||
|
|
||||||
|
# Creating a new session replaces session_ids[0] again
|
||||||
|
_init_session(client)
|
||||||
|
|
||||||
|
# Resuming all sessions one by one will in turn bump out the previous session.
|
||||||
|
for session_id in session_ids:
|
||||||
|
new_session_id = _init_session(client, session_id)
|
||||||
|
assert session_id != new_session_id
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip_ui
|
||||||
|
@pytest.mark.setup_client(passphrase=True)
|
||||||
|
def test_multiple_passphrases(client):
|
||||||
# start a session
|
# start a session
|
||||||
session_ids.append(_init_session(client))
|
session_a = _init_session(client)
|
||||||
assert _get_xpub(client, passphrase="A") == XPUB_PASSPHRASES["A"]
|
assert _get_xpub(client, passphrase="A") == XPUB_PASSPHRASES["A"]
|
||||||
# start it again wit the same session id
|
# start it again wit the same session id
|
||||||
new_session_id = _init_session(client, session_id=session_ids[0])
|
new_session_id = _init_session(client, session_id=session_a)
|
||||||
# session is the same
|
# session is the same
|
||||||
assert new_session_id == session_ids[0]
|
assert new_session_id == session_a
|
||||||
# passphrase is not prompted
|
# passphrase is not prompted
|
||||||
assert _get_xpub(client, passphrase=None) == XPUB_PASSPHRASES["A"]
|
assert _get_xpub(client, passphrase=None) == XPUB_PASSPHRASES["A"]
|
||||||
|
|
||||||
# start a second session
|
# start a second session
|
||||||
session_ids.append(_init_session(client))
|
session_b = _init_session(client)
|
||||||
# new session -> new session id and passphrase prompt
|
# new session -> new session id and passphrase prompt
|
||||||
assert _get_xpub(client, passphrase="B") == XPUB_PASSPHRASES["B"]
|
assert _get_xpub(client, passphrase="B") == XPUB_PASSPHRASES["B"]
|
||||||
|
|
||||||
# provide the same session id -> must not ask for passphrase again.
|
# provide the same session id -> must not ask for passphrase again.
|
||||||
new_session_id = _init_session(client, session_id=session_ids[1])
|
new_session_id = _init_session(client, session_id=session_b)
|
||||||
assert new_session_id == session_ids[1]
|
assert new_session_id == session_b
|
||||||
assert _get_xpub(client, passphrase=None) == XPUB_PASSPHRASES["B"]
|
assert _get_xpub(client, passphrase=None) == XPUB_PASSPHRASES["B"]
|
||||||
|
|
||||||
# provide the first session id -> must not ask for passphrase again and return the same result.
|
# provide the first session id -> must not ask for passphrase again and return the same result.
|
||||||
new_session_id = _init_session(client, session_id=session_ids[0])
|
new_session_id = _init_session(client, session_id=session_a)
|
||||||
assert new_session_id == session_ids[0]
|
assert new_session_id == session_a
|
||||||
assert _get_xpub(client, passphrase=None) == XPUB_PASSPHRASES["A"]
|
assert _get_xpub(client, passphrase=None) == XPUB_PASSPHRASES["A"]
|
||||||
|
|
||||||
passphrases = list(XPUB_PASSPHRASES.keys())
|
# provide the second session id -> must not ask for passphrase again and return the same result.
|
||||||
xpubs = list(XPUB_PASSPHRASES.values())
|
new_session_id = _init_session(client, session_id=session_b)
|
||||||
# start as many sessions as the limit is (2 were started already)
|
assert new_session_id == session_b
|
||||||
for i in range(2, SESSIONS_STORED):
|
assert _get_xpub(client, passphrase=None) == XPUB_PASSPHRASES["B"]
|
||||||
new_session_id = _init_session(client)
|
|
||||||
assert new_session_id not in session_ids
|
|
||||||
session_ids.append(new_session_id)
|
@pytest.mark.skip_ui
|
||||||
assert _get_xpub(client, passphrase=passphrases[i]) == xpubs[i]
|
@pytest.mark.timeout(600)
|
||||||
|
@pytest.mark.slow
|
||||||
|
@pytest.mark.setup_client(passphrase=True)
|
||||||
|
def test_max_sessions_with_passphrases(client):
|
||||||
|
# for the following tests, we are using as many passphrases as there are available sessions
|
||||||
|
assert len(XPUB_PASSPHRASES) == SESSIONS_STORED
|
||||||
|
|
||||||
|
# start as many sessions as the limit is
|
||||||
|
session_ids = {}
|
||||||
|
for passphrase, xpub in XPUB_PASSPHRASES.items():
|
||||||
|
session_id = _init_session(client)
|
||||||
|
assert session_id not in session_ids.values()
|
||||||
|
session_ids[passphrase] = session_id
|
||||||
|
assert _get_xpub(client, passphrase=passphrase) == xpub
|
||||||
|
|
||||||
# passphrase is not prompted for the started the sessions, regardless the order
|
# passphrase is not prompted for the started the sessions, regardless the order
|
||||||
for i in reversed(range(0, SESSIONS_STORED)):
|
# let's try 20 different orderings
|
||||||
_init_session(client, session_id=session_ids[i])
|
passphrases = list(XPUB_PASSPHRASES.keys())
|
||||||
assert _get_xpub(client, passphrase=None) == xpubs[i]
|
shuffling = passphrases[:]
|
||||||
|
for _ in range(20):
|
||||||
|
random.shuffle(shuffling)
|
||||||
|
for passphrase in shuffling:
|
||||||
|
session_id = _init_session(client, session_id=session_ids[passphrase])
|
||||||
|
assert session_id == session_ids[passphrase]
|
||||||
|
assert _get_xpub(client, passphrase=None) == XPUB_PASSPHRASES[passphrase]
|
||||||
|
|
||||||
# creating one more will exceed the limit, the LRU item is at the moment the last one (see above)
|
# make sure the usage order is the reverse of the creation order
|
||||||
# it should have been removed -> must ask for passphrase
|
for passphrase in reversed(passphrases):
|
||||||
_init_session(client)
|
session_id = _init_session(client, session_id=session_ids[passphrase])
|
||||||
_get_xpub(client, passphrase="XX") # create one more
|
assert session_id == session_ids[passphrase]
|
||||||
_init_session(client, session_id=session_ids[SESSIONS_STORED - 1])
|
assert _get_xpub(client, passphrase=None) == XPUB_PASSPHRASES[passphrase]
|
||||||
_get_xpub(client, passphrase="whatever") # the session is gone
|
|
||||||
|
|
||||||
# now the second to last is the next LRU
|
# creating one more session will exceed the limit
|
||||||
_init_session(client)
|
_init_session(client)
|
||||||
_get_xpub(client, passphrase="XXXX")
|
# new session asks for passphrase
|
||||||
_init_session(client, session_id=session_ids[SESSIONS_STORED - 2])
|
_get_xpub(client, passphrase="XX")
|
||||||
_get_xpub(client, passphrase="whatever")
|
|
||||||
|
# restoring the sessions in reverse will evict the next-up session
|
||||||
|
for passphrase in reversed(passphrases):
|
||||||
|
_init_session(client, session_id=session_ids[passphrase])
|
||||||
|
_get_xpub(client, passphrase="whatever") # passphrase is prompted
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip_ui
|
@pytest.mark.skip_ui
|
||||||
@ -235,7 +298,7 @@ def test_passphrase_always_on_device(client):
|
|||||||
_init_session(client)
|
_init_session(client)
|
||||||
response = client.call_raw(XPUB_REQUEST)
|
response = client.call_raw(XPUB_REQUEST)
|
||||||
assert isinstance(response, messages.ButtonRequest)
|
assert isinstance(response, messages.ButtonRequest)
|
||||||
client.debug.input("A") # Input empty passphrase.
|
client.debug.input("A") # Input non-empty passphrase.
|
||||||
response = client.call_raw(messages.ButtonAck())
|
response = client.call_raw(messages.ButtonAck())
|
||||||
assert isinstance(response, messages.PublicKey)
|
assert isinstance(response, messages.PublicKey)
|
||||||
assert response.xpub == XPUB_PASSPHRASES["A"]
|
assert response.xpub == XPUB_PASSPHRASES["A"]
|
||||||
|
Loading…
Reference in New Issue
Block a user