From b301d7e3bd3ad2d1ed85af0d043cbc18be908c25 Mon Sep 17 00:00:00 2001 From: Carlos Medeiros Date: Tue, 17 Dec 2024 15:52:16 +0000 Subject: [PATCH] add swap support structure --- app/Makefile | 24 +++++++-- app/src/apdu_handler.c | 25 ++++++++++ app/src/common/main.c | 107 ++++++++++++++++++++++++++++++++++++----- app/src/common/tx.c | 24 +++++++++ 4 files changed, 164 insertions(+), 16 deletions(-) diff --git a/app/Makefile b/app/Makefile index 1ffb0280..918ca905 100755 --- a/app/Makefile +++ b/app/Makefile @@ -27,7 +27,18 @@ include $(CURDIR)/../deps/ledger-zxlib/makefiles/Makefile.installer_script include $(BOLOS_SDK)/Makefile.defines include $(CURDIR)/Makefile.version +ifndef COIN +COIN=ATOM +endif + PRODUCTION_BUILD ?= 1 +ifeq ($(COIN),ATOM) +ifeq ($(TARGET_NAME),TARGET_NANOS) + HAVE_SWAP ?= 0 +else + HAVE_SWAP ?= 1 +endif +endif # Display the target name $(info ************ TARGET_NAME = [$(TARGET_NAME)]) @@ -38,14 +49,21 @@ ifeq ($(PRODUCTION_BUILD), 1) else $(info ************ PRODUCTION_BUILD = [INTERNAL USE]) endif + +ifeq ($(HAVE_SWAP), 1) + $(info ************ HAVE_SWAP = [ENABLED]) + DEFINES += HAVE_SWAP=$(HAVE_SWAP) +else + $(info ************ HAVE_SWAP = [DISABLED]) +endif + + # Add the PRODUCTION_BUILD definition to the compiler flags DEFINES += PRODUCTION_BUILD=$(PRODUCTION_BUILD) include $(CURDIR)/../deps/ledger-zxlib/makefiles/Makefile.app_testing -ifndef COIN -COIN=ATOM -endif + $(info COIN = [$(COIN)]) diff --git a/app/src/apdu_handler.c b/app/src/apdu_handler.c index 18ca7d10..e105c7c8 100644 --- a/app/src/apdu_handler.c +++ b/app/src/apdu_handler.c @@ -37,6 +37,10 @@ #include "chain_config.h" +#ifdef HAVE_SWAP +#include "swap.h" +#endif + static const char *msg_error1 = "Expert Mode"; static const char *msg_error2 = "Required"; @@ -212,6 +216,17 @@ __Z_INLINE void handleSign(volatile uint32_t *flags, volatile uint32_t *tx, uint THROW(APDU_CODE_DATA_INVALID); } +#ifdef HAVE_SWAP + if (G_swap_state.called_from_swap && G_swap_state.should_exit && error_msg == NULL) { + // Call app_sign without going through UI display, the UI validation was done in + // Exchange app already + app_sign(); + // Go back to Exchange and report our success to display the modal + finalize_exchange_sign_transaction(true); + // Unreachable + } +#endif + CHECK_APP_CANARY() view_review_init(tx_getItem, tx_getNumItems, app_sign); view_review_show(REVIEW_TXN); @@ -276,6 +291,16 @@ void handleApdu(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { } FINALLY { +#ifdef HAVE_SWAP + if (G_swap_state.called_from_swap && G_swap_state.should_exit) { + // Swap checking failed, send reply now and exit, don't wait next cycle + if (sw != 0) { + io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, *tx); + } + // Go back to exchange and report our status + finalize_exchange_sign_transaction(sw == 0); + } +#endif } } END_TRY; diff --git a/app/src/common/main.c b/app/src/common/main.c index 87150f07..b2b452d8 100644 --- a/app/src/common/main.c +++ b/app/src/common/main.c @@ -19,25 +19,106 @@ #include -__attribute__((section(".boot"))) int -main(void) { +#ifdef HAVE_NBGL +#include "nbgl_use_case.h" +#endif + +#ifdef HAVE_SWAP +#include "lib_standard_app/swap_lib_calls.h" +#include "swap.h" +#endif + +#ifdef HAVE_SWAP +// Helper to quit the application in a limited THROW context +static void app_exit(void) { + BEGIN_TRY_L(exit) { + TRY_L(exit) { + os_sched_exit(-1); + } + FINALLY_L(exit) { + } + } + END_TRY_L(exit); +} + +// Helper to handle the different library commands +static void library_main(libargs_t *args) { + BEGIN_TRY { + TRY { + switch (args->command) { + case SIGN_TRANSACTION: { + // Backup up transaction parameters and wipe BSS to avoid collusion with + // app-exchange BSS data. + bool success = copy_transaction_parameters(args->create_transaction); + if (success) { + // BSS was wiped, we can now init these globals + G_swap_state.called_from_swap = true; + G_swap_state.should_exit = false; + +#ifdef HAVE_NBGL + // On Stax, display a modal + nbgl_useCaseSpinner("Signing"); +#endif // HAVE_NBGL + + view_init(); + app_init(); + app_main(); + } + break; + } + case CHECK_ADDRESS: + handle_check_address(args->check_address); + break; + case GET_PRINTABLE_AMOUNT: + handle_get_printable_amount(args->get_printable_amount); + break; + default: + break; + } + } + CATCH_OTHER(e) { + } + FINALLY { + os_lib_end(); + } + } + END_TRY; +} +#endif + +__attribute__((section(".boot"))) int main(int arg0) { // exit critical section __asm volatile("cpsie i"); - view_init(); os_boot(); - BEGIN_TRY - { - TRY + if (arg0 != 0) { +#if HAVE_SWAP + // The app has been started in library mode + libargs_t *args = (libargs_t *)arg0; + if (args->id != 0x100) { + // Invalid mode ID + app_exit(); + } else { + library_main(args); + } +#endif + } else { + // The app has been launched from the dashboard + // G_swap_state.called_from_swap = false; + BEGIN_TRY { - app_init(); - app_main(); + TRY + { + view_init(); + app_init(); + app_main(); + } + CATCH_OTHER(e) + {} + FINALLY + {} } - CATCH_OTHER(e) - {} - FINALLY - {} + END_TRY; } - END_TRY; } diff --git a/app/src/common/tx.c b/app/src/common/tx.c index 764c2f9b..9ec249a7 100644 --- a/app/src/common/tx.c +++ b/app/src/common/tx.c @@ -21,6 +21,10 @@ #include #include "zxmacros.h" +#ifdef HAVE_SWAP +#include "swap.h" +#endif + #if defined(TARGET_NANOS2) || defined(TARGET_STAX) || defined(TARGET_FLEX) #define RAM_BUFFER_SIZE 8192 #define FLASH_BUFFER_SIZE 16384 @@ -113,6 +117,26 @@ const char *tx_parse(tx_type_e type) return parser_getErrorDescription(err); } + #ifdef HAVE_SWAP + // If in swap mode, compare swap tx parameters with stored info. + if (G_swap_state.called_from_swap) { + if (G_swap_state.should_exit == 1) { + // Safety against trying to make the app sign multiple TX + // This panic quit is a failsafe that should never trigger, as the app is supposed to + // exit after the first send when started in swap mode + os_sched_exit(-1); + } else { + // We will quit the app after this transaction, whether it succeeds or fails + G_swap_state.should_exit = 1; + } + err = check_swap_conditions(&ctx_parsed_tx); + CHECK_APP_CANARY() + if (err != parser_ok) { + return parser_getErrorDescription(err); + } + } +#endif + return NULL; }