forked from onflow/ledger-app-flow
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathtest_slots.py
159 lines (122 loc) · 4.72 KB
/
test_slots.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
from pathlib import Path
from typing import Tuple
import pytest
from application_client.flow_command_sender import FlowCommandSender, Errors, HashType, MAX_SLOTS, CryptoOptions
from application_client.flow_response_unpacker import unpack_get_slot_response
from ragger.bip import CurveChoice
from ragger.error import ExceptionRAPDU
from ragger.navigator import Navigator
from ragger.firmware import Firmware
from utils import util_set_slot, util_navigate
def _extract_option(option: bytes) -> CryptoOptions:
""" Extract curve and hash from options bytes array """
hash_value = int(option[0:2])
curve_value = int(option[2:4])
if curve_value == 2:
curve = CurveChoice.Nist256p1
elif curve_value == 3:
curve = CurveChoice.Secp256k1
else:
raise ValueError(f'Wrong Cruve "{curve_value}"')
if hash_value == 1:
hash_t = HashType.HASH_SHA2
elif hash_value == 3:
hash_t = HashType.HASH_SHA3
else:
raise ValueError(f'Wrong Hash "{hash_value}"')
return CryptoOptions(curve, hash_t)
def _set_slot_and_check(
client: FlowCommandSender,
firmware: Firmware,
navigator: Navigator,
test_name: Path,
slot: int,
crypto_options: CryptoOptions,
address: str,
path: str,
) -> None:
""" Set slot content, and check back """
# Send the APDU - Set slot
util_set_slot(client, firmware, navigator, test_name, slot, crypto_options, address, path)
# Send the APDU - Slot status
response = client.get_slot_status()
assert response.status == Errors.SW_SUCCESS
# Assert expected result
assert response.data[slot] == 1
# Send the APDU - Slot content
response = client.get_slot(slot)
assert response.status == Errors.SW_SUCCESS
# Parse the response
ret_address, ret_path, ret_option = unpack_get_slot_response(response.data)
ret_option = _extract_option(ret_option)
print(f" Address: {ret_address}")
print(f" Path: {ret_path}")
print(f" Curve: {ret_option.curve}")
print(f" Hash: {ret_option.hash_t}")
# Check expected value
assert address == ret_address
assert crypto_options == ret_option
def test_get_slot_status(backend):
""" Check slots status are all empty """
# Use the app interface instead of raw interface
client = FlowCommandSender(backend)
# Send the APDU
response = client.get_slot_status()
assert response.status == Errors.SW_SUCCESS
# Check expected values
for slot in range(MAX_SLOTS):
assert not response.data[slot]
def test_get_slot_empty(backend):
""" Check empty slots """
# Use the app interface instead of raw interface
client = FlowCommandSender(backend)
# Test parameters
slot = 10
with pytest.raises(ExceptionRAPDU) as err:
# Send the APDU
response = client.get_slot(slot)
assert not response.data
# Assert we have received a refusal
assert err.value.status == Errors.SW_EMPTY_BUFFER
assert len(err.value.data) == 0
def test_get_slot_accepted(firmware, backend, navigator, test_name):
""" slot Test in confirmation mode """
# Use the app interface instead of raw interface
client = FlowCommandSender(backend)
# Test parameters
slot = 10
address = "e467b9dd11fa00df"
path = "m/44'/539'/513'/0/0"
crypto_options = CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2)
# Send the APDU - Set slot
part = 0
_set_slot_and_check(
client, firmware, navigator, f"{test_name}/part{part}", slot, crypto_options, address, path
)
# Send the APDU - Update slot
address = "e467b9dd11fa00de"
path = "m/44'/539'/513'/0/1"
crypto_options2 = CryptoOptions(CurveChoice.Nist256p1, HashType.HASH_SHA2)
part += 1
_set_slot_and_check(
client, firmware, navigator, f"{test_name}/part{part}", slot, crypto_options2, address, path
)
# Clean Slot
part += 1
util_set_slot(client, firmware, navigator, f"{test_name}/part{part}", slot)
def test_get_slot_refused(firmware, backend, navigator, test_name):
""" Check slot in confirmation mode when user refuses """
# Use the app interface instead of raw interface
client = FlowCommandSender(backend)
# Test parameters
slot = 10
address = "e467b9dd11fa00df"
path = "m/44'/539'/513'/0/0"
crypto_options = CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2)
# Send the APDU (Asynchronous)
with pytest.raises(ExceptionRAPDU) as err:
with client.set_slot(slot, address, path, crypto_options):
util_navigate(firmware, navigator, test_name, "REJECT_SLOT")
# Assert we have received a refusal
assert err.value.status == Errors.SW_COMMAND_NOT_ALLOWED
assert len(err.value.data) == 0