Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve error message returned in swap #663

Merged
merged 1 commit into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src_features/signTx/cmd_signTx.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,11 @@ uint16_t handleSign(uint8_t p1,
// We have encountered an error while trying to sign a SWAP type transaction
// Return dedicated error code and flag an early exit back to Exchange
G_swap_response_ready = true;
return APDU_RESPONSE_MODE_CHECK_FAILED;
} else {
return APDU_RESPONSE_INVALID_DATA;
send_swap_error(ERROR_GENERIC, APP_CODE_CALLDATA_ISSUE, NULL, NULL);
// unreachable
os_sched_exit(0);
}
cedelavergne-ledger marked this conversation as resolved.
Show resolved Hide resolved
return APDU_RESPONSE_INVALID_DATA;
default:
PRINTF("Unexpected parser status\n");
return APDU_RESPONSE_INVALID_DATA;
Expand Down
18 changes: 18 additions & 0 deletions src_features/signTx/feature_signTx.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@

#include "shared_context.h"

// Error codes for swap, to be moved in SDK?
cedelavergne-ledger marked this conversation as resolved.
Show resolved Hide resolved
#define ERROR_WRONG_AMOUNT 0x01
#define ERROR_WRONG_DESTINATION 0x02
#define ERROR_WRONG_FEES 0x03
#define ERROR_WRONG_METHOD 0x04
#define ERROR_CROSSCHAIN_WRONG_MODE 0x05
#define ERROR_CROSSCHAIN_WRONG_METHOD 0x06
#define ERROR_GENERIC 0xFF
cedelavergne-ledger marked this conversation as resolved.
Show resolved Hide resolved
cedelavergne-ledger marked this conversation as resolved.
Show resolved Hide resolved

// App codes for detail.
typedef enum {
APP_CODE_DEFAULT = 0x00,
APP_CODE_CALLDATA_ISSUE = 0x01,
APP_CODE_NO_STANDARD_UI = 0x02
} app_code_t;

typedef enum {

PLUGIN_UI_INSIDE = 0,
Expand All @@ -15,4 +31,6 @@ uint16_t finalizeParsing();
void ux_approve_tx(bool fromPlugin);
void start_signature_flow(void);

void send_swap_error(uint8_t error_code, app_code_t app_code, const char *str1, const char *str2);

#endif // _SIGN_TX_H_
99 changes: 80 additions & 19 deletions src_features/signTx/logic_signTx.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include "crypto_helpers.h"
#include "format.h"
#include "manage_asset_info.h"
#include "handle_swap_sign_transaction.h"
#include "os_math.h"

static bool g_use_standard_ui;

Expand Down Expand Up @@ -323,6 +325,56 @@ static int strcasecmp_workaround(const char *str1, const char *str2) {
return 0;
}

__attribute__((noreturn)) void send_swap_error(uint8_t error_code,
app_code_t app_code,
const char *str1,
const char *str2) {
uint32_t tx = 0;
uint len = 0;
PRINTF("APDU_RESPONSE_MODE_CHECK_FAILED: 0x%x\n", error_code);
// Set RAPDU error codes
G_io_apdu_buffer[tx++] = error_code;
G_io_apdu_buffer[tx++] = app_code;
// Set RAPDU error message
if (str1 != NULL) {
PRINTF("Expected %s\n", str1);
// If the string is too long, truncate it
len = MIN(strlen((const char *) str1), sizeof(G_io_apdu_buffer) - tx - 2);
memmove(G_io_apdu_buffer + tx, str1, len);
tx += len;
if (len < strlen((const char *) str1)) {
PRINTF("Truncated %s to %d bytes\n", str1, len);
G_io_apdu_buffer[tx - 1] = '*';
}
}
if (str2 != NULL) {
PRINTF("Received %s\n", str2);
// Do we have enough space to add a separator?
if ((tx + 1 + 2) < sizeof(G_io_apdu_buffer)) {
G_io_apdu_buffer[tx++] = '#';
}
// Do we have enough space to add at least one character?
if ((tx + 1 + 2) < sizeof(G_io_apdu_buffer)) {
// If the string is too long, truncate it
len = MIN(strlen((const char *) str2), sizeof(G_io_apdu_buffer) - tx - 2);
memmove(G_io_apdu_buffer + tx, str2, len);
tx += len;
if (len < strlen((const char *) str2)) {
PRINTF("Truncated %s to %d bytes\n", str2, len);
G_io_apdu_buffer[tx - 1] = '*';
}
}
}
// Set RAPDU status word, with previous check we are sure there is at least 2 bytes left
U2BE_ENCODE(G_io_apdu_buffer, tx, APDU_RESPONSE_MODE_CHECK_FAILED);
tx += 2;
cedelavergne-ledger marked this conversation as resolved.
Show resolved Hide resolved
cedelavergne-ledger marked this conversation as resolved.
Show resolved Hide resolved
// Send RAPDU
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
// In case of success, the apdu is sent immediately and eth exits
// Reaching this code means we encountered an error
finalize_exchange_sign_transaction(false);
}

__attribute__((noinline)) static uint16_t finalize_parsing_helper(void) {
char displayBuffer[50];
uint8_t decimals = WEI_TO_ETHER;
Expand Down Expand Up @@ -453,19 +505,20 @@ __attribute__((noinline)) static uint16_t finalize_parsing_helper(void) {
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 && !g_use_standard_ui) {
PRINTF("APDU_RESPONSE_MODE_CHECK_FAILED, G_called_from_swap\n");
return APDU_RESPONSE_MODE_CHECK_FAILED;
}

// Specific calldata check when in swap mode
if (G_called_from_swap) {
// User has just validated a swap but ETH received apdus about a non standard plugin /
// contract
if (!g_use_standard_ui) {
send_swap_error(ERROR_WRONG_METHOD, APP_CODE_NO_STANDARD_UI, NULL, NULL);
// unreachable
os_sched_exit(0);
}
// Two success cases: we are in standard mode and no calldata was received
// We are in crosschain mode and the correct calldata has been received
if (G_swap_mode != SWAP_MODE_STANDARD && G_swap_mode != SWAP_MODE_CROSSCHAIN_SUCCESS) {
PRINTF("Error: G_swap_mode %d refused\n", G_swap_mode);
return APDU_RESPONSE_MODE_CHECK_FAILED;
send_swap_error(ERROR_CROSSCHAIN_WRONG_MODE, APP_CODE_DEFAULT, NULL, NULL);
// unreachable
os_sched_exit(0);
}
}

Expand All @@ -491,8 +544,12 @@ __attribute__((noinline)) static uint16_t finalize_parsing_helper(void) {
if (G_called_from_swap) {
// Ensure the values are the same that the ones that have been previously validated
if (strcasecmp_workaround(strings.common.toAddress, displayBuffer) != 0) {
PRINTF("APDU_RESPONSE_MODE_CHECK_FAILED, address check failed\n");
return APDU_RESPONSE_MODE_CHECK_FAILED;
send_swap_error(ERROR_WRONG_DESTINATION,
APP_CODE_DEFAULT,
strings.common.toAddress,
displayBuffer);
// unreachable
os_sched_exit(0);
}
} else {
strlcpy(strings.common.toAddress, displayBuffer, sizeof(strings.common.toAddress));
Expand All @@ -514,10 +571,12 @@ __attribute__((noinline)) static uint16_t finalize_parsing_helper(void) {
if (G_called_from_swap) {
// Ensure the values are the same that the ones that have been previously validated
if (strcmp(strings.common.fullAmount, displayBuffer) != 0) {
PRINTF("APDU_RESPONSE_MODE_CHECK_FAILED, amount check failed\n");
PRINTF("Expected %s\n", strings.common.fullAmount);
PRINTF("Received %s\n", displayBuffer);
return APDU_RESPONSE_MODE_CHECK_FAILED;
send_swap_error(ERROR_WRONG_AMOUNT,
APP_CODE_DEFAULT,
strings.common.fullAmount,
displayBuffer);
// unreachable
os_sched_exit(0);
}
} else {
strlcpy(strings.common.fullAmount, displayBuffer, sizeof(strings.common.fullAmount));
Expand All @@ -536,10 +595,12 @@ __attribute__((noinline)) static uint16_t finalize_parsing_helper(void) {
if (G_called_from_swap) {
// Ensure the values are the same that the ones that have been previously validated
if (strcmp(strings.common.maxFee, displayBuffer) != 0) {
PRINTF("APDU_RESPONSE_MODE_CHECK_FAILED, fees check failed\n");
PRINTF("Expected %s\n", strings.common.maxFee);
PRINTF("Received %s\n", displayBuffer);
return APDU_RESPONSE_MODE_CHECK_FAILED;
send_swap_error(ERROR_WRONG_FEES,
APP_CODE_DEFAULT,
strings.common.maxFee,
displayBuffer);
// unreachable
os_sched_exit(0);
}
} else {
strlcpy(strings.common.maxFee, displayBuffer, sizeof(strings.common.maxFee));
Expand Down
Loading