diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 316b267f9..7666345f4 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -134,8 +134,8 @@ jobs: - name: Run tests run: | - cd tests_liquid_main pip install --prefer-binary -r requirements.txt + cd tests_liquid_main PYTHONPATH=$PYTHONPATH:/speculos pytest --tb=short -v --device=${{matrix.model}} --speculos_api_port 5000 job_test_testnet: @@ -166,8 +166,8 @@ jobs: - name: Run tests run: | - cd tests_liquid_testnet pip install --prefer-binary -r requirements.txt + cd tests_liquid_testnet PYTHONPATH=$PYTHONPATH:/speculos pytest --tb=short -v --device=${{matrix.model}} --speculos_api_port 5000 job_test_python_lib_legacyapp: @@ -193,8 +193,8 @@ jobs: - name: Run tests run: | + pip install --prefer-binary -r requirements.txt cd bitcoin_client/tests - pip install -r requirements.txt PYTHONPATH=$PYTHONPATH:/speculos pytest --headless --timeout=300 --model=nanosp job_test_js_lib: diff --git a/Makefile b/Makefile index 4936a6246..ac3f69943 100644 --- a/Makefile +++ b/Makefile @@ -27,35 +27,9 @@ ifeq ($(BOLOS_SDK),) $(error Environment variable BOLOS_SDK is not set) endif -include $(BOLOS_SDK)/Makefile.defines - -# TODO: Compile with the right path restrictions -# -# The right path restriction would be something like -# --path "*'/0'" -# for mainnet, and -# --path "*'/1'" -# for testnet. -# -# That is, restrict the BIP-44 coin_type, but not the purpose. -# However, such wildcards are not currently supported by the OS. -# -# Note that the app still requires explicit user approval before exporting -# any xpub outside of a small set of allowed standard paths. - # Application allowed derivation curves. CURVE_APP_LOAD_PARAMS = secp256k1 -# Application allowed derivation paths. -# -# If there would be a dedicated SDK function returning master key -# fingerprint without the need to derive the root pubkey, the proper path -# configuration should be: -# -# PATH_APP_LOAD_PARAMS = "44'/1'" "48'/1'" "49'/1'" "84'/1'" "86'/1'" -# -PATH_APP_LOAD_PARAMS = "" - # Allowed SLIP21 paths PATH_SLIP21_APP_LOAD_PARAMS = "LEDGER-Wallet policy" @@ -83,94 +57,108 @@ VARIANT_VALUES = bitcoin_testnet bitcoin liquid_regtest liquid_testnet liquid ######################################## # Application custom permissions # ######################################## -HAVE_APPLICATION_FLAG_DERIVE_MASTER = 1 HAVE_APPLICATION_FLAG_GLOBAL_PIN = 1 HAVE_APPLICATION_FLAG_BOLOS_SETTINGS = 1 ifneq (,$(findstring bitcoin,$(COIN))) HAVE_APPLICATION_FLAG_LIBRARY = 1 endif - ifeq ($(COIN),bitcoin_testnet) + # Application allowed derivation paths (testnet). + PATH_APP_LOAD_PARAMS = "*/1'" -# Bitcoin testnet, no legacy support -DEFINES += BIP32_PUBKEY_VERSION=0x043587CF -DEFINES += BIP44_COIN_TYPE=1 -DEFINES += COIN_P2PKH_VERSION=111 -DEFINES += COIN_P2SH_VERSION=196 -DEFINES += COIN_NATIVE_SEGWIT_PREFIX=\"tb\" -DEFINES += COIN_COINID_SHORT=\"TEST\" + # Bitcoin testnet, no legacy support + DEFINES += BIP32_PUBKEY_VERSION=0x043587CF + DEFINES += BIP44_COIN_TYPE=1 + DEFINES += COIN_P2PKH_VERSION=111 + DEFINES += COIN_P2SH_VERSION=196 + DEFINES += COIN_NATIVE_SEGWIT_PREFIX=\"tb\" + DEFINES += COIN_COINID_SHORT=\"TEST\" -APPNAME = "Bitcoin Test" -DISPLAYED_APPNAME = "Bitcoin Testnet" + APPNAME = "Bitcoin Test" + DISPLAYED_APPNAME = "Bitcoin Testnet" else ifeq ($(COIN),bitcoin) + # Application allowed derivation paths (mainnet). + PATH_APP_LOAD_PARAMS = "*/0'" + + # the version for performance tests automatically approves all requests + # there is no reason to ever compile the mainnet app with this flag + ifneq ($(AUTOAPPROVE_FOR_PERF_TESTS),0) + $(error Use testnet app for performance tests) + endif -# Bitcoin mainnet, no legacy support -DEFINES += BIP32_PUBKEY_VERSION=0x0488B21E -DEFINES += BIP44_COIN_TYPE=0 -DEFINES += COIN_P2PKH_VERSION=0 -DEFINES += COIN_P2SH_VERSION=5 -DEFINES += COIN_NATIVE_SEGWIT_PREFIX=\"bc\" -DEFINES += COIN_COINID_SHORT=\"BTC\" + # Bitcoin mainnet, no legacy support + DEFINES += BIP32_PUBKEY_VERSION=0x0488B21E + DEFINES += BIP44_COIN_TYPE=0 + DEFINES += COIN_P2PKH_VERSION=0 + DEFINES += COIN_P2SH_VERSION=5 + DEFINES += COIN_NATIVE_SEGWIT_PREFIX=\"bc\" + DEFINES += COIN_COINID_SHORT=\"BTC\" -APPNAME = "Bitcoin" + APPNAME = "Bitcoin" else ifeq ($(COIN),liquid_regtest) - -# Liquid regtest -DEFINES += BIP32_PUBKEY_VERSION=0x043587CF -DEFINES += BIP32_PRIVKEY_VERSION=0x04358394 -DEFINES += BIP44_COIN_TYPE=1 -DEFINES += COIN_P2PKH_VERSION=111 -DEFINES += COIN_P2SH_VERSION=75 -DEFINES += COIN_PREFIX_CONFIDENTIAL=4 -DEFINES += HAVE_LIQUID -DEFINES += LIQUID_NET_REGTEST -DEFINES += COIN_COINID_SHORT=\"tLBTC\" -DEFINES += COIN_NATIVE_SEGWIT_PREFIX=\"ert\" -DEFINES += COIN_NATIVE_SEGWIT_PREFIX_CONFIDENTIAL=\"el\" - -APPNAME = "Liquid Regtest" + # Application allowed derivation paths (Liquid testnet/regtest). + PATH_APP_LOAD_PARAMS = "*/1'" # purpose=* / coin_type=Testnet(1) + + # Liquid regtest + DEFINES += BIP32_PUBKEY_VERSION=0x043587CF + DEFINES += BIP32_PRIVKEY_VERSION=0x04358394 + DEFINES += BIP44_COIN_TYPE=1 + DEFINES += COIN_P2PKH_VERSION=111 + DEFINES += COIN_P2SH_VERSION=75 + DEFINES += COIN_PREFIX_CONFIDENTIAL=4 + DEFINES += HAVE_LIQUID + DEFINES += LIQUID_NET_REGTEST + DEFINES += COIN_COINID_SHORT=\"tLBTC\" + DEFINES += COIN_NATIVE_SEGWIT_PREFIX=\"ert\" + DEFINES += COIN_NATIVE_SEGWIT_PREFIX_CONFIDENTIAL=\"el\" + + APPNAME = "Liquid Regtest" else ifeq ($(COIN),liquid_testnet) - -# Liquid testnet -DEFINES += BIP32_PUBKEY_VERSION=0x043587CF -DEFINES += BIP32_PRIVKEY_VERSION=0x04358394 -DEFINES += BIP44_COIN_TYPE=1 -DEFINES += COIN_P2PKH_VERSION=36 -DEFINES += COIN_P2SH_VERSION=19 -DEFINES += COIN_PREFIX_CONFIDENTIAL=23 -DEFINES += HAVE_LIQUID -DEFINES += LIQUID_NET_TESTNET -DEFINES += COIN_COINID_SHORT=\"tLBTC\" -DEFINES += COIN_NATIVE_SEGWIT_PREFIX=\"tex\" -DEFINES += COIN_NATIVE_SEGWIT_PREFIX_CONFIDENTIAL=\"tlq\" - -APPNAME = "Liquid Testnet" + # Application allowed derivation paths (Liquid testnet/regtest). + PATH_APP_LOAD_PARAMS = "*/1'" # purpose=* / coin_type=Testnet(1) + + # Liquid testnet + DEFINES += BIP32_PUBKEY_VERSION=0x043587CF + DEFINES += BIP32_PRIVKEY_VERSION=0x04358394 + DEFINES += BIP44_COIN_TYPE=1 + DEFINES += COIN_P2PKH_VERSION=36 + DEFINES += COIN_P2SH_VERSION=19 + DEFINES += COIN_PREFIX_CONFIDENTIAL=23 + DEFINES += HAVE_LIQUID + DEFINES += LIQUID_NET_TESTNET + DEFINES += COIN_COINID_SHORT=\"tLBTC\" + DEFINES += COIN_NATIVE_SEGWIT_PREFIX=\"tex\" + DEFINES += COIN_NATIVE_SEGWIT_PREFIX_CONFIDENTIAL=\"tlq\" + + APPNAME = "Liquid Testnet" else ifeq ($(COIN),liquid) - -# Liquid -DEFINES += BIP32_PUBKEY_VERSION=0x0488B21E -DEFINES += BIP32_PRIVKEY_VERSION=0x0488ADE4 -DEFINES += BIP44_COIN_TYPE=1776 -DEFINES += COIN_P2PKH_VERSION=57 -DEFINES += COIN_P2SH_VERSION=39 -DEFINES += COIN_PREFIX_CONFIDENTIAL=12 -DEFINES += HAVE_LIQUID -DEFINES += LIQUID_NET_MAINNET -DEFINES += COIN_COINID_SHORT=\"LBTC\" -DEFINES += COIN_NATIVE_SEGWIT_PREFIX=\"ex\" -DEFINES += COIN_NATIVE_SEGWIT_PREFIX_CONFIDENTIAL=\"lq\" - -APPNAME = "Liquid" + # Application allowed derivation paths (Liquid main network, liquidv1). + PATH_APP_LOAD_PARAMS = "*/1776'" # purpose=* / coin_type=Liquid(1776) + + # Liquid + DEFINES += BIP32_PUBKEY_VERSION=0x0488B21E + DEFINES += BIP32_PRIVKEY_VERSION=0x0488ADE4 + DEFINES += BIP44_COIN_TYPE=1776 + DEFINES += COIN_P2PKH_VERSION=57 + DEFINES += COIN_P2SH_VERSION=39 + DEFINES += COIN_PREFIX_CONFIDENTIAL=12 + DEFINES += HAVE_LIQUID + DEFINES += LIQUID_NET_MAINNET + DEFINES += COIN_COINID_SHORT=\"LBTC\" + DEFINES += COIN_NATIVE_SEGWIT_PREFIX=\"ex\" + DEFINES += COIN_NATIVE_SEGWIT_PREFIX_CONFIDENTIAL=\"lq\" + + APPNAME = "Liquid" else -ifeq ($(filter clean,$(MAKECMDGOALS)),) -$(error Unsupported COIN - use bitcoin_testnet, bitcoin, liquid_regtest, liquid_testnet, liquid) -endif + ifeq ($(filter clean,$(MAKECMDGOALS)),) + $(error Unsupported COIN - use bitcoin_testnet, bitcoin, liquid_regtest, liquid_testnet, liquid) + endif endif ifneq (,$(findstring liquid,$(COIN))) diff --git a/ledger_app.toml b/ledger_app.toml index 5b8fbaad2..b5a17a988 100644 --- a/ledger_app.toml +++ b/ledger_app.toml @@ -1,7 +1,7 @@ [app] build_directory = "./" sdk = "C" -devices = ["nanos", "nanox", "nanos+"] +devices = ["nanox", "nanos+"] [tests] unit_directory = "./unit-tests/" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..2febb424c --- /dev/null +++ b/requirements.txt @@ -0,0 +1,14 @@ +# requirements for the various test suites + +pytest>=6.1.1,<7.0.0 +pytest-benchmark>=4.0.0,<5.0.0 +pytest-timeout>=2.1.0,<3.0.0 +ledgercomm>=1.1.0,<1.2.0 +ecdsa>=0.16.1,<0.17.0 +typing-extensions>=3.7,<4.0 +embit>=0.7.0,<0.8.0 +mnemonic==0.20 +bip32>=3.4,<4.0 +speculos>=0.21.2 +ragger[speculos, ledgerwallet]>=1.37.0 +-e ./bitcoin_client # path relative to the current working directory; assume it's the root of the repo diff --git a/src/crypto.c b/src/crypto.c index f523bddaa..dfe72b8da 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -37,8 +37,8 @@ #include "common/read.h" #include "common/write.h" -#include "cxram_stash.h" -#include "debug-helpers/debug.h" +#include "../boilerplate/sw.h" +#include "../debug-helpers/debug.h" #include "crypto.h" @@ -290,26 +290,28 @@ bool crypto_generate_compressed_pubkey_pair(const uint8_t privkey[static 32], return ok; } -bool crypto_get_compressed_pubkey_at_path(const uint32_t bip32_path[], - uint8_t bip32_path_len, - uint8_t pubkey[static 33], - uint8_t chain_code[]) { +cx_err_t crypto_get_compressed_pubkey_at_path(const uint32_t bip32_path[], + uint8_t bip32_path_len, + uint8_t pubkey[static 33], + uint8_t chain_code[]) { uint8_t raw_public_key[65]; + cx_err_t error = CX_OK; - if (bip32_derive_get_pubkey_256(CX_CURVE_256K1, - bip32_path, - bip32_path_len, - raw_public_key, - chain_code, - CX_SHA512) != CX_OK) { - return false; + error = bip32_derive_get_pubkey_256(CX_CURVE_256K1, + bip32_path, + bip32_path_len, + raw_public_key, + chain_code, + CX_SHA512); + if (error != CX_OK) { + return error; } if (crypto_get_compressed_pubkey(raw_public_key, pubkey) < 0) { - return false; + return CX_INTERNAL_ERROR; } - return true; + return error; } uint32_t crypto_get_key_fingerprint(const uint8_t pub_key[static 33]) { @@ -319,12 +321,15 @@ uint32_t crypto_get_key_fingerprint(const uint8_t pub_key[static 33]) { return read_u32_be(key_rip, 0); } -uint32_t crypto_get_master_key_fingerprint(void) { - uint8_t master_pub_key[33]; - uint32_t bip32_path[] = {}; - LEDGER_ASSERT(crypto_get_compressed_pubkey_at_path(bip32_path, 0, master_pub_key, NULL), - "It never fails"); - return crypto_get_key_fingerprint(master_pub_key); +uint32_t crypto_get_master_key_fingerprint() { + uint8_t master_key_identifier[CX_RIPEMD160_SIZE] = {0}; + + int res = os_perso_get_master_key_identifier(master_key_identifier, CX_RIPEMD160_SIZE); + LEDGER_ASSERT( + res == CX_OK, + "Unexpected error in os_perso_get_master_key_identifier computation. Returned: %d", + res); + return read_u32_be(master_key_identifier, 0); } bool crypto_derive_symmetric_key(const char *label, size_t label_len, uint8_t key[static 32]) { @@ -353,23 +358,26 @@ bool crypto_derive_symmetric_key(const char *label, size_t label_len, uint8_t ke return res; } -int get_extended_pubkey_at_path(const uint32_t bip32_path[], - uint8_t bip32_path_len, - uint32_t bip32_pubkey_version, - serialized_extended_pubkey_t *out_pubkey) { +cx_err_t get_extended_pubkey_at_path(const uint32_t bip32_path[], + uint8_t bip32_path_len, + uint32_t bip32_pubkey_version, + serialized_extended_pubkey_t *out_pubkey) { // find parent key's fingerprint and child number uint32_t parent_fingerprint = 0; uint32_t child_number = 0; + cx_err_t error = CX_OK; + if (bip32_path_len > 0) { // here we reuse the storage for the parent keys that we will later use // for the response, in order to save memory uint8_t parent_pubkey[33]; - if (!crypto_get_compressed_pubkey_at_path(bip32_path, - bip32_path_len - 1, - parent_pubkey, - NULL)) { - return -1; + error = crypto_get_compressed_pubkey_at_path(bip32_path, + bip32_path_len - 1, + parent_pubkey, + NULL); + if (error != CX_OK) { + return error; } parent_fingerprint = crypto_get_key_fingerprint(parent_pubkey); @@ -381,14 +389,31 @@ int get_extended_pubkey_at_path(const uint32_t bip32_path[], write_u32_be(out_pubkey->parent_fingerprint, 0, parent_fingerprint); write_u32_be(out_pubkey->child_number, 0, child_number); - if (!crypto_get_compressed_pubkey_at_path(bip32_path, - bip32_path_len, - out_pubkey->compressed_pubkey, - out_pubkey->chain_code)) { - return -1; + return crypto_get_compressed_pubkey_at_path(bip32_path, + bip32_path_len, + out_pubkey->compressed_pubkey, + out_pubkey->chain_code); +} + +uint16_t cx_err_to_sw(cx_err_t error) { + if (error == CX_OK) { + return SW_OK; } - return 0; + /* The error codes are not currently defined in the SDK */ + if (error == 0x4212) { + PRINTF( + "Attempt to derive a key at root level without " + "HAVE_APPLICATION_FLAG_DERIVE_MASTER permission.\n"); + return SW_NOT_SUPPORTED; + } + if (error == 0x4215) { + PRINTF("Attempt to derive a key at unauthorized path.\n"); + return SW_NOT_SUPPORTED; + } + + PRINTF("Failed getting bip32 pubkey, error = 0x%08X\n", error); + return SW_BAD_STATE; } int base58_encode_address(const uint8_t in[20], uint32_t version, char *out, size_t out_len) { diff --git a/src/crypto.h b/src/crypto.h index a79140a54..c90ae6b95 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -318,10 +318,10 @@ void crypto_get_checksum(const uint8_t *in, uint16_t in_len, uint8_t out[static * * @return true on success, false in case of error. */ -WARN_UNUSED_RESULT bool crypto_get_compressed_pubkey_at_path(const uint32_t bip32_path[], - uint8_t bip32_path_len, - uint8_t pubkey[static 33], - uint8_t chain_code[]); +WARN_UNUSED_RESULT cx_err_t crypto_get_compressed_pubkey_at_path(const uint32_t bip32_path[], + uint8_t bip32_path_len, + uint8_t pubkey[static 33], + uint8_t chain_code[]); /** * Computes the fingerprint of a compressed key as per BIP32; that is, the first 4 bytes of the @@ -355,10 +355,10 @@ uint32_t crypto_get_master_key_fingerprint(void); * * @return 0 on success, or -1 on error. */ -WARN_UNUSED_RESULT int get_extended_pubkey_at_path(const uint32_t bip32_path[], - uint8_t bip32_path_len, - uint32_t bip32_pubkey_version, - serialized_extended_pubkey_t *out_pubkey); +WARN_UNUSED_RESULT cx_err_t get_extended_pubkey_at_path(const uint32_t bip32_path[], + uint8_t bip32_path_len, + uint32_t bip32_pubkey_version, + serialized_extended_pubkey_t *out_pubkey); /** * Derives the level-1 symmetric key at the given label using SLIP-0021. @@ -559,3 +559,13 @@ WARN_UNUSED_RESULT int validate_serialized_extended_pubkey(const char *pubkey, const uint32_t bip32_path[], int bip32_path_len, uint32_t bip32_pubkey_version); + +/** + * Converts cx_err_t to 2-bytes SW and prints out debug information. + * + * @param[in] error + * Cryptographic error code + * + * @return SW (SW_OK on success, other value on error). + */ +uint16_t cx_err_to_sw(cx_err_t error); diff --git a/src/handler/get_extended_pubkey.c b/src/handler/get_extended_pubkey.c index 9c56176e8..7b5b5f684 100644 --- a/src/handler/get_extended_pubkey.c +++ b/src/handler/get_extended_pubkey.c @@ -139,12 +139,13 @@ void handler_get_extended_pubkey(dispatcher_context_t *dc, uint8_t protocol_vers } serialized_extended_pubkey_check_t pubkey_check; - if (0 > get_extended_pubkey_at_path(bip32_path, - bip32_path_len, - BIP32_PUBKEY_VERSION, - &pubkey_check.serialized_extended_pubkey)) { - PRINTF("Failed getting bip32 pubkey\n"); - SEND_SW(dc, SW_BAD_STATE); + uint16_t sw = + cx_err_to_sw(get_extended_pubkey_at_path(bip32_path, + bip32_path_len, + BIP32_PUBKEY_VERSION, + &pubkey_check.serialized_extended_pubkey)); + if (SW_OK != sw) { + SEND_SW(dc, sw); return; } diff --git a/src/handler/get_master_fingerprint.c b/src/handler/get_master_fingerprint.c index e1993c390..63305ef93 100644 --- a/src/handler/get_master_fingerprint.c +++ b/src/handler/get_master_fingerprint.c @@ -17,6 +17,8 @@ #include +#include "os_seed.h" + #include "boilerplate/dispatcher.h" #include "boilerplate/sw.h" #include "../commands.h" @@ -27,14 +29,12 @@ void handler_get_master_fingerprint(dispatcher_context_t *dc, uint8_t protocol_version) { (void) protocol_version; - uint8_t master_pubkey[33]; - if (!crypto_get_compressed_pubkey_at_path((uint32_t[]){}, 0, master_pubkey, NULL)) { + uint8_t master_key_identifier[CX_RIPEMD160_SIZE] = {0}; + + if (os_perso_get_master_key_identifier(master_key_identifier, CX_RIPEMD160_SIZE) != CX_OK) { SEND_SW(dc, SW_BAD_STATE); // should never happen return; } - uint8_t master_fingerprint_be[4]; - write_u32_be(master_fingerprint_be, 0, crypto_get_key_fingerprint(master_pubkey)); - - SEND_RESPONSE(dc, master_fingerprint_be, sizeof(master_fingerprint_be), SW_OK); + SEND_RESPONSE(dc, master_key_identifier, 4, SW_OK); } diff --git a/src/handler/lib/policy.c b/src/handler/lib/policy.c index 5595ab279..5cdf48d27 100644 --- a/src/handler/lib/policy.c +++ b/src/handler/lib/policy.c @@ -1501,10 +1501,10 @@ bool is_wallet_policy_standard(dispatcher_context_t *dispatcher_context, // generate pubkey and check if it matches serialized_extended_pubkey_t derived_pubkey; - if (0 > get_extended_pubkey_at_path(key_info.master_key_derivation, - key_info.master_key_derivation_len, - BIP32_PUBKEY_VERSION, - &derived_pubkey)) { + if (CX_OK != get_extended_pubkey_at_path(key_info.master_key_derivation, + key_info.master_key_derivation_len, + BIP32_PUBKEY_VERSION, + &derived_pubkey)) { PRINTF("Failed to derive pubkey\n"); return false; } diff --git a/src/handler/register_wallet.c b/src/handler/register_wallet.c index deb020dfb..48e443a6c 100644 --- a/src/handler/register_wallet.c +++ b/src/handler/register_wallet.c @@ -196,13 +196,13 @@ void handler_register_wallet(dispatcher_context_t *dc, uint8_t protocol_version) read_u32_be(key_info.master_key_fingerprint, 0) == master_key_fingerprint) { // we verify that we can actually generate the same pubkey serialized_extended_pubkey_t pubkey_derived; - int serialized_pubkey_len = - get_extended_pubkey_at_path(key_info.master_key_derivation, - key_info.master_key_derivation_len, - BIP32_PUBKEY_VERSION, - &pubkey_derived); - if (serialized_pubkey_len == -1) { - SEND_SW(dc, SW_BAD_STATE); + uint16_t sw = + cx_err_to_sw(get_extended_pubkey_at_path(key_info.master_key_derivation, + key_info.master_key_derivation_len, + BIP32_PUBKEY_VERSION, + &pubkey_derived)); + if (SW_OK != sw) { + SEND_SW(dc, sw); (void) ui_post_processing_confirm_wallet_registration(dc, false); return; } diff --git a/src/handler/sign_psbt.c b/src/handler/sign_psbt.c index 3f1073062..36c9509b2 100644 --- a/src/handler/sign_psbt.c +++ b/src/handler/sign_psbt.c @@ -1174,10 +1174,10 @@ fill_placeholder_info_if_internal(dispatcher_context_t *dc, { // it could be a collision on the fingerprint; we verify that we can actually generate // the same pubkey - if (0 > get_extended_pubkey_at_path(key_info.master_key_derivation, - key_info.master_key_derivation_len, - BIP32_PUBKEY_VERSION, - &placeholder_info->pubkey)) { + if (CX_OK != get_extended_pubkey_at_path(key_info.master_key_derivation, + key_info.master_key_derivation_len, + BIP32_PUBKEY_VERSION, + &placeholder_info->pubkey)) { SEND_SW(dc, SW_BAD_STATE); return false; } diff --git a/src/swap/handle_check_address.c b/src/swap/handle_check_address.c index 1c954ec5d..4b5650f08 100644 --- a/src/swap/handle_check_address.c +++ b/src/swap/handle_check_address.c @@ -112,10 +112,8 @@ int handle_check_address(check_address_parameters_t* params) { return false; } - if (!crypto_get_compressed_pubkey_at_path(path.path, - path.length, - compressed_public_key, - NULL)) { + if (CX_OK != + crypto_get_compressed_pubkey_at_path(path.path, path.length, compressed_public_key, NULL)) { return 0; } char address[MAX_ADDRESS_LENGTH_STR + 1]; @@ -135,4 +133,4 @@ int handle_check_address(check_address_parameters_t* params) { } PRINTF("Addresses match\n"); return 1; -} \ No newline at end of file +} diff --git a/tests/requirements.txt b/tests/requirements.txt index d8554a27a..4c4900149 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,9 +1,2 @@ -pytest>=6.1.1,<7.0.0 -pytest-timeout>=2.1.0,<3.0.0 -ledgercomm>=1.1.0,<1.2.0 -ecdsa>=0.16.1,<0.17.0 -typing-extensions>=3.7,<4.0 -embit>=0.7.0,<0.8.0 -mnemonic==0.20 -bip32>=3.4,<4.0 -ragger[speculos, ledgerwallet]>=1.6.0 \ No newline at end of file +# The reusable ragger workflow expects a requirements.txt file in the tests directory, but we want to just use the one in the repository's root. +-r ../requirements.txt diff --git a/tests/test_get_extended_pubkey.py b/tests/test_get_extended_pubkey.py index 7bb8c00c8..71fcbaa3d 100644 --- a/tests/test_get_extended_pubkey.py +++ b/tests/test_get_extended_pubkey.py @@ -2,6 +2,7 @@ from ragger_bitcoin import RaggerClient from ragger.navigator import Navigator +from ragger.backend import SpeculosBackend from ragger.firmware import Firmware from ragger.error import ExceptionRAPDU @@ -86,15 +87,32 @@ def test_get_extended_pubkey_non_standard(navigator: Navigator, firmware: Firmwa # Test the successful UX flow for a non-standard path (here, root path) # (Slow test, not feasible to repeat it for many paths) - pub_key = client.get_extended_pubkey( - path="m", # root pubkey - display=True, - navigator=navigator, - instructions=pubkey_instruction_approve(firmware), - testname=test_name - ) + # The test will be re-enabled for Speculos once the installation parameters are supported + if isinstance(client.transport_client, SpeculosBackend): + pytest.skip("The test derives key at root level - now prohibited and the reinforcement is not yet implemented in Speculos.") - assert pub_key == "tpubD6NzVbkrYhZ4YgUx2ZLNt2rLYAMTdYysCRzKoLu2BeSHKvzqPaBDvf17GeBPnExUVPkuBpx4kniP964e2MxyzzazcXLptxLXModSVCVEV1T" + # Deriving a key at root level without HAVE_APPLICATION_FLAG_DERIVE_MASTER permission + with pytest.raises(ExceptionRAPDU) as e: + pub_key = client.get_extended_pubkey( + path="m", # root pubkey + display=True, + navigator=navigator, + instructions=pubkey_instruction_approve(firmware), + testname=test_name + ) + assert DeviceException.exc.get(e.value.status) == NotSupportedError + assert len(e.value.data) == 0 + # Deriving a key at unauthorized path + with pytest.raises(ExceptionRAPDU) as e: + pub_key = client.get_extended_pubkey( + path="m/44'/2'/333'", # root pubkey + display=True, + navigator=navigator, + instructions=pubkey_instruction_approve(firmware), + testname=test_name + ) + assert DeviceException.exc.get(e.value.status) == NotSupportedError + assert len(e.value.data) == 0 def test_get_extended_pubkey_non_standard_reject_early(navigator: Navigator, firmware: Firmware, @@ -102,9 +120,22 @@ def test_get_extended_pubkey_non_standard_reject_early(navigator: Navigator, fir # Test rejecting after the "Reject if you're not sure" warning # (Slow test, not feasible to repeat it for many paths) + # Deriving with a suspicious path without displaying + with pytest.raises(ExceptionRAPDU) as e: + client.get_extended_pubkey( + path="m/46'/1'/333'", + display=False, + navigator=navigator, + instructions=pubkey_instruction_reject_early(firmware), + testname=test_name + ) + assert DeviceException.exc.get(e.value.status) == NotSupportedError + assert len(e.value.data) == 0 + + # Deriving with a suspicious path with displaying, but rejecting as early as the path is displayed with pytest.raises(ExceptionRAPDU) as e: client.get_extended_pubkey( - path="m/111'/222'/333'", + path="m/46'/1'/333'", display=True, navigator=navigator, instructions=pubkey_instruction_reject_early(firmware), @@ -119,9 +150,10 @@ def test_get_extended_pubkey_non_standard_reject(navigator: Navigator, firmware: # Test rejecting at the end # (Slow test, not feasible to repeat it for many paths) + # Deriving with a suspicious path with displaying, but rejecting on the last screen with pytest.raises(ExceptionRAPDU) as e: client.get_extended_pubkey( - path="m/111'/222'/333'", + path="m/46'/1'/333'", display=True, navigator=navigator, instructions=pubkey_reject(firmware), diff --git a/tests/test_register_wallet.py b/tests/test_register_wallet.py index 376ff67d0..2cdd4bb5d 100644 --- a/tests/test_register_wallet.py +++ b/tests/test_register_wallet.py @@ -341,7 +341,7 @@ def test_register_unusual_singlesig_accounts(navigator: Navigator, firmware: Fir run_register_test(navigator, client, speculos_globals, WalletPolicy( name="Unusual Legacy", descriptor_template="pkh(@0/**)", - keys_info=["[f5acc2fd/1'/2'/3']tpubDCsHVWwqALkDzorr5zdc91Wj93zR3so1kUEH6LWsPrLtC9MVPjb8NEQwCzhPM4TEFP6KbgmTb7xAsyrbf3oEBh31Q7iAKhzMHj2FZ5YGNrr"] + keys_info=["[f5acc2fd/44'/1'/3']tpubDCwYjpDhUdPGW815u9VExvLRXDAHehcnkNfjqiwSvJp7NizpAGsX3Qfq9A173rES9vF17HgeqXBUvodRTyeTHCeAvg7gVgDE19mudggheN1"] ), instructions=register_wallet_instruction_approve_unusual(firmware), test_name=f"{test_name}_Unusual_Legacy") @@ -349,7 +349,7 @@ def test_register_unusual_singlesig_accounts(navigator: Navigator, firmware: Fir run_register_test(navigator, client, speculos_globals, WalletPolicy( name="Unusual Nested SegWit", descriptor_template="sh(wpkh(@0/**))", - keys_info=["[f5acc2fd/1'/2'/3']tpubDCsHVWwqALkDzorr5zdc91Wj93zR3so1kUEH6LWsPrLtC9MVPjb8NEQwCzhPM4TEFP6KbgmTb7xAsyrbf3oEBh31Q7iAKhzMHj2FZ5YGNrr"] + keys_info=["[f5acc2fd/44'/1'/3']tpubDCwYjpDhUdPGW815u9VExvLRXDAHehcnkNfjqiwSvJp7NizpAGsX3Qfq9A173rES9vF17HgeqXBUvodRTyeTHCeAvg7gVgDE19mudggheN1"] ), instructions=register_wallet_instruction_approve_unusual(firmware), test_name=f"{test_name}_Unusual_Nested_Segwit") @@ -357,7 +357,7 @@ def test_register_unusual_singlesig_accounts(navigator: Navigator, firmware: Fir run_register_test(navigator, client, speculos_globals, WalletPolicy( name="Unusual Native SegWit", descriptor_template="wpkh(@0/**)", - keys_info=["[f5acc2fd/1'/2'/3']tpubDCsHVWwqALkDzorr5zdc91Wj93zR3so1kUEH6LWsPrLtC9MVPjb8NEQwCzhPM4TEFP6KbgmTb7xAsyrbf3oEBh31Q7iAKhzMHj2FZ5YGNrr"] + keys_info=["[f5acc2fd/44'/1'/3']tpubDCwYjpDhUdPGW815u9VExvLRXDAHehcnkNfjqiwSvJp7NizpAGsX3Qfq9A173rES9vF17HgeqXBUvodRTyeTHCeAvg7gVgDE19mudggheN1"] ), instructions=register_wallet_instruction_approve_unusual(firmware), test_name=f"{test_name}_Unusual_Native_Segwit") @@ -365,7 +365,7 @@ def test_register_unusual_singlesig_accounts(navigator: Navigator, firmware: Fir run_register_test(navigator, client, speculos_globals, WalletPolicy( name="Unusual Taproot", descriptor_template="tr(@0/**)", - keys_info=["[f5acc2fd/1'/2'/3']tpubDCsHVWwqALkDzorr5zdc91Wj93zR3so1kUEH6LWsPrLtC9MVPjb8NEQwCzhPM4TEFP6KbgmTb7xAsyrbf3oEBh31Q7iAKhzMHj2FZ5YGNrr"] + keys_info=["[f5acc2fd/44'/1'/3']tpubDCwYjpDhUdPGW815u9VExvLRXDAHehcnkNfjqiwSvJp7NizpAGsX3Qfq9A173rES9vF17HgeqXBUvodRTyeTHCeAvg7gVgDE19mudggheN1"] ), instructions=register_wallet_instruction_approve_unusual(firmware), test_name=f"{test_name}_Unusual_Taproot") diff --git a/tests_liquid/requirements.txt b/tests_liquid/requirements.txt index d8554a27a..4c4900149 100644 --- a/tests_liquid/requirements.txt +++ b/tests_liquid/requirements.txt @@ -1,9 +1,2 @@ -pytest>=6.1.1,<7.0.0 -pytest-timeout>=2.1.0,<3.0.0 -ledgercomm>=1.1.0,<1.2.0 -ecdsa>=0.16.1,<0.17.0 -typing-extensions>=3.7,<4.0 -embit>=0.7.0,<0.8.0 -mnemonic==0.20 -bip32>=3.4,<4.0 -ragger[speculos, ledgerwallet]>=1.6.0 \ No newline at end of file +# The reusable ragger workflow expects a requirements.txt file in the tests directory, but we want to just use the one in the repository's root. +-r ../requirements.txt diff --git a/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_0_0/00002.png b/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_0_0/00002.png index 690fd0268..ec4f7e28b 100644 Binary files a/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_0_0/00002.png and b/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_0_0/00002.png differ diff --git a/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_0_1/00000.png b/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_0_1/00000.png index 8a9432bd6..ae7ff35fc 100644 Binary files a/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_0_1/00000.png and b/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_0_1/00000.png differ diff --git a/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_0_1/00001.png b/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_0_1/00001.png index 212d3b21e..a3be7d8d9 100644 Binary files a/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_0_1/00001.png and b/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_0_1/00001.png differ diff --git a/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_0_1/00002.png b/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_0_1/00002.png index dd9c46984..10ea68f9b 100644 Binary files a/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_0_1/00002.png and b/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_0_1/00002.png differ diff --git a/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_early_0_0/00002.png b/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_early_0_0/00002.png index 690fd0268..ec4f7e28b 100644 Binary files a/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_early_0_0/00002.png and b/tests_liquid/snapshots/nanosp/test_get_extended_pubkey_non_standard_reject_early_0_0/00002.png differ diff --git a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00000.png b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00000.png index 8ed992b5f..96859a0a8 100644 Binary files a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00000.png and b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00000.png differ diff --git a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00001.png b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00001.png index 575c5d8b1..546b6b131 100644 Binary files a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00001.png and b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00001.png differ diff --git a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00002.png b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00002.png index 7d609fa86..7bf11e1fd 100644 Binary files a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00002.png and b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00002.png differ diff --git a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00000.png b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00000.png index 8ed992b5f..2cf2115b4 100644 Binary files a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00000.png and b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00000.png differ diff --git a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00001.png b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00001.png index 575c5d8b1..f3fb18af4 100644 Binary files a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00001.png and b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00001.png differ diff --git a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00002.png b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00002.png index 7d609fa86..23c13d0b4 100644 Binary files a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00002.png and b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00002.png differ diff --git a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00000.png b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00000.png index 8ed992b5f..48fc4d761 100644 Binary files a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00000.png and b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00000.png differ diff --git a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00001.png b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00001.png index 575c5d8b1..19b8f9f93 100644 Binary files a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00001.png and b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00001.png differ diff --git a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00002.png b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00002.png index 7d609fa86..7f4b16466 100644 Binary files a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00002.png and b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00002.png differ diff --git a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00000.png b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00000.png index 8ed992b5f..2ba4d741a 100644 Binary files a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00000.png and b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00000.png differ diff --git a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00001.png b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00001.png index 575c5d8b1..1eb6c7d43 100644 Binary files a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00001.png and b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00001.png differ diff --git a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00002.png b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00002.png index 7d609fa86..fa6a10bce 100644 Binary files a/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00002.png and b/tests_liquid/snapshots/nanosp/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00002.png differ diff --git a/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_0_0/00002.png b/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_0_0/00002.png index 690fd0268..ec4f7e28b 100644 Binary files a/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_0_0/00002.png and b/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_0_0/00002.png differ diff --git a/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_0_1/00000.png b/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_0_1/00000.png index 8a9432bd6..ae7ff35fc 100644 Binary files a/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_0_1/00000.png and b/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_0_1/00000.png differ diff --git a/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_0_1/00001.png b/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_0_1/00001.png index 212d3b21e..a3be7d8d9 100644 Binary files a/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_0_1/00001.png and b/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_0_1/00001.png differ diff --git a/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_0_1/00002.png b/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_0_1/00002.png index dd9c46984..10ea68f9b 100644 Binary files a/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_0_1/00002.png and b/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_0_1/00002.png differ diff --git a/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_early_0_0/00002.png b/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_early_0_0/00002.png index 690fd0268..ec4f7e28b 100644 Binary files a/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_early_0_0/00002.png and b/tests_liquid/snapshots/nanox/test_get_extended_pubkey_non_standard_reject_early_0_0/00002.png differ diff --git a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00000.png b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00000.png index 8ed992b5f..96859a0a8 100644 Binary files a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00000.png and b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00000.png differ diff --git a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00001.png b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00001.png index 575c5d8b1..546b6b131 100644 Binary files a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00001.png and b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00001.png differ diff --git a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00002.png b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00002.png index 7d609fa86..7bf11e1fd 100644 Binary files a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00002.png and b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Legacy_1_0/00002.png differ diff --git a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00000.png b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00000.png index 8ed992b5f..2cf2115b4 100644 Binary files a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00000.png and b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00000.png differ diff --git a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00001.png b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00001.png index 575c5d8b1..f3fb18af4 100644 Binary files a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00001.png and b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00001.png differ diff --git a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00002.png b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00002.png index 7d609fa86..23c13d0b4 100644 Binary files a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00002.png and b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Native_Segwit_1_0/00002.png differ diff --git a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00000.png b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00000.png index 8ed992b5f..48fc4d761 100644 Binary files a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00000.png and b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00000.png differ diff --git a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00001.png b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00001.png index 575c5d8b1..19b8f9f93 100644 Binary files a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00001.png and b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00001.png differ diff --git a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00002.png b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00002.png index 7d609fa86..7f4b16466 100644 Binary files a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00002.png and b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Nested_Segwit_1_0/00002.png differ diff --git a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00000.png b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00000.png index 8ed992b5f..2ba4d741a 100644 Binary files a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00000.png and b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00000.png differ diff --git a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00001.png b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00001.png index 575c5d8b1..1eb6c7d43 100644 Binary files a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00001.png and b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00001.png differ diff --git a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00002.png b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00002.png index 7d609fa86..fa6a10bce 100644 Binary files a/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00002.png and b/tests_liquid/snapshots/nanox/test_register_unusual_singlesig_accounts_Unusual_Taproot_1_0/00002.png differ diff --git a/tests_liquid/test_get_extended_pubkey.py b/tests_liquid/test_get_extended_pubkey.py index 3cd39ac23..c92c76ce6 100644 --- a/tests_liquid/test_get_extended_pubkey.py +++ b/tests_liquid/test_get_extended_pubkey.py @@ -2,6 +2,7 @@ from ragger_bitcoin import RaggerClient from ragger.navigator import Navigator +from ragger.backend import SpeculosBackend from ragger.firmware import Firmware from ragger.error import ExceptionRAPDU @@ -59,15 +60,32 @@ def test_get_extended_pubkey_non_standard(navigator: Navigator, firmware: Firmwa # Test the successful UX flow for a non-standard path (here, root path) # (Slow test, not feasible to repeat it for many paths) - pub_key = client.get_extended_pubkey( - path="m", # root pubkey - display=True, - navigator=navigator, - instructions=pubkey_instruction_approve(firmware), - testname=test_name - ) + # The test will be re-enabled for Speculos once the installation parameters are supported + if isinstance(client.transport_client, SpeculosBackend): + pytest.skip("The test derives key at root level - now prohibited and the reinforcement is not yet implemented in Speculos.") - assert pub_key == "tpubD6NzVbkrYhZ4YgUx2ZLNt2rLYAMTdYysCRzKoLu2BeSHKvzqPaBDvf17GeBPnExUVPkuBpx4kniP964e2MxyzzazcXLptxLXModSVCVEV1T" + # Deriving a key at root level without HAVE_APPLICATION_FLAG_DERIVE_MASTER permission + with pytest.raises(ExceptionRAPDU) as e: + pub_key = client.get_extended_pubkey( + path="m", # root pubkey + display=True, + navigator=navigator, + instructions=pubkey_instruction_approve(firmware), + testname=test_name + ) + assert DeviceException.exc.get(e.value.status) == NotSupportedError + assert len(e.value.data) == 0 + # Deriving a key at unauthorized path + with pytest.raises(ExceptionRAPDU) as e: + pub_key = client.get_extended_pubkey( + path="m/44'/2'/333'", + display=True, + navigator=navigator, + instructions=pubkey_instruction_approve(firmware), + testname=test_name + ) + assert DeviceException.exc.get(e.value.status) == NotSupportedError + assert len(e.value.data) == 0 @pytest.mark.use_on_backend("speculos") @@ -76,9 +94,22 @@ def test_get_extended_pubkey_non_standard_reject_early(navigator: Navigator, fir # Test rejecting after the "Reject if you're not sure" warning # (Slow test, not feasible to repeat it for many paths) + # Deriving with a suspicious path without displaying + with pytest.raises(ExceptionRAPDU) as e: + client.get_extended_pubkey( + path="m/46'/1'/333'", + display=False, + navigator=navigator, + instructions=pubkey_instruction_reject_early(firmware), + testname=test_name + ) + assert DeviceException.exc.get(e.value.status) == NotSupportedError + assert len(e.value.data) == 0 + + # Deriving with a suspicious path with displaying, but rejecting as early as the path is displayed with pytest.raises(ExceptionRAPDU) as e: client.get_extended_pubkey( - path="m/111'/222'/333'", + path="m/46'/1'/333'", display=True, navigator=navigator, instructions=pubkey_instruction_reject_early(firmware), @@ -94,9 +125,10 @@ def test_get_extended_pubkey_non_standard_reject(navigator: Navigator, firmware: # Test rejecting at the end # (Slow test, not feasible to repeat it for many paths) + # Deriving with a suspicious path with displaying, but rejecting on the last screen with pytest.raises(ExceptionRAPDU) as e: client.get_extended_pubkey( - path="m/111'/222'/333'", + path="m/46'/1'/333'", display=True, navigator=navigator, instructions=pubkey_reject(firmware), diff --git a/tests_liquid/test_register_wallet.py b/tests_liquid/test_register_wallet.py index cc354ae34..add56c6a9 100644 --- a/tests_liquid/test_register_wallet.py +++ b/tests_liquid/test_register_wallet.py @@ -349,7 +349,7 @@ def test_register_unusual_singlesig_accounts(navigator: Navigator, firmware: Fir run_register_test(navigator, client, speculos_globals, WalletPolicy( name="Unusual Legacy", descriptor_template="pkh(@0/**)", - keys_info=["[f5acc2fd/1'/2'/3']tpubDCsHVWwqALkDzorr5zdc91Wj93zR3so1kUEH6LWsPrLtC9MVPjb8NEQwCzhPM4TEFP6KbgmTb7xAsyrbf3oEBh31Q7iAKhzMHj2FZ5YGNrr"] + keys_info=["[f5acc2fd/44'/1'/10']tpubDCwYjpDhUdPGp21gSpVay2QPJVh6WNySWMXPhbcu1DsxH31dF7mY18oibbu5RxCLBc1Szerjscuc3D5HyvfYqfRvc9mesewnFqGmPjney4d"] ), instructions=register_wallet_instruction_approve_unusual(firmware), test_name=f"{test_name}_Unusual_Legacy") @@ -357,7 +357,7 @@ def test_register_unusual_singlesig_accounts(navigator: Navigator, firmware: Fir run_register_test(navigator, client, speculos_globals, WalletPolicy( name="Unusual Nested SegWit", descriptor_template="sh(wpkh(@0/**))", - keys_info=["[f5acc2fd/1'/2'/3']tpubDCsHVWwqALkDzorr5zdc91Wj93zR3so1kUEH6LWsPrLtC9MVPjb8NEQwCzhPM4TEFP6KbgmTb7xAsyrbf3oEBh31Q7iAKhzMHj2FZ5YGNrr"] + keys_info=["[f5acc2fd/49'/1'/0']tpubDC871vGLAiKPcwAw22EjhKVLk5L98UGXBEcGR8gpcigLQVDDfgcYW24QBEyTHTSFEjgJgbaHU8CdRi9vmG4cPm1kPLmZhJEP17FMBdNheh3"] ), instructions=register_wallet_instruction_approve_unusual(firmware), test_name=f"{test_name}_Unusual_Nested_Segwit") @@ -365,7 +365,7 @@ def test_register_unusual_singlesig_accounts(navigator: Navigator, firmware: Fir run_register_test(navigator, client, speculos_globals, WalletPolicy( name="Unusual Native SegWit", descriptor_template="wpkh(@0/**)", - keys_info=["[f5acc2fd/1'/2'/3']tpubDCsHVWwqALkDzorr5zdc91Wj93zR3so1kUEH6LWsPrLtC9MVPjb8NEQwCzhPM4TEFP6KbgmTb7xAsyrbf3oEBh31Q7iAKhzMHj2FZ5YGNrr"] + keys_info=["[f5acc2fd/84'/1'/0']tpubDCtKfsNyRhULjZ9XMS4VKKtVcPdVDi8MKUbcSD9MJDyjRu1A2ND5MiipozyyspBT9bg8upEp7a8EAgFxNxXn1d7QkdbL52Ty5jiSLcxPt1P"] ), instructions=register_wallet_instruction_approve_unusual(firmware), test_name=f"{test_name}_Unusual_Native_Segwit") @@ -373,7 +373,7 @@ def test_register_unusual_singlesig_accounts(navigator: Navigator, firmware: Fir run_register_test(navigator, client, speculos_globals, WalletPolicy( name="Unusual Taproot", descriptor_template="tr(@0/**)", - keys_info=["[f5acc2fd/1'/2'/3']tpubDCsHVWwqALkDzorr5zdc91Wj93zR3so1kUEH6LWsPrLtC9MVPjb8NEQwCzhPM4TEFP6KbgmTb7xAsyrbf3oEBh31Q7iAKhzMHj2FZ5YGNrr"] + keys_info=["[f5acc2fd/86'/1'/0']tpubDDKYE6BREvDsSWMazgHoyQWiJwYaDDYPbCFjYxN3HFXJP5fokeiK4hwK5tTLBNEDBwrDXn8cQ4v9b2xdW62Xr5yxoQdMu1v6c7UDXYVH27U"] ), instructions=register_wallet_instruction_approve_unusual(firmware), test_name=f"{test_name}_Unusual_Taproot") diff --git a/tests_liquid_main/requirements.txt b/tests_liquid_main/requirements.txt index d8554a27a..4c4900149 100644 --- a/tests_liquid_main/requirements.txt +++ b/tests_liquid_main/requirements.txt @@ -1,9 +1,2 @@ -pytest>=6.1.1,<7.0.0 -pytest-timeout>=2.1.0,<3.0.0 -ledgercomm>=1.1.0,<1.2.0 -ecdsa>=0.16.1,<0.17.0 -typing-extensions>=3.7,<4.0 -embit>=0.7.0,<0.8.0 -mnemonic==0.20 -bip32>=3.4,<4.0 -ragger[speculos, ledgerwallet]>=1.6.0 \ No newline at end of file +# The reusable ragger workflow expects a requirements.txt file in the tests directory, but we want to just use the one in the repository's root. +-r ../requirements.txt diff --git a/tests_liquid_testnet/requirements.txt b/tests_liquid_testnet/requirements.txt index d8554a27a..4c4900149 100644 --- a/tests_liquid_testnet/requirements.txt +++ b/tests_liquid_testnet/requirements.txt @@ -1,9 +1,2 @@ -pytest>=6.1.1,<7.0.0 -pytest-timeout>=2.1.0,<3.0.0 -ledgercomm>=1.1.0,<1.2.0 -ecdsa>=0.16.1,<0.17.0 -typing-extensions>=3.7,<4.0 -embit>=0.7.0,<0.8.0 -mnemonic==0.20 -bip32>=3.4,<4.0 -ragger[speculos, ledgerwallet]>=1.6.0 \ No newline at end of file +# The reusable ragger workflow expects a requirements.txt file in the tests directory, but we want to just use the one in the repository's root. +-r ../requirements.txt diff --git a/unit-tests/mock_includes/lcx_common.h b/unit-tests/mock_includes/lcx_common.h index 5cecb1e18..c1f116091 100644 --- a/unit-tests/mock_includes/lcx_common.h +++ b/unit-tests/mock_includes/lcx_common.h @@ -41,6 +41,9 @@ typedef struct uint64_s uint64bits_t; typedef uint64_t uint64bits_t; #endif +/** Type of error code */ +typedef uint32_t cx_err_t; + // clang-format off /** * @brief Cryptography flags