From f5ed4bb1e59b1b2acbbdae8d9f8678ae1f738b93 Mon Sep 17 00:00:00 2001 From: Charles-Edouard de la Vergne Date: Thu, 12 Sep 2024 11:15:00 +0200 Subject: [PATCH] Adapt client and ragger tests for eip712 friction --- .../src/ledger_app_clients/ethereum/client.py | 9 +++ .../ethereum/eip712/InputData.py | 6 ++ tests/ragger/test_eip712.py | 63 ++++++++++++++++++- 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/client/src/ledger_app_clients/ethereum/client.py b/client/src/ledger_app_clients/ethereum/client.py index a6008402b..89154e34a 100644 --- a/client/src/ledger_app_clients/ethereum/client.py +++ b/client/src/ledger_app_clients/ethereum/client.py @@ -104,6 +104,15 @@ def send_raw(self, cla: int, ins: int, p1: int, p2: int, payload: bytes): header.append(len(payload)) return self._exchange(header + payload) + def send_raw_async(self, cla: int, ins: int, p1: int, p2: int, payload: bytes): + header = bytearray() + header.append(cla) + header.append(ins) + header.append(p1) + header.append(p2) + header.append(len(payload)) + return self._exchange_async(header + payload) + def eip712_send_struct_def_struct_name(self, name: str): return self._exchange_async(self._cmd_builder.eip712_send_struct_def_struct_name(name)) diff --git a/client/src/ledger_app_clients/ethereum/eip712/InputData.py b/client/src/ledger_app_clients/ethereum/eip712/InputData.py index 43f88f3af..c5066ffeb 100644 --- a/client/src/ledger_app_clients/ethereum/eip712/InputData.py +++ b/client/src/ledger_app_clients/ethereum/eip712/InputData.py @@ -11,6 +11,7 @@ from client.client import EthAppClient, EIP712FieldType from ragger.firmware import Firmware +from ragger.navigator import Navigator, NavInsID from client.client import PKIPubKeyUsage @@ -436,6 +437,7 @@ def disable_autonext(): def process_data(aclient: EthAppClient, + navigator: Navigator, data_json: dict, filters: Optional[dict] = None, autonext: Optional[Callable] = None, @@ -494,6 +496,10 @@ def process_data(aclient: EthAppClient, # send domain implementation with app_client.eip712_send_struct_impl_root_struct(domain_typename): + if not app_client._client.firmware.is_nano and filters is None: + navigator.navigate([NavInsID.USE_CASE_CHOICE_REJECT], + screen_change_before_first_instruction=False, + screen_change_after_last_instruction=False) enable_autonext() disable_autonext() if not send_struct_impl(types, domain, domain_typename): diff --git a/tests/ragger/test_eip712.py b/tests/ragger/test_eip712.py index 90f8022d6..3bb068919 100644 --- a/tests/ragger/test_eip712.py +++ b/tests/ragger/test_eip712.py @@ -10,13 +10,14 @@ import web3 from ragger.backend import BackendInterface +from ragger.error import ExceptionRAPDU from ragger.firmware import Firmware from ragger.navigator import Navigator, NavInsID from ragger.navigator.navigation_scenario import NavigateWithScenario import client.response_parser as ResponseParser from client.utils import recover_message -from client.client import EthAppClient +from client.client import EthAppClient, StatusWord from client.eip712 import InputData from client.settings import SettingID, settings_toggle @@ -117,6 +118,7 @@ def eip712_new_common(firmware: Firmware, verbose: bool, golden_run: bool): assert InputData.process_data(app_client, + navigator, json_data, filters, partial(autonext, firmware, navigator, default_screenshot_path), @@ -151,6 +153,54 @@ def eip712_new_common(firmware: Firmware, return ResponseParser.signature(app_client.response().data) +def test_eip712_blind_sign_error(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + test_name: str, + default_screenshot_path: Path): + app_client = EthAppClient(backend) + if firmware.is_nano: + pytest.skip("Not supported on Nano") + + # TODO: Find a better way, using the JSON file directly with navigation + # APDU list generated from the following JSON: 00-simple_mail-data.json + apdu_list = [ + "e01a00000c454950373132446f6d61696e", + "e01a00ff0605046e616d65", + "e01a00ff09050776657273696f6e", + "e01a00ff0a422007636861696e4964", + "e01a00ff130311766572696679696e67436f6e7472616374", + "e01a0000044d61696c", + "e01a00ff0d0006506572736f6e0466726f6d", + "e01a00ff0b0006506572736f6e02746f", + "e01a00ff0a0508636f6e74656e7473", + "e01a000006506572736f6e", + "e01a00ff0605046e616d65", + "e01a00ff0b8301000777616c6c657473", + "e01c00000c454950373132446f6d61696e", + "e01c00ff0d000b53696d706c65204d61696c", + ] + + for apdu in apdu_list[:-1]: + app_client.send_raw(int(apdu[0:2], 16), + int(apdu[2:4], 16), + int(apdu[4:6], 16), + int(apdu[6:8], 16), + bytes.fromhex(apdu[10:])) + apdu = apdu_list[-1] + with pytest.raises(ExceptionRAPDU) as e: + with app_client.send_raw_async(int(apdu[0:2], 16), + int(apdu[2:4], 16), + int(apdu[4:6], 16), + int(apdu[6:8], 16), + bytes.fromhex(apdu[10:])): + navigator.navigate_and_compare(default_screenshot_path, + test_name, + [NavInsID.USE_CASE_REVIEW_REJECT]) + + assert e.value.status == StatusWord.CONDITION_NOT_SATISFIED + + def test_eip712_new(firmware: Firmware, backend: BackendInterface, navigator: Navigator, @@ -161,6 +211,8 @@ def test_eip712_new(firmware: Firmware, app_client = EthAppClient(backend) if firmware == Firmware.NANOS: pytest.skip("Not supported on LNS") + if not firmware.is_nano and not verbose and not filtering: + pytest.skip("Not supported on Flex/Stax") test_path = f"{input_file.parent}/{'-'.join(input_file.stem.split('-')[:-1])}" @@ -173,8 +225,13 @@ def test_eip712_new(firmware: Firmware, except (IOError, json.decoder.JSONDecodeError) as e: pytest.skip(f"{filterfile.name}: {e.strerror}") + settings = [] if verbose: - settings_toggle(firmware, navigator, [SettingID.VERBOSE_EIP712]) + settings.append(SettingID.VERBOSE_EIP712) + if not filtering: + settings.append(SettingID.BLIND_SIGNING) + if len(settings) > 0: + settings_toggle(firmware, navigator, settings) with open(input_file, encoding="utf-8") as file: data = json.load(file) @@ -566,7 +623,7 @@ def test_eip712_advanced_missing_token(firmware: Firmware, golden_run: bool): global SNAPS_CONFIG - test_name += "-%s-%s" % (len(tokens[0]) == 0, len(tokens[1]) == 0) + test_name += f"-{len(tokens[0]) == 0}-{len(tokens[1]) == 0}" SNAPS_CONFIG = SnapshotsConfig(test_name) app_client = EthAppClient(backend)