From 60d1d97667f5dbf9ad578ad96068340feeaffeaf Mon Sep 17 00:00:00 2001 From: Francois Beutin Date: Fri, 1 Dec 2023 19:50:07 +0100 Subject: [PATCH] Return to Exchange when failing to sign in swap mode --- src/handle_swap_sign_transaction.c | 1 + src/main.c | 15 +++++++++++++++ src/shared_context.h | 1 + src_features/signTx/logic_signTx.c | 11 +++++++++++ 4 files changed, 28 insertions(+) diff --git a/src/handle_swap_sign_transaction.c b/src/handle_swap_sign_transaction.c index 789cbdd..495586a 100644 --- a/src/handle_swap_sign_transaction.c +++ b/src/handle_swap_sign_transaction.c @@ -80,6 +80,7 @@ void handle_swap_sign_transaction(chain_config_t* config) { chainConfig = config; reset_app_context(); G_called_from_swap = true; + G_swap_response_ready = false; io_seproxyhal_init(); if (N_storage.initialized != 0x01) { diff --git a/src/main.c b/src/main.c index 9ff8041..f8a6232 100644 --- a/src/main.c +++ b/src/main.c @@ -53,6 +53,7 @@ cx_sha3_t global_sha3; uint8_t appState; uint16_t apdu_response_code; bool G_called_from_swap; +bool G_swap_response_ready; pluginType_t pluginType; #ifdef HAVE_STARKWARE bool quantumSet; @@ -78,6 +79,7 @@ void reset_app_context() { // PRINTF("!!RESET_APP_CONTEXT\n"); appState = APP_STATE_IDLE; G_called_from_swap = false; + G_swap_response_ready = false; pluginType = OLD_INTERNAL; #ifdef HAVE_STARKWARE quantumSet = false; @@ -456,6 +458,7 @@ void handleApdu(unsigned int *flags, unsigned int *tx) { THROW(EXCEPTION_IO_RESET); } CATCH_OTHER(e) { + bool quit_now = G_called_from_swap && G_swap_response_ready; switch (e & 0xF000) { case 0x6000: // Wipe the transaction context and report the exception @@ -476,6 +479,18 @@ void handleApdu(unsigned int *flags, unsigned int *tx) { G_io_apdu_buffer[*tx] = sw >> 8; G_io_apdu_buffer[*tx + 1] = sw; *tx += 2; + + // If we are in swap mode and have validated a TX, we send it and immediately quit + if (quit_now) { + if (io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, *tx) == 0) { + // In case of success, the apdu is sent immediatly and eth exits + // Reaching this code means we encountered an error + finalize_exchange_sign_transaction(false); + } else { + PRINTF("Unrecoverable\n"); + os_sched_exit(-1); + } + } } FINALLY { } diff --git a/src/shared_context.h b/src/shared_context.h index c87f286..08e48d6 100644 --- a/src/shared_context.h +++ b/src/shared_context.h @@ -215,6 +215,7 @@ extern cx_sha3_t global_sha3; extern const internalStorage_t N_storage_real; extern bool G_called_from_swap; +extern bool G_swap_response_ready; typedef enum { EXTERNAL, // External plugin, set by setExternalPlugin. diff --git a/src_features/signTx/logic_signTx.c b/src_features/signTx/logic_signTx.c index 5c47e64..08f031c 100644 --- a/src_features/signTx/logic_signTx.c +++ b/src_features/signTx/logic_signTx.c @@ -433,6 +433,15 @@ void finalizeParsing(bool direct) { } } + if (G_called_from_swap) { + if (G_swap_response_ready) { + // Unreachable given current return to exchange mechanism. Safeguard against regression + PRINTF("FATAL: safety against double sign triggered\n"); + os_sched_exit(-1); + } + G_swap_response_ready = true; + } + // User has just validated a swap but ETH received apdus about a non standard plugin / contract if (G_called_from_swap && !use_standard_UI) { PRINTF("ERR_SILENT_MODE_CHECK_FAILED, G_called_from_swap\n"); @@ -504,6 +513,8 @@ void finalizeParsing(bool direct) { // Ensure the values are the same that the ones that have been previously validated if (strcmp(strings.common.maxFee, displayBuffer) != 0) { PRINTF("ERR_SILENT_MODE_CHECK_FAILED, fees check failed\n"); + PRINTF("Expected %s\n", strings.common.maxFee); + PRINTF("Received %s\n", displayBuffer); THROW(ERR_SILENT_MODE_CHECK_FAILED); } } else {