1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-26 01:18:28 +00:00

Merge pull request #675 from trezor/ciny/shamir_click_tests

tests: click tests for basic and advanced slip39
This commit is contained in:
Tomas Susanka 2019-11-05 11:39:34 +01:00 committed by GitHub
commit e30245b96b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 446 additions and 2 deletions

View File

@ -21,8 +21,14 @@ INFO = (MID, BOTTOM)
CONFIRM_WORD = (MID, TOP)
MINUS = (LEFT, grid(DISPLAY_HEIGHT, 5, 2))
PLUS = (RIGHT, grid(DISPLAY_HEIGHT, 5, 2))
RESET_MINUS = (LEFT, grid(DISPLAY_HEIGHT, 5, 1))
RESET_PLUS = (RIGHT, grid(DISPLAY_HEIGHT, 5, 1))
RESET_WORD_CHECK = [
(MID, grid(DISPLAY_HEIGHT, 6, 3)),
(MID, grid(DISPLAY_HEIGHT, 6, 4)),
(MID, grid(DISPLAY_HEIGHT, 6, 5)),
]
BUTTON_LETTERS = ("ab", "cd", "ef", "ghij", "klm", "nopq", "rs", "tuv", "wxyz")

View File

@ -0,0 +1,71 @@
import shamir_mnemonic as shamir
from trezorlib import messages
from .. import buttons
def confirm_wait(debug, startswith):
layout = debug.wait_layout()
assert layout.text.startswith(startswith)
debug.click(buttons.OK, wait=True)
def confirm_read(debug, startswith):
layout = debug.read_layout()
assert layout.text.startswith(startswith)
debug.click(buttons.OK, wait=True)
def set_selection(debug, button, diff):
layout = debug.read_layout()
assert layout.text.startswith("Slip39NumInput")
for _ in range(diff):
debug.click(button, wait=False)
debug.click(buttons.OK, wait=True)
def read_words(debug, is_advanced=False):
words = []
layout = debug.read_layout()
if is_advanced:
assert layout.text.startswith("Group")
else:
assert layout.text.startswith("Recovery share")
for i in range(6):
lines = debug.read_layout().lines
if i == 0:
words.append(lines[3].split()[1])
words.append(lines[4].split()[1])
debug.input(swipe=messages.DebugSwipeDirection.UP, wait=True)
elif i == 5:
words.append(lines[1].split()[1])
words.append(lines[2].split()[1])
else:
words.append(lines[1].split()[1])
words.append(lines[2].split()[1])
words.append(lines[3].split()[1])
words.append(lines[4].split()[1])
debug.input(swipe=messages.DebugSwipeDirection.UP, wait=True)
debug.press_yes()
return words
def confirm_words(debug, words):
# confirm words
layout = debug.wait_layout()
layout.text.startswith("Check share")
for _ in range(3):
word_pos = int(debug.state().layout_lines[1].split()[2])
button_pos = debug.state().layout_lines.index(words[word_pos - 1]) - 2
debug.click(buttons.RESET_WORD_CHECK[button_pos], wait=True)
def validate_mnemonics(mnemonics, expected_ems):
# We expect these combinations to recreate the secret properly
# In case of click tests the mnemonics are always XofX so no need for combinations
ms = shamir.combine_mnemonics(mnemonics)
identifier, iteration_exponent, _, _, _ = shamir._decode_mnemonics(mnemonics)
ems = shamir._encrypt(ms, b"", iteration_exponent, identifier)
assert ems == expected_ems

View File

@ -0,0 +1,193 @@
# This file is part of the Trezor project.
#
# Copyright (C) 2012-2019 SatoshiLabs and contributors
#
# This library is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License version 3
# as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# 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>.
from unittest import mock
import pytest
from trezorlib import device, messages
from .. import buttons
from ..common import generate_entropy
from . import reset
EXTERNAL_ENTROPY = b"zlutoucky kun upel divoke ody" * 2
@pytest.mark.skip_t1
@pytest.mark.setup_client(uninitialized=True)
def test_reset_slip39_advanced_2of2groups_2of2shares(device_handler):
features = device_handler.features()
debug = device_handler.debuglink()
assert features.initialized is False
os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY)
with mock.patch("os.urandom", os_urandom), device_handler:
device_handler.run(
device.reset,
strength=128,
backup_type=messages.BackupType.Slip39_Advanced,
pin_protection=False,
)
# confirm new wallet
reset.confirm_wait(debug, "Create new wallet")
# confirm back up
reset.confirm_wait(debug, "Success")
# confirm checklist
reset.confirm_read(debug, "Checklist")
# set num of groups
reset.set_selection(debug, buttons.RESET_MINUS, 3)
# confirm checklist
reset.confirm_read(debug, "Checklist")
# set group threshold
reset.set_selection(debug, buttons.RESET_MINUS, 0)
# confirm checklist
reset.confirm_read(debug, "Checklist")
# set share num and threshold for groups
for _ in range(2):
# set num of shares
reset.set_selection(debug, buttons.RESET_MINUS, 3)
# set share threshold
reset.set_selection(debug, buttons.RESET_MINUS, 0)
# confirm backup warning
reset.confirm_read(debug, "Caution")
all_words = []
for _ in range(2):
for _ in range(2):
# read words
words = reset.read_words(debug, True)
# confirm words
reset.confirm_words(debug, words)
# confirm share checked
reset.confirm_read(debug, "Success")
all_words.append(" ".join(words))
# confirm backup done
reset.confirm_read(debug, "Success")
# generate secret locally
internal_entropy = debug.state().reset_entropy
secret = generate_entropy(128, internal_entropy, EXTERNAL_ENTROPY)
# validate that all combinations will result in the correct master secret
reset.validate_mnemonics(all_words, secret)
assert device_handler.result() == "Initialized"
features = device_handler.features()
assert features.initialized is True
assert features.needs_backup is False
assert features.pin_protection is False
assert features.passphrase_protection is False
assert features.backup_type is messages.BackupType.Slip39_Advanced
@pytest.mark.skip_t1
@pytest.mark.setup_client(uninitialized=True)
def test_reset_slip39_advanced_16of16groups_16of16shares(device_handler):
features = device_handler.features()
debug = device_handler.debuglink()
assert features.initialized is False
os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY)
with mock.patch("os.urandom", os_urandom), device_handler:
device_handler.run(
device.reset,
strength=128,
backup_type=messages.BackupType.Slip39_Advanced,
pin_protection=False,
)
# confirm new wallet
reset.confirm_wait(debug, "Create new wallet")
# confirm back up
reset.confirm_wait(debug, "Success")
# confirm checklist
reset.confirm_read(debug, "Checklist")
# set num of groups
reset.set_selection(debug, buttons.RESET_PLUS, 11)
# confirm checklist
reset.confirm_read(debug, "Checklist")
# set group threshold
reset.set_selection(debug, buttons.RESET_PLUS, 11)
# confirm checklist
reset.confirm_read(debug, "Checklist")
# set share num and threshold for groups
for _ in range(16):
# set num of shares
reset.set_selection(debug, buttons.RESET_PLUS, 11)
# set share threshold
reset.set_selection(debug, buttons.RESET_PLUS, 11)
# confirm backup warning
reset.confirm_read(debug, "Caution")
all_words = []
for _ in range(16):
for _ in range(16):
# read words
words = reset.read_words(debug, True)
# confirm words
reset.confirm_words(debug, words)
# confirm share checked
reset.confirm_read(debug, "Success")
all_words.append(" ".join(words))
# confirm backup done
reset.confirm_read(debug, "Success")
# generate secret locally
internal_entropy = debug.state().reset_entropy
secret = generate_entropy(128, internal_entropy, EXTERNAL_ENTROPY)
# validate that all combinations will result in the correct master secret
reset.validate_mnemonics(all_words, secret)
assert device_handler.result() == "Initialized"
features = device_handler.features()
assert features.initialized is True
assert features.needs_backup is False
assert features.pin_protection is False
assert features.passphrase_protection is False
assert features.backup_type is messages.BackupType.Slip39_Advanced

View File

@ -0,0 +1,174 @@
# This file is part of the Trezor project.
#
# Copyright (C) 2012-2019 SatoshiLabs and contributors
#
# This library is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License version 3
# as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# 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>.
from unittest import mock
import pytest
from trezorlib import device, messages
from .. import buttons
from ..common import generate_entropy
from . import reset
EXTERNAL_ENTROPY = b"zlutoucky kun upel divoke ody" * 2
@pytest.mark.skip_t1
@pytest.mark.setup_client(uninitialized=True)
def test_reset_slip39_basic_1of1(device_handler):
features = device_handler.features()
debug = device_handler.debuglink()
assert features.initialized is False
os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY)
with mock.patch("os.urandom", os_urandom), device_handler:
device_handler.run(
device.reset,
strength=128,
backup_type=messages.BackupType.Slip39_Basic,
pin_protection=False,
)
# confirm new wallet
reset.confirm_wait(debug, "Create new wallet")
# confirm back up
reset.confirm_wait(debug, "Success")
# confirm checklist
reset.confirm_read(debug, "Checklist")
# set num of shares
# default is 5 so we press RESET_MINUS 4 times
reset.set_selection(debug, buttons.RESET_MINUS, 4)
# confirm checklist
reset.confirm_read(debug, "Checklist")
# set threshold
# threshold will default to 1
reset.set_selection(debug, buttons.RESET_MINUS, 0)
# confirm checklist
reset.confirm_read(debug, "Checklist")
# confirm backup warning
reset.confirm_read(debug, "Caution")
# read words
words = reset.read_words(debug)
# confirm words
reset.confirm_words(debug, words)
# confirm share checked
reset.confirm_read(debug, "Success")
# confirm backup done
reset.confirm_read(debug, "Success")
# generate secret locally
internal_entropy = debug.state().reset_entropy
secret = generate_entropy(128, internal_entropy, EXTERNAL_ENTROPY)
# validate that all combinations will result in the correct master secret
validate = [" ".join(words)]
reset.validate_mnemonics(validate, secret)
assert device_handler.result() == "Initialized"
features = device_handler.features()
assert features.initialized is True
assert features.needs_backup is False
assert features.pin_protection is False
assert features.passphrase_protection is False
assert features.backup_type is messages.BackupType.Slip39_Basic
@pytest.mark.skip_t1
@pytest.mark.setup_client(uninitialized=True)
def test_reset_slip39_basic_16of16(device_handler):
features = device_handler.features()
debug = device_handler.debuglink()
assert features.initialized is False
os_urandom = mock.Mock(return_value=EXTERNAL_ENTROPY)
with mock.patch("os.urandom", os_urandom), device_handler:
device_handler.run(
device.reset,
strength=128,
backup_type=messages.BackupType.Slip39_Basic,
pin_protection=False,
)
# confirm new wallet
reset.confirm_wait(debug, "Create new wallet")
# confirm back up
reset.confirm_wait(debug, "Success")
# confirm checklist
reset.confirm_read(debug, "Checklist")
# set num of shares
# default is 5 so we add 11
reset.set_selection(debug, buttons.RESET_PLUS, 11)
# confirm checklist
reset.confirm_read(debug, "Checklist")
# set threshold
# default is 5 so we add 11
reset.set_selection(debug, buttons.RESET_PLUS, 11)
# confirm checklist
reset.confirm_read(debug, "Checklist")
# confirm backup warning
reset.confirm_read(debug, "Caution")
all_words = []
for _ in range(16):
# read words
words = reset.read_words(debug)
# confirm words
reset.confirm_words(debug, words)
# confirm share checked
reset.confirm_read(debug, "Success")
all_words.append(" ".join(words))
# confirm backup done
reset.confirm_read(debug, "Success")
# generate secret locally
internal_entropy = debug.state().reset_entropy
secret = generate_entropy(128, internal_entropy, EXTERNAL_ENTROPY)
# validate that all combinations will result in the correct master secret
reset.validate_mnemonics(all_words, secret)
assert device_handler.result() == "Initialized"
features = device_handler.features()
assert features.initialized is True
assert features.needs_backup is False
assert features.pin_protection is False
assert features.passphrase_protection is False
assert features.backup_type is messages.BackupType.Slip39_Basic