From b39923a095fe8151215e2ef6b6405a0347320cb9 Mon Sep 17 00:00:00 2001 From: Robert Lukotka Date: Fri, 27 Sep 2024 15:28:42 +0200 Subject: [PATCH] Python client refactor Fixed too many arguments CI issue --- .../application_client/flow_command_sender.py | 49 +++++---- tests/test_app_mainmenu.py | 7 +- tests/test_pubkey_cmd.py | 41 ++++--- tests/test_sign_cmd.py | 101 +++++++----------- tests/test_slots.py | 33 +++--- tests/utils.py | 25 ++--- 6 files changed, 112 insertions(+), 144 deletions(-) diff --git a/tests/application_client/flow_command_sender.py b/tests/application_client/flow_command_sender.py index 59f1984a..cc07082a 100644 --- a/tests/application_client/flow_command_sender.py +++ b/tests/application_client/flow_command_sender.py @@ -1,5 +1,6 @@ from enum import IntEnum, Enum from typing import Generator, Optional, List +from dataclasses import dataclass from contextlib import contextmanager from bip_utils import Bip32Utils # type: ignore[import] @@ -70,6 +71,12 @@ class HashType(str, Enum): # SHA3-256 HASH_SHA3 = "sha-3" +@dataclass(frozen=True) +class CryptoOptions: + """Stores curve and hash""" + curve: CurveChoice + hash_t: HashType + def _pack_derivation(derivation_path: str) -> bytes: """ Pack derivation path in bytes """ @@ -91,33 +98,32 @@ def _pack_derivation(derivation_path: str) -> bytes: return path_bytes -def _pack_crypto_option(curve: CurveChoice, hash_t: HashType) -> bytes: +def _pack_crypto_option(crypto_options: CryptoOptions) -> bytes: """ Pack crypto (curve + hash) options in bytes """ path_bytes: bytes = bytes() - if hash_t == HashType.HASH_SHA2: + if crypto_options.hash_t == HashType.HASH_SHA2: hash_value = 1 - elif hash_t == HashType.HASH_SHA3: + elif crypto_options.hash_t == HashType.HASH_SHA3: hash_value = 3 else: - raise ValueError(f'Wrong Hash "{hash_t}"') + raise ValueError(f'Wrong Hash "{crypto_options.hash_t}"') path_bytes += int(hash_value).to_bytes(1, byteorder='little') - if curve == CurveChoice.Nist256p1: + if crypto_options.curve == CurveChoice.Nist256p1: curve_value = 2 - elif curve == CurveChoice.Secp256k1: + elif crypto_options.curve == CurveChoice.Secp256k1: curve_value = 3 else: - raise ValueError(f'Wrong Cruve "{curve}"') + raise ValueError(f'Wrong Cruve "{crypto_options.curve}"') path_bytes += int(curve_value).to_bytes(1, byteorder='little') return path_bytes def _format_apdu_data( - curve: CurveChoice = CurveChoice.Secp256k1, - hash_t: HashType = HashType.HASH_SHA2, + crypto_options: CryptoOptions, path: str = "", address: str = "", slot: int = MAX_SLOTS, @@ -135,7 +141,7 @@ def _format_apdu_data( # Consider empty slot, force option to 0 data_path += int(0).to_bytes(2, 'little') else: - data_path += _pack_crypto_option(curve, hash_t) + data_path += _pack_crypto_option(crypto_options) return data_path @@ -149,7 +155,8 @@ def __init__(self, backend: BackendInterface) -> None: def get_generic(self) -> RAPDU: """ APDU generic version """ - data_path= _format_apdu_data(address="00") + data_path = _format_apdu_data(CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2), + address="00") return self.backend.exchange(cla=ClaType.CLA_GEN, ins=InsType.GENERIC, data=data_path) @@ -182,12 +189,11 @@ def set_slot( slot: int, address: str, path: str, - curve: CurveChoice, - hash_t: HashType, + crypto_options: CryptoOptions, ) -> Generator[None, None, None]: """ APDU set slot """ - data_path= _format_apdu_data(curve, hash_t, path, address, slot) + data_path= _format_apdu_data(crypto_options, path, address, slot) with self.backend.exchange_async(cla=ClaType.CLA_APP, ins=InsType.SET_SLOT, data=data_path) as response: @@ -196,12 +202,11 @@ def set_slot( def get_public_key_no_confirmation( self, path: str, - curve: CurveChoice, - hash_t: HashType, + crypto_options: CryptoOptions, ) -> RAPDU: """ APDU get public key - no confirmation """ - data_path= _format_apdu_data(curve, hash_t, path) + data_path= _format_apdu_data(crypto_options, path) return self.backend.exchange(cla=ClaType.CLA_APP, ins=InsType.GET_PUBKEY, p1=P1.P1_NO_CONFIRM, @@ -211,12 +216,11 @@ def get_public_key_no_confirmation( def get_public_key_with_confirmation( self, path: str, - curve: CurveChoice, - hash_t: HashType, + crypto_options: CryptoOptions, ) -> Generator[None, None, None]: """ APDU get public key - with confirmation """ - data_path= _format_apdu_data(curve, hash_t, path) + data_path= _format_apdu_data(crypto_options, path) with self.backend.exchange_async(cla=ClaType.CLA_APP, ins=InsType.GET_PUBKEY, p1=P1.P1_CONFIRM, @@ -227,14 +231,13 @@ def get_public_key_with_confirmation( def sign_tx( self, path: str, - curve: CurveChoice, + crypto_options: CryptoOptions, transaction: bytes, - hash_t: HashType, hint: str = "" ) -> Generator[None, None, None]: """ APDU sign transaction """ - data_path = _format_apdu_data(curve, hash_t, path) + data_path = _format_apdu_data(crypto_options, path) self.backend.exchange(cla=ClaType.CLA_APP, ins=InsType.SIGN, p1=P1.P1_INIT, diff --git a/tests/test_app_mainmenu.py b/tests/test_app_mainmenu.py index d99b4406..f950583b 100644 --- a/tests/test_app_mainmenu.py +++ b/tests/test_app_mainmenu.py @@ -1,4 +1,4 @@ -from application_client.flow_command_sender import FlowCommandSender, HashType +from application_client.flow_command_sender import FlowCommandSender, HashType, CryptoOptions from ragger.navigator import NavIns, NavInsID from ragger.bip import CurveChoice @@ -55,12 +55,11 @@ def test_app_mainmenu(firmware, backend, navigator, test_name): screen_change_before_first_instruction=False) # Send the APDU - Set slot - hash_t = HashType.HASH_SHA2 + crypto_options = CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2) address = "e467b9dd11fa00df" path = "m/44'/539'/513'/0/0" - curve = CurveChoice.Secp256k1 part += 1 - util_set_slot(client, firmware, navigator, f"{test_name}/part{part}", 0, curve, hash_t, address, path) + util_set_slot(client, firmware, navigator, f"{test_name}/part{part}", 0, crypto_options, address, path) # Navigate in the main menu, click "View address" if firmware.device.startswith("nano"): diff --git a/tests/test_pubkey_cmd.py b/tests/test_pubkey_cmd.py index 5526f8d2..95c086a7 100644 --- a/tests/test_pubkey_cmd.py +++ b/tests/test_pubkey_cmd.py @@ -1,6 +1,6 @@ import pytest -from application_client.flow_command_sender import FlowCommandSender, Errors, HashType +from application_client.flow_command_sender import FlowCommandSender, Errors, HashType, CryptoOptions from application_client.flow_response_unpacker import unpack_get_public_key_response from ragger.bip import calculate_public_key_and_chaincode, CurveChoice @@ -34,7 +34,7 @@ def test_get_public_key_no_confirm(backend): # Send the APDU and check the results for path in path_list: for curve in curve_list: - _ = util_check_pub_key(client, path, curve) + _ = util_check_pub_key(client, path, CryptoOptions(curve, HashType.HASH_SHA2)) def test_get_public_key_slot(firmware, backend, navigator, test_name): @@ -46,6 +46,9 @@ def test_get_public_key_slot(firmware, backend, navigator, test_name): slot = 0 curve0 = CurveChoice.Secp256k1 curve1 = CurveChoice.Nist256p1 + options0 = CryptoOptions(curve0, HashType.HASH_SHA2) + options1 = CryptoOptions(curve0, HashType.HASH_SHA3) + options2 = CryptoOptions(curve1, HashType.HASH_SHA2) address = "e467b9dd11fa00de" path0 = "m/44'/539'/513'/0/0" path1 = "m/44'/539'/513'/0/1" @@ -53,22 +56,22 @@ def test_get_public_key_slot(firmware, backend, navigator, test_name): # Send the APDU and check the results # Call get_public_key when slot is empty - _ = util_check_pub_key(client, path0, curve0) + _ = util_check_pub_key(client, path0, options0) part = 0 # Set_slot to some other path - util_set_slot(client, firmware, navigator, f"{test_name}/part{part}", slot, curve0, HashType.HASH_SHA2, address, path1) + util_set_slot(client, firmware, navigator, f"{test_name}/part{part}", slot, options0, address, path1) # Call get_public_key for different path values path_list = [path0, path1] for path in path_list: - _ = util_check_pub_key(client, path, curve0) + _ = util_check_pub_key(client, path, options0) # Call get_public_key for other path - but hashes do not match - does not matter - _ = util_check_pub_key(client, path1, curve0, HashType.HASH_SHA3) + _ = util_check_pub_key(client, path1, options1) # Call get_public_key for other path - but curves do not match - warning - _ = util_check_pub_key(client, path1, curve1) + _ = util_check_pub_key(client, path1, options2) # Clean Slot part += 1 @@ -83,14 +86,8 @@ def test_get_public_key_expert(self, firmware, backend, navigator, test_name): client = FlowCommandSender(backend) # Test parameters test_cfg = [ - { - "curve": CurveChoice.Secp256k1, - "hash": HashType.HASH_SHA2, - }, - { - "curve": CurveChoice.Nist256p1, - "hash": HashType.HASH_SHA3, - }, + CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2), + CryptoOptions(CurveChoice.Nist256p1, HashType.HASH_SHA3), ] path = "m/44'/539'/513'/0/0" @@ -99,7 +96,7 @@ def test_get_public_key_expert(self, firmware, backend, navigator, test_name): # Send the APDU and check the results for cfg in test_cfg: - _ = util_check_pub_key(client, path, cfg["curve"], cfg["hash"]) + _ = util_check_pub_key(client, path, cfg) def test_get_public_key_confirm_accepted(firmware, backend, navigator, test_name): @@ -109,11 +106,10 @@ def test_get_public_key_confirm_accepted(firmware, backend, navigator, test_name client = FlowCommandSender(backend) # Test parameters path = "m/44'/539'/0'/0/0" - curve = CurveChoice.Secp256k1 - hash_t = HashType.HASH_SHA2 + options = CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2) # Send the APDU (Asynchronous) - with client.get_public_key_with_confirmation(path, curve, hash_t): + with client.get_public_key_with_confirmation(path, options): util_navigate(firmware, navigator, test_name, "APPROVE_PUBKEY") # Check the status (Asynchronous) @@ -123,7 +119,7 @@ def test_get_public_key_confirm_accepted(firmware, backend, navigator, test_name # Parse the response public_key = unpack_get_public_key_response(response.data) # Compute the reference data - ref_public_key, _ = calculate_public_key_and_chaincode(curve, path, OPTIONAL.CUSTOM_SEED) + ref_public_key, _ = calculate_public_key_and_chaincode(options.curve, path, OPTIONAL.CUSTOM_SEED) # Check expected value assert public_key == ref_public_key @@ -135,12 +131,11 @@ def test_get_public_key_confirm_refused(firmware, backend, navigator, test_name) client = FlowCommandSender(backend) # Test parameters path = "m/44'/1'/0'/0/0" - curve = CurveChoice.Secp256k1 - hash_t = HashType.HASH_SHA2 + options = CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2) # Send the APDU (Asynchronous) with pytest.raises(ExceptionRAPDU) as err: - with client.get_public_key_with_confirmation(path, curve, hash_t): + with client.get_public_key_with_confirmation(path, options): util_navigate(firmware, navigator, test_name, "REJECT_PUBKEY") # Assert we have received a refusal diff --git a/tests/test_sign_cmd.py b/tests/test_sign_cmd.py index e16941f6..5684440d 100644 --- a/tests/test_sign_cmd.py +++ b/tests/test_sign_cmd.py @@ -2,7 +2,7 @@ import pytest import re -from application_client.flow_command_sender import FlowCommandSender, Errors, HashType, ClaType, InsType, P1 +from application_client.flow_command_sender import FlowCommandSender, Errors, HashType, ClaType, InsType, P1, CryptoOptions from application_client.flow_response_unpacker import unpack_sign_tx_response from application_client.txMerkleTree import merkleTree, merkleIndex @@ -27,21 +27,20 @@ def _check_transaction( test_name: Path, transaction: str, path: str, - curve: CurveChoice, - hash_t: HashType, + crypto_options: CryptoOptions, signable_type: str, timeout: int = 300, ) -> None: """ Check the transaction in confirmation mode when user accepts """ # Retrieve and Check the public key - public_key = util_check_pub_key(client, path, curve, hash_t) + public_key = util_check_pub_key(client, path, crypto_options) # Convert message to bytes message = bytes.fromhex(transaction) # Send the APDU (Asynchronous) - with client.sign_tx(path, curve, message, hash_t, signable_type): + with client.sign_tx(path, crypto_options, message, signable_type): util_navigate(firmware, navigator, test_name, "APPROVE_SIGN", timeout) # Send the APDU (Asynchronous) @@ -51,7 +50,7 @@ def _check_transaction( # Parse the response _, der_sig = unpack_sign_tx_response(response.data) # Check the signature - util_check_signature(public_key, der_sig, message, curve, hash_t, signable_type) + util_check_signature(public_key, der_sig, message, crypto_options, signable_type) def get_tx_and_hash(titles, network): # Retrieve FA.01, FA.02, FA.03 from manifest @@ -184,7 +183,7 @@ def test_transaction_params(firmware, backend, navigator, test_name): for curve in curve_list: for hash_t in hash_list: part += 1 - _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction[0], path, curve, hash_t, transaction[1]) + _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction[0], path, CryptoOptions(curve, hash_t), transaction[1]) class Test_EXPERT(): @@ -198,14 +197,8 @@ def test_transaction_expert(self, firmware, backend, navigator, test_name): # Test parameters path: str = "m/44'/539'/0'/0/0" test_cfg = [ - { - "curve": CurveChoice.Secp256k1, - "hash": HashType.HASH_SHA2, - }, - { - "curve": CurveChoice.Nist256p1, - "hash": HashType.HASH_SHA3, - }, + CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2), + CryptoOptions(CurveChoice.Nist256p1, HashType.HASH_SHA3), ] # Retrieve FA.03 from manifest @@ -221,7 +214,7 @@ def test_transaction_expert(self, firmware, backend, navigator, test_name): # Send the APDU and check the results for cfg in test_cfg: part += 1 - _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, path, cfg["curve"], cfg["hash"], txHash) + _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, path, cfg, txHash) def test_transaction_slot(firmware, backend, navigator, test_name): @@ -233,7 +226,7 @@ def test_transaction_slot(firmware, backend, navigator, test_name): path: str = "m/44'/539'/771'/0/0" bad_path: str = "m/44'/539'/771'/0/1" curve: CurveChoice = CurveChoice.Nist256p1 - hash_t: HashType = HashType.HASH_SHA3 + crypto_options: CryptoOptions = CryptoOptions(curve, HashType.HASH_SHA3) bad_hash: HashType = HashType.HASH_SHA2 slot = 0 address = "f8d6e0586b0a20c7" @@ -245,19 +238,19 @@ def test_transaction_slot(firmware, backend, navigator, test_name): # Send the APDU and check the results part = 0 - _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, path, curve, hash_t, scriptHash) + _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, path, crypto_options, scriptHash) # Set slot to correct path correct address, part += 1 - util_set_slot(client, firmware, navigator, f"{test_name}/part{part}", slot, curve, hash_t, address, path) + util_set_slot(client, firmware, navigator, f"{test_name}/part{part}", slot, crypto_options, address, path) # Sign the Tx again - incorrect hd path part += 1 - _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, bad_path, curve, hash_t, scriptHash) + _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, bad_path, crypto_options, scriptHash) # Sign the Tx again - correct path part += 1 - _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, path, curve, hash_t, scriptHash) + _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, path, crypto_options, scriptHash) # f19c161bc24cf4b4 - used as incorrect address; f8d6e0586b0a20c7 - correct one print(transaction) @@ -285,11 +278,11 @@ def test_transaction_slot(firmware, backend, navigator, test_name): # Send the APDU and check the results for blob in transactions: part += 1 - _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", blob, path, curve, hash_t, scriptHash) + _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", blob, path, crypto_options, scriptHash) # sign the Tx again - correct path - wrong hash part += 1 - _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, path, curve, bad_hash, scriptHash) + _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", transaction, path, CryptoOptions(curve, bad_hash), scriptHash) # Now delete the slot so that the next test starts in a clean state util_set_slot(client, firmware, navigator, test_name, slot) @@ -302,15 +295,14 @@ def test_transaction_invalid(firmware, backend, navigator, test_name): client = FlowCommandSender(backend) # Test parameters path: str = "m/44'/539'/513'/0/0" - curve: CurveChoice = CurveChoice.Secp256k1 - hash_t: HashType = HashType.HASH_SHA2 + crypto_options: CryptoOptions = CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2) # Prepare an invalid message bad_message = "1234567890" transaction = bad_message.encode("utf-8").hex() # Send the APDU and check the results try: - _check_transaction(client, firmware, navigator, test_name, transaction, path, curve, hash_t, "", 5) + _check_transaction(client, firmware, navigator, test_name, transaction, path, crypto_options, "", 5) except TimeoutError: pass @@ -322,8 +314,7 @@ def test_transaction_refused(firmware, backend, navigator, test_name): client = FlowCommandSender(backend) # Test parameters path: str = "m/44'/539'/0'/0/0" - curve: CurveChoice = CurveChoice.Nist256p1 - hash_t = HashType.HASH_SHA2 + crypto_options: CryptoOptions = CryptoOptions(CurveChoice.Nist256p1, HashType.HASH_SHA2) # Retrieve FA.01 from manifest transactionsAndScriptHashes = get_tx_and_hash(("FA.01",), "Mainnet") @@ -335,7 +326,7 @@ def test_transaction_refused(firmware, backend, navigator, test_name): # Send the APDU (Asynchronous) with pytest.raises(ExceptionRAPDU) as err: - with client.sign_tx(path, curve, message, hash_t, scriptHash): + with client.sign_tx(path, crypto_options, message, scriptHash): util_navigate(firmware, navigator, test_name, "REJECT_SIGN") # Assert we have received a refusal @@ -350,8 +341,7 @@ def test_transaction_manifest(firmware, backend, navigator, test_name): client = FlowCommandSender(backend) # Test parameters path: str = "m/44'/539'/0'/0/0" - curve: CurveChomanifestice = CurveChoice.Nist256p1 - hash_t = HashType.HASH_SHA3 + crypto_options: CryptoOptions = CryptoOptions(CurveChoice.Nist256p1, HashType.HASH_SHA3) with open(MANIFEST_FILE) as json_file: transactions = json.load(json_file) @@ -363,7 +353,7 @@ def test_transaction_manifest(firmware, backend, navigator, test_name): if len(title_split) > 3 and title_split[-2] == "-": tx_name = tx_name+"-"+title_split[-1] chain = transaction["chainID"] - _check_transaction(client, firmware, navigator, f"{test_name}/{tx_name}-{chain}", transaction["encodedTransactionEnvelopeHex"], path, curve, hash_t, transaction["hash"]) + _check_transaction(client, firmware, navigator, f"{test_name}/{tx_name}-{chain}", transaction["encodedTransactionEnvelopeHex"], path, crypto_options, transaction["hash"]) class Test_MESSAGE(): def test_message_normal(self, firmware, backend, navigator, test_name): @@ -375,26 +365,22 @@ def test_message_normal(self, firmware, backend, navigator, test_name): path: str = "m/44'/539'/0'/0/0" test_cfg = [ { - "curve": CurveChoice.Secp256k1, - "hash": HashType.HASH_SHA2, + "options": CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2), # "This is a nice message that has only displayable characters and is short enough to be displayed" "message": "546869732069732061206e696365206d657373616765207468617420686173206f6e6c7920646973706c617961626c65206368617261637465727320616e642069732073686f727420656e6f75676820746f20626520646973706c61796564" }, { - "curve": CurveChoice.Secp256k1, - "hash": HashType.HASH_SHA2, + "options": CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2), # Message too long to be displayed normally "message": 1000*"40" }, { - "curve": CurveChoice.Nist256p1, - "hash": HashType.HASH_SHA3, + "options": CryptoOptions(CurveChoice.Nist256p1, HashType.HASH_SHA3), # "This is a nice message that has only displayable characters and is short enough to be displayed" "message": "546869732069732061206e696365206d657373616765207468617420686173206f6e6c7920646973706c617961626c65206368617261637465727320616e642069732073686f727420656e6f75676820746f20626520646973706c61796564" }, { - "curve": CurveChoice.Secp256k1, - "hash": HashType.HASH_SHA2, + "options": CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2), # Message too long to be displayed normally "message": 1000*"40" }, @@ -404,7 +390,7 @@ def test_message_normal(self, firmware, backend, navigator, test_name): # Send the APDU and check the results for i,cfg in enumerate(test_cfg): - _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", cfg["message"], path, cfg["curve"], cfg["hash"], "message") + _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", cfg["message"], path, cfg["options"], "message") part += 1 if i == 0 or i == 3: # Navigate in the main menu to change to expert mode @@ -421,14 +407,12 @@ def test_message_invalid(self, firmware, backend, navigator, test_name): path: str = "m/44'/539'/0'/0/0" test_cfg = [ { - "curve": CurveChoice.Secp256k1, - "hash": HashType.HASH_SHA2, + "options": CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2), # Message with non-displayable characters "message": "4d657373616765ee" }, { - "curve": CurveChoice.Secp256k1, - "hash": HashType.HASH_SHA2, + "options": CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2), # Message too long to display and expert mode is off "message": 1000*"40" }, @@ -443,7 +427,7 @@ def test_message_invalid(self, firmware, backend, navigator, test_name): # Send the APDU (Asynchronous) with pytest.raises(ExceptionRAPDU) as err: - with client.sign_tx(path, cfg["curve"], message, cfg["hash"], "message"): + with client.sign_tx(path, cfg["options"], message, "message"): pass assert(str(err) == "") part += 1 @@ -459,14 +443,13 @@ def test_arbitrary_transaction_signing_fail_in_no_expert_mode(self, firmware, ba path: str = "m/44'/539'/0'/0/0" cfg = { "tx": "f906e9f906e5b90423696d706f727420466c6f775374616b696e67436f6c6c656374696f6e2066726f6d203078386430653837623635313539616536330a0a2f2f2f20437265617465732061206d616368696e65206163636f756e7420666f722061206e6f6465207468617420697320616c726561647920696e20746865207374616b696e6720636f6c6c656374696f6e0a2f2f2f20616e642061646473207075626c6963206b65797320746f20746865206e6577206163636f756e740a0a7472616e73616374696f6e286e6f646549443a20537472696e672c207075626c69634b6579733a205b537472696e675d29207b0a202020200a202020206c6574207374616b696e67436f6c6c656374696f6e5265663a2026466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e0a0a2020202070726570617265286163636f756e743a20417574684163636f756e7429207b0a202020202020202073656c662e7374616b696e67436f6c6c656374696f6e526566203d206163636f756e742e626f72726f773c26466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e3e2866726f6d3a20466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e53746f7261676550617468290a2020202020202020202020203f3f2070616e69632822436f756c64206e6f7420626f72726f772072656620746f205374616b696e67436f6c6c656374696f6e22290a0a20202020202020206966206c6574206d616368696e654163636f756e74203d2073656c662e7374616b696e67436f6c6c656374696f6e5265662e6372656174654d616368696e654163636f756e74466f724578697374696e674e6f6465286e6f646549443a206e6f646549442c2070617965723a206163636f756e7429207b0a2020202020202020202020206966207075626c69634b657973203d3d206e696c207c7c207075626c69634b657973212e6c656e677468203d3d2030207b0a2020202020202020202020202020202070616e6963282243616e6e6f742070726f76696465207a65726f206b65797320666f7220746865206d616368696e65206163636f756e7422290a2020202020202020202020207d0a202020202020202020202020666f72206b657920696e207075626c69634b65797321207b0a202020202020202020202020202020206d616368696e654163636f756e742e6164645075626c69634b6579286b65792e6465636f64654865782829290a2020202020202020202020207d0a20202020202020207d20656c7365207b0a20202020202020202020202070616e69632822436f756c64206e6f74206372656174652061206d616368696e65206163636f756e7420666f7220746865206e6f646522290a20202020202020207d0a202020207d0a7d0af9027cb85c7b2274797065223a22537472696e67222c2276616c7565223a2238383534393333356531646237623562343663326164353864646237306237613435653737306363356665373739363530626132366631306536626165356536227db9021b7b2274797065223a224172726179222c2276616c7565223a5b7b2274797065223a22537472696e67222c2276616c7565223a2266383435623834303665346634336637396433633164386361636233643566336537616565646232396665616562343535396664623731613937653266643034333835363533313065383736373030333564383362633130666536376665333134646261353336336338313635343539356436343838346231656361643135313261363465363565303230313634227d2c7b2274797065223a22537472696e67222c2276616c7565223a2266383435623834303665346634336637396433633164386361636233643566336537616565646232396665616562343535396664623731613937653266643034333835363533313065383736373030333564383362633130666536376665333134646261353336336338313635343539356436343838346231656361643135313261363465363565303230313634227d2c7b2274797065223a22537472696e67222c2276616c7565223a2266383435623834303665346634336637396433633164386361636233643566336537616565646232396665616562343535396664623731613937653266643034333835363533313065383736373030333564383362633130666536376665333134646261353336336338313635343539356436343838346231656361643135313261363465363565303230313634227d5d7da0f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b2a88f19c161bc24cf4b4040a88f19c161bc24cf4b4c988f19c161bc24cf4b4c0", - "curve": CurveChoice.Secp256k1, - "hash": HashType.HASH_SHA2, + "options": CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2), } part = 0 # Send the APDU and check the results with pytest.raises(ExceptionRAPDU) as err: - with client.sign_tx(path, cfg["curve"], bytes.fromhex(cfg["tx"]), cfg["hash"], "arbitrary"): + with client.sign_tx(path, cfg["options"], bytes.fromhex(cfg["tx"]), "arbitrary"): pass assert(str(err) == "") @@ -480,33 +463,27 @@ def test_arbitrary_transaction_signing_expert(self, firmware, backend, navigator test_cfg = [ { "tx": "f906e9f906e5b90423696d706f727420466c6f775374616b696e67436f6c6c656374696f6e2066726f6d203078386430653837623635313539616536330a0a2f2f2f20437265617465732061206d616368696e65206163636f756e7420666f722061206e6f6465207468617420697320616c726561647920696e20746865207374616b696e6720636f6c6c656374696f6e0a2f2f2f20616e642061646473207075626c6963206b65797320746f20746865206e6577206163636f756e740a0a7472616e73616374696f6e286e6f646549443a20537472696e672c207075626c69634b6579733a205b537472696e675d29207b0a202020200a202020206c6574207374616b696e67436f6c6c656374696f6e5265663a2026466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e0a0a2020202070726570617265286163636f756e743a20417574684163636f756e7429207b0a202020202020202073656c662e7374616b696e67436f6c6c656374696f6e526566203d206163636f756e742e626f72726f773c26466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e3e2866726f6d3a20466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e53746f7261676550617468290a2020202020202020202020203f3f2070616e69632822436f756c64206e6f7420626f72726f772072656620746f205374616b696e67436f6c6c656374696f6e22290a0a20202020202020206966206c6574206d616368696e654163636f756e74203d2073656c662e7374616b696e67436f6c6c656374696f6e5265662e6372656174654d616368696e654163636f756e74466f724578697374696e674e6f6465286e6f646549443a206e6f646549442c2070617965723a206163636f756e7429207b0a2020202020202020202020206966207075626c69634b657973203d3d206e696c207c7c207075626c69634b657973212e6c656e677468203d3d2030207b0a2020202020202020202020202020202070616e6963282243616e6e6f742070726f76696465207a65726f206b65797320666f7220746865206d616368696e65206163636f756e7422290a2020202020202020202020207d0a202020202020202020202020666f72206b657920696e207075626c69634b65797321207b0a202020202020202020202020202020206d616368696e654163636f756e742e6164645075626c69634b6579286b65792e6465636f64654865782829290a2020202020202020202020207d0a20202020202020207d20656c7365207b0a20202020202020202020202070616e69632822436f756c64206e6f74206372656174652061206d616368696e65206163636f756e7420666f7220746865206e6f646522290a20202020202020207d0a202020207d0a7d0af9027cb85c7b2274797065223a22537472696e67222c2276616c7565223a2238383534393333356531646237623562343663326164353864646237306237613435653737306363356665373739363530626132366631306536626165356536227db9021b7b2274797065223a224172726179222c2276616c7565223a5b7b2274797065223a22537472696e67222c2276616c7565223a2266383435623834303665346634336637396433633164386361636233643566336537616565646232396665616562343535396664623731613937653266643034333835363533313065383736373030333564383362633130666536376665333134646261353336336338313635343539356436343838346231656361643135313261363465363565303230313634227d2c7b2274797065223a22537472696e67222c2276616c7565223a2266383435623834303665346634336637396433633164386361636233643566336537616565646232396665616562343535396664623731613937653266643034333835363533313065383736373030333564383362633130666536376665333134646261353336336338313635343539356436343838346231656361643135313261363465363565303230313634227d2c7b2274797065223a22537472696e67222c2276616c7565223a2266383435623834303665346634336637396433633164386361636233643566336537616565646232396665616562343535396664623731613937653266643034333835363533313065383736373030333564383362633130666536376665333134646261353336336338313635343539356436343838346231656361643135313261363465363565303230313634227d5d7da0f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b2a88f19c161bc24cf4b4040a88f19c161bc24cf4b4c988f19c161bc24cf4b4c0", - "curve": CurveChoice.Secp256k1, - "hash": HashType.HASH_SHA2, + "options": CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2), }, { "tx": "f904e6f904e2b90423696d706f727420466c6f775374616b696e67436f6c6c656374696f6e2066726f6d203078393565303139613137643065323364370a0a2f2f2f20437265617465732061206d616368696e65206163636f756e7420666f722061206e6f6465207468617420697320616c726561647920696e20746865207374616b696e6720636f6c6c656374696f6e0a2f2f2f20616e642061646473207075626c6963206b65797320746f20746865206e6577206163636f756e740a0a7472616e73616374696f6e286e6f646549443a20537472696e672c207075626c69634b6579733a205b537472696e675d29207b0a202020200a202020206c6574207374616b696e67436f6c6c656374696f6e5265663a2026466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e0a0a2020202070726570617265286163636f756e743a20417574684163636f756e7429207b0a202020202020202073656c662e7374616b696e67436f6c6c656374696f6e526566203d206163636f756e742e626f72726f773c26466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e3e2866726f6d3a20466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e53746f7261676550617468290a2020202020202020202020203f3f2070616e69632822436f756c64206e6f7420626f72726f772072656620746f205374616b696e67436f6c6c656374696f6e22290a0a20202020202020206966206c6574206d616368696e654163636f756e74203d2073656c662e7374616b696e67436f6c6c656374696f6e5265662e6372656174654d616368696e654163636f756e74466f724578697374696e674e6f6465286e6f646549443a206e6f646549442c2070617965723a206163636f756e7429207b0a2020202020202020202020206966207075626c69634b657973203d3d206e696c207c7c207075626c69634b657973212e6c656e677468203d3d2030207b0a2020202020202020202020202020202070616e6963282243616e6e6f742070726f76696465207a65726f206b65797320666f7220746865206d616368696e65206163636f756e7422290a2020202020202020202020207d0a202020202020202020202020666f72206b657920696e207075626c69634b65797321207b0a202020202020202020202020202020206d616368696e654163636f756e742e6164645075626c69634b6579286b65792e6465636f64654865782829290a2020202020202020202020207d0a20202020202020207d20656c7365207b0a20202020202020202020202070616e69632822436f756c64206e6f74206372656174652061206d616368696e65206163636f756e7420666f7220746865206e6f646522290a20202020202020207d0a202020207d0a7d0af87ab85c7b2274797065223a22537472696e67222c2276616c7565223a2238383534393333356531646237623562343663326164353864646237306237613435653737306363356665373739363530626132366631306536626165356536227d9b7b2274797065223a224172726179222c2276616c7565223a5b5d7da0f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b2a8899a8ac2c71d4f6bd040a8899a8ac2c71d4f6bdc98899a8ac2c71d4f6bdc0", - "curve": CurveChoice.Nist256p1, - "hash": HashType.HASH_SHA3, + "options": CryptoOptions(CurveChoice.Nist256p1, HashType.HASH_SHA3), }, { "tx": "f9039df90399b902a4696d706f727420466c6f775374616b696e67436f6c6c656374696f6e2066726f6d203078393565303139613137643065323364370a0a2f2f2f20526571756573747320756e7374616b696e6720666f722074686520737065636966696564206e6f6465206f722064656c656761746f7220696e20746865207374616b696e6720636f6c6c656374696f6e0a0a7472616e73616374696f6e286e6f646549443a20537472696e672c2064656c656761746f7249443a2055496e7433323f2c20616d6f756e743a2055466978363429207b0a202020200a202020206c6574207374616b696e67436f6c6c656374696f6e5265663a2026466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e0a0a2020202070726570617265286163636f756e743a20417574684163636f756e7429207b0a202020202020202073656c662e7374616b696e67436f6c6c656374696f6e526566203d206163636f756e742e626f72726f773c26466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e3e2866726f6d3a20466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e53746f7261676550617468290a2020202020202020202020203f3f2070616e69632822436f756c64206e6f7420626f72726f772072656620746f205374616b696e67436f6c6c656374696f6e22290a202020207d0a0a2020202065786563757465207b0a202020202020202073656c662e7374616b696e67436f6c6c656374696f6e5265662e72657175657374556e7374616b696e67286e6f646549443a206e6f646549442c2064656c656761746f7249443a2064656c656761746f7249442c20616d6f756e743a20616d6f756e74290a202020207d0a7d0af8b0b85c7b2274797065223a22537472696e67222c2276616c7565223a2238383534393333356531646237623562343663326164353864646237306237613435653737306363356665373739363530626132366631306536626165356536227da07b2274797065223a224f7074696f6e616c222c2276616c7565223a6e756c6c7db07b2274797065223a22554669783634222c2276616c7565223a2239323233333732303336382e3534373735383038227da0f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b2a8899a8ac2c71d4f6bd040a8899a8ac2c71d4f6bdc98899a8ac2c71d4f6bdc0", - "curve": CurveChoice.Secp256k1, - "hash": HashType.HASH_SHA2, + "options": CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2), }, { "tx": "f903b8f903b4b902a4696d706f727420466c6f775374616b696e67436f6c6c656374696f6e2066726f6d203078386430653837623635313539616536330a0a2f2f2f20526571756573747320756e7374616b696e6720666f722074686520737065636966696564206e6f6465206f722064656c656761746f7220696e20746865207374616b696e6720636f6c6c656374696f6e0a0a7472616e73616374696f6e286e6f646549443a20537472696e672c2064656c656761746f7249443a2055496e7433323f2c20616d6f756e743a2055466978363429207b0a202020200a202020206c6574207374616b696e67436f6c6c656374696f6e5265663a2026466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e0a0a2020202070726570617265286163636f756e743a20417574684163636f756e7429207b0a202020202020202073656c662e7374616b696e67436f6c6c656374696f6e526566203d206163636f756e742e626f72726f773c26466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e3e2866726f6d3a20466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e53746f7261676550617468290a2020202020202020202020203f3f2070616e69632822436f756c64206e6f7420626f72726f772072656620746f205374616b696e67436f6c6c656374696f6e22290a202020207d0a0a2020202065786563757465207b0a202020202020202073656c662e7374616b696e67436f6c6c656374696f6e5265662e72657175657374556e7374616b696e67286e6f646549443a206e6f646549442c2064656c656761746f7249443a2064656c656761746f7249442c20616d6f756e743a20616d6f756e74290a202020207d0a7d0af8cbb85c7b2274797065223a22537472696e67222c2276616c7565223a2238383534393333356531646237623562343663326164353864646237306237613435653737306363356665373739363530626132366631306536626165356536227db83a7b2274797065223a224f7074696f6e616c222c2276616c7565223a7b2274797065223a2255496e743332222c2276616c7565223a223432227d7db07b2274797065223a22554669783634222c2276616c7565223a2239323233333732303336382e3534373735383038227da0f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b2a88f19c161bc24cf4b4040a88f19c161bc24cf4b4c988f19c161bc24cf4b4c0", - "curve": CurveChoice.Secp256k1, - "hash": HashType.HASH_SHA2, + "options": CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2), }, { "tx": "f90864f90860b9058a696d706f72742043727970746f0a696d706f727420466c6f775374616b696e67436f6c6c656374696f6e2066726f6d203078393565303139613137643065323364370a0a2f2f2f2052656769737465727320612064656c656761746f7220696e20746865207374616b696e6720636f6c6c656374696f6e207265736f757263650a2f2f2f20666f722074686520737065636966696564206e6f646520696e666f726d6174696f6e20616e642074686520616d6f756e74206f6620746f6b656e7320746f20636f6d6d69740a0a7472616e73616374696f6e2869643a20537472696e672c0a202020202020202020202020726f6c653a2055496e74382c0a2020202020202020202020206e6574776f726b696e67416464726573733a20537472696e672c0a2020202020202020202020206e6574776f726b696e674b65793a20537472696e672c0a2020202020202020202020207374616b696e674b65793a20537472696e672c0a202020202020202020202020616d6f756e743a205546697836342c0a2020202020202020202020207075626c69634b6579733a205b43727970746f2e4b65794c697374456e7472795d3f29207b0a202020200a202020206c6574207374616b696e67436f6c6c656374696f6e5265663a2026466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e0a0a2020202070726570617265286163636f756e743a20417574684163636f756e7429207b0a202020202020202073656c662e7374616b696e67436f6c6c656374696f6e526566203d206163636f756e742e626f72726f773c26466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e3e2866726f6d3a20466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e53746f7261676550617468290a2020202020202020202020203f3f2070616e69632822436f756c64206e6f7420626f72726f772072656620746f205374616b696e67436f6c6c656374696f6e22290a0a20202020202020206966206c6574206d616368696e654163636f756e74203d2073656c662e7374616b696e67436f6c6c656374696f6e5265662e72656769737465724e6f6465280a20202020202020202020202069643a2069642c0a202020202020202020202020726f6c653a20726f6c652c0a2020202020202020202020206e6574776f726b696e67416464726573733a206e6574776f726b696e67416464726573732c0a2020202020202020202020206e6574776f726b696e674b65793a206e6574776f726b696e674b65792c0a2020202020202020202020207374616b696e674b65793a207374616b696e674b65792c0a202020202020202020202020616d6f756e743a20616d6f756e742c0a20202020202020202020202070617965723a206163636f756e7429200a20202020202020207b0a2020202020202020202020206966207075626c69634b657973203d3d206e696c207c7c207075626c69634b657973212e6c656e677468203d3d2030207b0a2020202020202020202020202020202070616e6963282243616e6e6f742070726f76696465207a65726f206b65797320666f7220746865206d616368696e65206163636f756e7422290a2020202020202020202020207d0a202020202020202020202020666f72206b657920696e207075626c69634b65797321207b0a202020202020202020202020202020206d616368696e654163636f756e742e6b6579732e616464287075626c69634b65793a206b65792e7075626c69634b65792c2068617368416c676f726974686d3a206b65792e68617368416c676f726974686d2c207765696768743a206b65792e776569676874290a2020202020202020202020207d0a20202020202020207d0a202020207d0a7d0af90290b85c7b2274797065223a22537472696e67222c2276616c7565223a2238383534393333356531646237623562343663326164353864646237306237613435653737306363356665373739363530626132366631306536626165356536227d9c7b2274797065223a2255496e7438222c2276616c7565223a2231227daf7b2274797065223a22537472696e67222c2276616c7565223a22666c6f772d6e6f64652e746573743a33353639227db89c7b2274797065223a22537472696e67222c2276616c7565223a223133343833303762633737633638386538303034396465396430383161613039373535646133336536393937363035666130353964623231343466633835653536306362653666376461386437346234353366353931363631386362386664333932633264623835366633653738323231646336386462316231643931346534227db8dc7b2274797065223a22537472696e67222c2276616c7565223a22396539616530643634356664356664393035303739326530623064616138326363313638366439313333616661306638316137383462333735633432616534383536376431353435653761396531393635663263316133326637336366383537356562623761393637663665346431303464326466373865623862653430393133356431326461303439396238613030373731663634326331623963343933393766323262343430343339663033366333626465653832663533303964616233227db07b2274797065223a22554669783634222c2276616c7565223a2239323233333732303336382e3534373735383038227db77b2274797065223a224f7074696f6e616c222c2276616c7565223a7b2274797065223a224172726179222c2276616c7565223a5b5d7d7da0f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b2a8899a8ac2c71d4f6bd040a8899a8ac2c71d4f6bdc98899a8ac2c71d4f6bdc0", - "curve": CurveChoice.Secp256k1, - "hash": HashType.HASH_SHA2, + "options": CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2), }, { "tx": "f908b9f908b5b90534696d706f727420466c6f775374616b696e67436f6c6c656374696f6e2066726f6d203078393565303139613137643065323364370a0a2f2f2f2052656769737465727320612064656c656761746f7220696e20746865207374616b696e6720636f6c6c656374696f6e207265736f757263650a2f2f2f20666f722074686520737065636966696564206e6f646520696e666f726d6174696f6e20616e642074686520616d6f756e74206f6620746f6b656e7320746f20636f6d6d69740a0a7472616e73616374696f6e2869643a20537472696e672c0a202020202020202020202020726f6c653a2055496e74382c0a2020202020202020202020206e6574776f726b696e67416464726573733a20537472696e672c0a2020202020202020202020206e6574776f726b696e674b65793a20537472696e672c0a2020202020202020202020207374616b696e674b65793a20537472696e672c0a202020202020202020202020616d6f756e743a205546697836342c0a2020202020202020202020207075626c69634b6579733a205b537472696e675d3f29207b0a202020200a202020206c6574207374616b696e67436f6c6c656374696f6e5265663a2026466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e0a0a2020202070726570617265286163636f756e743a20417574684163636f756e7429207b0a202020202020202073656c662e7374616b696e67436f6c6c656374696f6e526566203d206163636f756e742e626f72726f773c26466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e3e2866726f6d3a20466c6f775374616b696e67436f6c6c656374696f6e2e5374616b696e67436f6c6c656374696f6e53746f7261676550617468290a2020202020202020202020203f3f2070616e69632822436f756c64206e6f7420626f72726f772072656620746f205374616b696e67436f6c6c656374696f6e22290a0a20202020202020206966206c6574206d616368696e654163636f756e74203d2073656c662e7374616b696e67436f6c6c656374696f6e5265662e72656769737465724e6f6465280a20202020202020202020202069643a2069642c0a202020202020202020202020726f6c653a20726f6c652c0a2020202020202020202020206e6574776f726b696e67416464726573733a206e6574776f726b696e67416464726573732c0a2020202020202020202020206e6574776f726b696e674b65793a206e6574776f726b696e674b65792c0a2020202020202020202020207374616b696e674b65793a207374616b696e674b65792c0a202020202020202020202020616d6f756e743a20616d6f756e742c0a20202020202020202020202070617965723a206163636f756e7429200a20202020202020207b0a2020202020202020202020206966207075626c69634b657973203d3d206e696c207c7c207075626c69634b657973212e6c656e677468203d3d2030207b0a2020202020202020202020202020202070616e6963282243616e6e6f742070726f76696465207a65726f206b65797320666f7220746865206d616368696e65206163636f756e7422290a2020202020202020202020207d0a202020202020202020202020666f72206b657920696e207075626c69634b65797321207b0a202020202020202020202020202020206d616368696e654163636f756e742e6164645075626c69634b6579286b65792e6465636f64654865782829290a2020202020202020202020207d0a20202020202020207d0a202020207d0a7d0af9033bb85c7b2274797065223a22537472696e67222c2276616c7565223a2238383534393333356531646237623562343663326164353864646237306237613435653737306363356665373739363530626132366631306536626165356536227d9c7b2274797065223a2255496e7438222c2276616c7565223a2231227daf7b2274797065223a22537472696e67222c2276616c7565223a22666c6f772d6e6f64652e746573743a33353639227db89c7b2274797065223a22537472696e67222c2276616c7565223a223133343833303762633737633638386538303034396465396430383161613039373535646133336536393937363035666130353964623231343466633835653536306362653666376461386437346234353366353931363631386362386664333932633264623835366633653738323231646336386462316231643931346534227db8dc7b2274797065223a22537472696e67222c2276616c7565223a22396539616530643634356664356664393035303739326530623064616138326363313638366439313333616661306638316137383462333735633432616534383536376431353435653761396531393635663263316133326637336366383537356562623761393637663665346431303464326466373865623862653430393133356431326461303439396238613030373731663634326331623963343933393766323262343430343339663033366333626465653832663533303964616233227db07b2274797065223a22554669783634222c2276616c7565223a2239323233333732303336382e3534373735383038227db8e17b2274797065223a224f7074696f6e616c222c2276616c7565223a7b2274797065223a224172726179222c2276616c7565223a5b7b2274797065223a22537472696e67222c2276616c7565223a2266383435623834303665346634336637396433633164386361636233643566336537616565646232396665616562343535396664623731613937653266643034333835363533313065383736373030333564383362633130666536376665333134646261353336336338313635343539356436343838346231656361643135313261363465363565303230313634227d5d7d7da0f0e4c2f76c58916ec258f246851bea091d14d4247a2fc3e18694461b1816e13b2a8899a8ac2c71d4f6bd040a8899a8ac2c71d4f6bdc98899a8ac2c71d4f6bdc0", - "curve": CurveChoice.Secp256k1, - "hash": HashType.HASH_SHA2, + "options": CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2), }, ] @@ -517,5 +494,5 @@ def test_arbitrary_transaction_signing_expert(self, firmware, backend, navigator # Send the APDU and check the results for cfg in test_cfg: part += 1 - _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", cfg["tx"], path, cfg["curve"], cfg["hash"], "arbitrary") + _check_transaction(client, firmware, navigator, f"{test_name}/part{part}", cfg["tx"], path, cfg["options"], "arbitrary") diff --git a/tests/test_slots.py b/tests/test_slots.py index 2fbc4ce2..6062bc41 100644 --- a/tests/test_slots.py +++ b/tests/test_slots.py @@ -2,7 +2,7 @@ from typing import Tuple import pytest -from application_client.flow_command_sender import FlowCommandSender, Errors, HashType, MAX_SLOTS +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 @@ -13,7 +13,7 @@ from utils import util_set_slot, util_navigate -def _extract_option(option: bytes) -> Tuple[CurveChoice, HashType]: +def _extract_option(option: bytes) -> CryptoOptions: """ Extract curve and hash from options bytes array """ hash_value = int(option[0:2]) @@ -33,7 +33,7 @@ def _extract_option(option: bytes) -> Tuple[CurveChoice, HashType]: else: raise ValueError(f'Wrong Hash "{hash_value}"') - return curve, hash_t + return CryptoOptions(curve, hash_t) def _set_slot_and_check( @@ -42,15 +42,14 @@ def _set_slot_and_check( navigator: Navigator, test_name: Path, slot: int, - curve: CurveChoice, - hash_t: HashType, + 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, curve, hash_t, address, path) + util_set_slot(client, firmware, navigator, test_name, slot, crypto_options, address, path) # Send the APDU - Slot status response = client.get_slot_status() @@ -64,15 +63,15 @@ def _set_slot_and_check( # Parse the response ret_address, ret_path, ret_option = unpack_get_slot_response(response.data) - ret_curve, ret_hash = _extract_option(ret_option) + ret_option = _extract_option(ret_option) print(f" Address: {ret_address}") print(f" Path: {ret_path}") - print(f" Curve: {ret_curve}") - print(f" Hash: {ret_hash}") + print(f" Curve: {ret_option.curve}") + print(f" Hash: {ret_option.hash_t}") # Check expected value assert address == ret_address - assert curve == ret_curve + assert crypto_options == ret_option def test_get_slot_status(backend): @@ -115,24 +114,23 @@ def test_get_slot_accepted(firmware, backend, navigator, test_name): client = FlowCommandSender(backend) # Test parameters slot = 10 - hash_t = HashType.HASH_SHA2 address = "e467b9dd11fa00df" path = "m/44'/539'/513'/0/0" - curve = CurveChoice.Secp256k1 + 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, curve, hash_t, address, path + 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" - curve = CurveChoice.Nist256p1 + crypto_options2 = CryptoOptions(CurveChoice.Nist256p1, HashType.HASH_SHA2) part += 1 _set_slot_and_check( - client, firmware, navigator, f"{test_name}/part{part}", slot, curve, hash_t, address, path + client, firmware, navigator, f"{test_name}/part{part}", slot, crypto_options2, address, path ) # Clean Slot @@ -149,12 +147,11 @@ def test_get_slot_refused(firmware, backend, navigator, test_name): slot = 10 address = "e467b9dd11fa00df" path = "m/44'/539'/513'/0/0" - curve = CurveChoice.Secp256k1 - hash_t = HashType.HASH_SHA2 + 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, curve, hash_t): + with client.set_slot(slot, address, path, crypto_options): util_navigate(firmware, navigator, test_name, "REJECT_SLOT") # Assert we have received a refusal diff --git a/tests/utils.py b/tests/utils.py index 084d997c..d972b763 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -6,7 +6,7 @@ from ecdsa.keys import VerifyingKey from ecdsa.util import sigdecode_der -from application_client.flow_command_sender import FlowCommandSender, Errors, HashType +from application_client.flow_command_sender import FlowCommandSender, Errors, HashType, CryptoOptions from application_client.flow_response_unpacker import unpack_get_public_key_response from ragger.bip import calculate_public_key_and_chaincode, CurveChoice @@ -40,25 +40,24 @@ def util_check_signature( public_key: bytes, signature: bytes, message: bytes, - curve: CurveChoice, - hash_t: HashType, + options: CryptoOptions, signable_type: str ) -> bool: """ Check if the signature of a given message is valid """ # Convert curve value between bip to ecdsa ec_curve: Curve - if curve == CurveChoice.Nist256p1: + if options.curve == CurveChoice.Nist256p1: ec_curve = NIST256p - elif curve == CurveChoice.Secp256k1: + elif options.curve == CurveChoice.Secp256k1: ec_curve = SECP256k1 else: raise ValueError(f'Wrong Cruve "{curve}"') # Convert hash value to get the function - if hash_t == HashType.HASH_SHA2: + if options.hash_t == HashType.HASH_SHA2: hashfunc = sha256 - elif hash_t == HashType.HASH_SHA3: + elif options.hash_t == HashType.HASH_SHA3: hashfunc = sha3_256 else: raise ValueError(f'Wrong Hash "{hash_t}"') @@ -74,19 +73,18 @@ def util_check_signature( def util_check_pub_key( client: FlowCommandSender, path: str, - curve: CurveChoice, - hash_t: HashType = HashType.HASH_SHA2, + crypto_options: CryptoOptions, ) -> None: """ Retrieve and check the public key """ # Send the APDU (Asynchronous) - response = client.get_public_key_no_confirmation(path, curve, hash_t) + response = client.get_public_key_no_confirmation(path, crypto_options) assert response.status == Errors.SW_SUCCESS # Parse the response (Asynchronous) public_key = unpack_get_public_key_response(response.data) # Compute the reference data - ref_public_key, _ = calculate_public_key_and_chaincode(curve, path, OPTIONAL.CUSTOM_SEED) + ref_public_key, _ = calculate_public_key_and_chaincode(crypto_options.curve, path, OPTIONAL.CUSTOM_SEED) # Check expected value assert public_key == ref_public_key @@ -99,15 +97,14 @@ def util_set_slot( navigator: Navigator, test_name: Path, slot: int, - curve: CurveChoice = CurveChoice.Secp256k1, - hash_t: HashType = HashType.HASH_SHA2, + crypto_options: CryptoOptions = CryptoOptions(CurveChoice.Secp256k1, HashType.HASH_SHA2), address: str = "0000000000000000", path: str = "m/0/0/0/0/0", ) -> None: """ Function to Set Slot parameters """ # Send the APDU (Asynchronous) - with client.set_slot(slot, address, path, curve, hash_t): + with client.set_slot(slot, address, path, crypto_options): util_navigate(firmware, navigator, test_name, "APPROVE_SLOT") # Check the status (Asynchronous)