From 9d4dfbe1bf16a4f082c6bd540d46e52b78398791 Mon Sep 17 00:00:00 2001 From: TamtamHero <10632523+TamtamHero@users.noreply.github.com> Date: Mon, 29 Jun 2020 15:43:02 +0200 Subject: [PATCH 1/5] Add Swap feature --- Makefile | 5 +- src/chainConfig.h | 4 +- src/handle_check_address.c | 70 +++++ src/handle_check_address.h | 9 + src/handle_get_printable_amount.c | 33 +++ src/handle_get_printable_amount.h | 9 + src/handle_swap_sign_transaction.c | 67 +++++ src/handle_swap_sign_transaction.h | 9 + src/main.c | 240 ++++++++++++------ src/shared_context.h | 11 +- src/swap_lib_calls.h | 52 ++++ src/tokens.h | 4 +- src/ui_flow.c | 6 +- src/utils.c | 38 +++ src/utils.h | 4 + src_common/ethUtils.c | 39 +-- src_common/ethUtils.h | 11 +- src_common/uint256.c | 122 +++------ src_common/uint256.h | 2 + src_features/getPublicKey/cmd_getPublicKey.c | 2 +- src_features/signMessage/cmd_signMessage.c | 10 +- src_features/signTx/cmd_signTx.c | 2 +- src_features/signTx/logic_signTx.c | 190 +++++++------- src_features/signTx/ui_common_signTx.c | 5 +- .../ui_flow_stark_deposit.c | 2 +- .../ui_flow_stark_escape.c | 2 +- .../ui_flow_stark_register.c | 4 +- .../ui_flow_stark_verify_escape.c | 2 +- .../ui_flow_stark_verifyVaultId.c | 2 +- .../ui_flow_stark_withdrawal.c | 2 +- src_features/stark_sign/cmd_stark_sign.c | 4 +- 31 files changed, 650 insertions(+), 312 deletions(-) create mode 100644 src/handle_check_address.c create mode 100644 src/handle_check_address.h create mode 100644 src/handle_get_printable_amount.c create mode 100644 src/handle_get_printable_amount.h create mode 100644 src/handle_swap_sign_transaction.c create mode 100644 src/handle_swap_sign_transaction.h create mode 100644 src/swap_lib_calls.h diff --git a/Makefile b/Makefile index 0508925..b3800a5 100755 --- a/Makefile +++ b/Makefile @@ -18,6 +18,7 @@ ifeq ($(BOLOS_SDK),) $(error Environment variable BOLOS_SDK is not set) endif + include $(BOLOS_SDK)/Makefile.defines DEFINES_LIB = USE_LIB_ETHEREUM @@ -245,7 +246,7 @@ DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=72 endif # Enabling debug PRINTF -DEBUG:=0 +DEBUG :=0 ifneq ($(DEBUG),0) DEFINES += HAVE_STACK_OVERFLOW_CHECK ifeq ($(TARGET_NAME),TARGET_NANOX) @@ -283,7 +284,7 @@ endif CC := $(CLANGPATH)clang #CFLAGS += -O0 -CFLAGS += -O3 -Os +CFLAGS += -O3 -Os -I/usr/include AS := $(GCCPATH)arm-none-eabi-gcc diff --git a/src/chainConfig.h b/src/chainConfig.h index 7229d9d..39708bd 100644 --- a/src/chainConfig.h +++ b/src/chainConfig.h @@ -56,12 +56,12 @@ typedef enum chain_kind_e { } chain_kind_t; typedef struct chain_config_s { - const char* coinName; // ticker + char coinName[10]; // ticker uint32_t chainId; chain_kind_t kind; #ifdef TARGET_BLUE - const char* header_text; unsigned int color_header; + char header_text[13]; unsigned int color_dashboard; #endif // TARGET_BLUE diff --git a/src/handle_check_address.c b/src/handle_check_address.c new file mode 100644 index 0000000..daec34c --- /dev/null +++ b/src/handle_check_address.c @@ -0,0 +1,70 @@ +#include "handle_check_address.h" +#include "os.h" +#include "shared_context.h" +#include "ethUtils.h" +#include "string.h" + +#define ZERO(x) os_memset(x, 0, sizeof(x)) + +void handle_check_address(check_address_parameters_t* params, chain_config_t* chain_config) { + PRINTF("Params on the address %d\n",(unsigned int)params); + PRINTF("Address to check %s\n",params->address_to_check); + PRINTF("Inside handle_check_address\n"); + params->result = 0; + if (params->address_to_check == 0) { + PRINTF("Address to check == 0\n"); + return; + } + + uint8_t i; + uint8_t *bip32_path_ptr = params->address_parameters; + uint8_t bip32PathLength = *(bip32_path_ptr++); + cx_sha3_t local_sha3; + + // Common memory is used for locals that are not used concurrently + union group1 + { + uint32_t bip32Path[MAX_BIP32_PATH]; + cx_ecfp_private_key_t privateKey; + char address[51]; + } locals_union1; + union group2 + { + uint8_t privateKeyData[32]; + cx_ecfp_public_key_t publicKey; + } locals_union2; + + + if ((bip32PathLength < 0x01) || + (bip32PathLength > MAX_BIP32_PATH) || + (bip32PathLength*4 != params->address_parameters_length - 1)) { + PRINTF("Invalid path\n"); + return; + } + for (i = 0; i < bip32PathLength; i++) { + locals_union1.bip32Path[i] = U4BE(bip32_path_ptr, 0); + bip32_path_ptr += 4; + } + os_perso_derive_node_bip32(CX_CURVE_256K1, locals_union1.bip32Path, bip32PathLength, locals_union2.privateKeyData, NULL); + ZERO(&locals_union1); + cx_ecfp_init_private_key(CX_CURVE_256K1, locals_union2.privateKeyData, 32, &locals_union1.privateKey); + ZERO(&locals_union2); + cx_ecfp_generate_pair(CX_CURVE_256K1, &locals_union2.publicKey, &locals_union1.privateKey, 1); + ZERO(&locals_union1); + getEthAddressStringFromKey(&locals_union2.publicKey, (uint8_t*)locals_union1.address, &local_sha3, chain_config); + ZERO(&locals_union2); + + uint8_t offset_0x = 0; + if(memcmp(params->address_to_check, "0x", 2) == 0){ + offset_0x = 2; + } + + if ((strlen(locals_union1.address) != strlen(params->address_to_check + offset_0x)) || + os_memcmp(locals_union1.address, params->address_to_check + offset_0x, strlen(locals_union1.address)) != 0) { + os_memcpy(params->address_to_check, locals_union1.address, 45); + PRINTF("Addresses doesn't match\n"); + return; + } + PRINTF("Addresses match\n"); + params->result = 1; +} \ No newline at end of file diff --git a/src/handle_check_address.h b/src/handle_check_address.h new file mode 100644 index 0000000..7dc175e --- /dev/null +++ b/src/handle_check_address.h @@ -0,0 +1,9 @@ +#ifndef _HANDLE_CHECK_ADDRESS_H_ +#define _HANDLE_CHECK_ADDRESS_H_ + +#include "swap_lib_calls.h" +#include "chainConfig.h" + +void handle_check_address(check_address_parameters_t* check_address_params, chain_config_t* chain_config); + +#endif // _HANDLE_CHECK_ADDRESS_H_ \ No newline at end of file diff --git a/src/handle_get_printable_amount.c b/src/handle_get_printable_amount.c new file mode 100644 index 0000000..6f7d36d --- /dev/null +++ b/src/handle_get_printable_amount.c @@ -0,0 +1,33 @@ +#include "handle_get_printable_amount.h" +#include "shared_context.h" +#include "ethUtils.h" +#include "utils.h" +#include "uint256.h" +#include "string.h" +#include + + +void handle_get_printable_amount( get_printable_amount_parameters_t* params, chain_config_t *config) { + uint8_t decimals; + char ticker[MAX_TICKER_LEN]; + os_memset(params->printable_amount, 0, sizeof(params->printable_amount)); + if (params->amount_length > 32) { + PRINTF("Amount is too big, 32 bytes max but buffer has %u bytes", params->amount_length); + os_lib_end(); + } + if(!parse_swap_config(params->coin_configuration, params->coin_configuration_length, ticker, &decimals)){ + PRINTF("Error while parsing config\n"); + os_lib_end(); + } + + // If the amount is a fee, its value is nominated in ETH even if we're doing an ERC20 swap + if(params->is_fee){ + uint8_t ticker_len = strnlen(config->coinName, sizeof(config->coinName)); + memcpy(ticker, config->coinName, ticker_len); + ticker[ticker_len] = ' '; + ticker[ticker_len+1] = '\0'; + decimals = WEI_TO_ETHER; + } + + amountToString(params->amount, params->amount_length, decimals, ticker, params->printable_amount, sizeof(params->printable_amount)); +} \ No newline at end of file diff --git a/src/handle_get_printable_amount.h b/src/handle_get_printable_amount.h new file mode 100644 index 0000000..d68f7e1 --- /dev/null +++ b/src/handle_get_printable_amount.h @@ -0,0 +1,9 @@ +#ifndef _HANDLE_GET_PRINTABLE_AMOUNT_H_ +#define _HANDLE_GET_PRINTABLE_AMOUNT_H_ + +#include "swap_lib_calls.h" +#include "chainConfig.h" + +void handle_get_printable_amount(get_printable_amount_parameters_t* get_printable_amount_params, chain_config_t *config); + +#endif // _HANDLE_GET_PRINTABLE_AMOUNT_H_ \ No newline at end of file diff --git a/src/handle_swap_sign_transaction.c b/src/handle_swap_sign_transaction.c new file mode 100644 index 0000000..cd24f2e --- /dev/null +++ b/src/handle_swap_sign_transaction.c @@ -0,0 +1,67 @@ +#include "handle_swap_sign_transaction.h" +#include "usbd_core.h" +#include "ux.h" +#include "shared_context.h" +#include "utils.h" + + +void copy_transaction_parameters(create_transaction_parameters_t* sign_transaction_params, chain_config_t *config) { + // first copy parameters to stack, and then to global data. + // We need this "trick" as the input data position can overlap with app-ethereum globals + txStringProperties_t stack_data; + memset(&stack_data, 0, sizeof(stack_data)); + strncpy(stack_data.fullAddress, sign_transaction_params->destination_address, sizeof(stack_data.fullAddress)); + if ((stack_data.fullAddress[sizeof(stack_data.fullAddress) - 1] != '\0') || + (sign_transaction_params->amount_length > 8) || + (sign_transaction_params->fee_amount_length > 8)) { + os_lib_end(); + } + + uint8_t decimals; + char ticker[MAX_TICKER_LEN]; + if(!parse_swap_config(sign_transaction_params->coin_configuration, sign_transaction_params->coin_configuration_length, ticker, &decimals)){ + PRINTF("Error while parsing config\n"); + os_lib_end(); + } + amountToString(sign_transaction_params->amount, sign_transaction_params->amount_length, decimals, ticker, stack_data.fullAmount, sizeof(stack_data.fullAmount)); + + // If the amount is a fee, its value is nominated in ETH even if we're doing an ERC20 swap + strcpy(ticker, config->coinName); + decimals = WEI_TO_ETHER; + amountToString(sign_transaction_params->fee_amount, sign_transaction_params->fee_amount_length, decimals, ticker, stack_data.maxFee, sizeof(stack_data.maxFee)); + + memcpy(&strings.common, &stack_data, sizeof(stack_data)); +} + +void handle_swap_sign_transaction(create_transaction_parameters_t* sign_transaction_params, chain_config_t *config) { + copy_transaction_parameters(sign_transaction_params, config); + chainConfig = config; + reset_app_context(); + called_from_swap = true; + io_seproxyhal_init(); + + if (N_storage.initialized != 0x01) { + internalStorage_t storage; + storage.dataAllowed = 0x00; + storage.contractDetails = 0x00; + storage.initialized = 0x01; + nvm_write((void*)&N_storage, (void*)&storage, sizeof(internalStorage_t)); + } + dataAllowed = N_storage.dataAllowed; + contractDetails = N_storage.contractDetails; + + UX_INIT(); + USB_power(0); + USB_power(1); + //ui_idle(); + PRINTF("USB power ON/OFF\n"); +#ifdef TARGET_NANOX + // grab the current plane mode setting + G_io_app.plane_mode = os_setting_get(OS_SETTING_PLANEMODE, NULL, 0); +#endif // TARGET_NANOX +#ifdef HAVE_BLE + BLE_power(0, NULL); + BLE_power(1, "Nano X"); +#endif // HAVE_BLE + app_main(); +} \ No newline at end of file diff --git a/src/handle_swap_sign_transaction.h b/src/handle_swap_sign_transaction.h new file mode 100644 index 0000000..712a177 --- /dev/null +++ b/src/handle_swap_sign_transaction.h @@ -0,0 +1,9 @@ +#ifndef _HANDLE_SWAP_SIGN_TRANSACTION_H_ +#define _HANDLE_SWAP_SIGN_TRANSACTION_H_ + +#include "swap_lib_calls.h" +#include "chainConfig.h" + +void handle_swap_sign_transaction(create_transaction_parameters_t* get_printable_amount_params, chain_config_t *config); + +#endif // _HANDLE_SWAP_SIGN_TRANSACTION_H_ \ No newline at end of file diff --git a/src/main.c b/src/main.c index 99cee90..a64caff 100644 --- a/src/main.c +++ b/src/main.c @@ -30,6 +30,11 @@ #include "glyphs.h" #include "utils.h" +#include "swap_lib_calls.h" +#include "handle_swap_sign_transaction.h" +#include "handle_get_printable_amount.h" +#include "handle_check_address.h" + #ifdef HAVE_STARKWARE #include "stark_crypto.h" #endif @@ -46,8 +51,7 @@ txContext_t txContext; tmpContent_t tmpContent; dataContext_t dataContext; strings_t strings; - -cx_sha3_t sha3; +cx_sha3_t global_sha3; uint8_t dataAllowed; uint8_t contractDetails; @@ -57,6 +61,7 @@ char addressSummary[32]; #endif bool dataPresent; contract_call_t contractProvisioned; +bool called_from_swap; #ifdef HAVE_STARKWARE bool quantumSet; #endif @@ -83,13 +88,14 @@ static const char const CONTRACT_ADDRESS[] = "New contract"; chain_config_t *chainConfig; void reset_app_context() { - PRINTF("!!RESET_APP_CONTEXT\n"); + //PRINTF("!!RESET_APP_CONTEXT\n"); appState = APP_STATE_IDLE; os_memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN); contractProvisioned = CONTRACT_NONE; -#ifdef HAVE_STARKWARE + called_from_swap = false; +#ifdef HAVE_STARKWARE quantumSet = false; -#endif +#endif os_memset((uint8_t*)&txContext, 0, sizeof(txContext)); os_memset((uint8_t*)&tmpContent, 0, sizeof(tmpContent)); } @@ -506,10 +512,10 @@ void handleApdu(unsigned int *flags, unsigned int *tx) { break; } CLOSE_TRY; - return; + return; } -#endif +#endif if (G_io_apdu_buffer[OFFSET_CLA] != CLA) { THROW(0x6E00); @@ -579,7 +585,7 @@ void handleApdu(unsigned int *flags, unsigned int *tx) { END_TRY; } -void sample_main(void) { +void app_main(void) { unsigned int rx = 0; unsigned int tx = 0; unsigned int flags = 0; @@ -611,7 +617,7 @@ void sample_main(void) { handleApdu(&flags, &tx); } CATCH(EXCEPTION_IO_RESET) { - THROW(EXCEPTION_IO_RESET); + THROW(EXCEPTION_IO_RESET); } CATCH_OTHER(e) { switch (e & 0xF000) { @@ -686,7 +692,7 @@ unsigned char io_event(unsigned char channel) { { }); break; -#endif +#endif } // close the event if not done previously (by a display or whatever) @@ -698,7 +704,7 @@ unsigned char io_event(unsigned char channel) { return 1; } -void app_exit(void) { +void app_exit() { BEGIN_TRY_L(exit) { TRY_L(exit) { @@ -711,65 +717,13 @@ void app_exit(void) { END_TRY_L(exit); } -chain_config_t const C_chain_config = { - .coinName = CHAINID_COINNAME " ", - .chainId = CHAIN_ID, - .kind = CHAIN_KIND, -#ifdef TARGET_BLUE - .color_header = COLOR_APP, - .color_dashboard = COLOR_APP_LIGHT, - .header_text = CHAINID_UPCASE, -#endif // TARGET_BLUE -}; -__attribute__((section(".boot"))) int main(int arg0) { -#ifdef USE_LIB_ETHEREUM - chain_config_t local_chainConfig; - os_memmove(&local_chainConfig, &C_chain_config, sizeof(chain_config_t)); - unsigned int libcall_params[3]; - unsigned char coinName[sizeof(CHAINID_COINNAME)]; - strcpy(coinName, CHAINID_COINNAME); -#ifdef TARGET_BLUE - unsigned char coinNameUP[sizeof(CHAINID_UPCASE)]; - strcpy(coinNameUP, CHAINID_UPCASE); - local_chainConfig.header_text = coinNameUP; -#endif // TARGET_BLUE - local_chainConfig.coinName = coinName; - BEGIN_TRY { - TRY { - // ensure syscall will accept us - check_api_level(CX_COMPAT_APILEVEL); - // delegate to Ethereum app/lib - libcall_params[0] = "Ethereum"; - libcall_params[1] = 0x100; // use the Init call, as we won't exit - libcall_params[2] = &local_chainConfig; - os_lib_call(&libcall_params); - } - FINALLY { - app_exit(); - } - } - END_TRY; -#else - // exit critical section - __asm volatile("cpsie i"); - - if (arg0) { - if (((unsigned int *)arg0)[0] != 0x100) { - os_lib_throw(INVALID_PARAMETER); - } - chainConfig = (chain_config_t *)((unsigned int *)arg0)[1]; - } - else { - chainConfig = (chain_config_t *)PIC(&C_chain_config); - } +void coin_main_with_config(chain_config_t *config) { + chainConfig = config; reset_app_context(); tmpCtx.transactionContext.currentTokenIndex = 0; - // ensure exception will work as planned - os_boot(); - for (;;) { UX_INIT(); @@ -783,11 +737,11 @@ __attribute__((section(".boot"))) int main(int arg0) { #endif // TARGET_NANOX if (N_storage.initialized != 0x01) { - internalStorage_t storage; - storage.dataAllowed = 0x00; - storage.contractDetails = 0x00; - storage.initialized = 0x01; - nvm_write((void*)&N_storage, (void*)&storage, sizeof(internalStorage_t)); + internalStorage_t storage; + storage.dataAllowed = 0x00; + storage.contractDetails = 0x00; + storage.initialized = 0x01; + nvm_write((void*)&N_storage, (void*)&storage, sizeof(internalStorage_t)); } dataAllowed = N_storage.dataAllowed; contractDetails = N_storage.contractDetails; @@ -801,28 +755,156 @@ __attribute__((section(".boot"))) int main(int arg0) { BLE_power(0, NULL); BLE_power(1, "Nano X"); #endif // HAVE_BLE - #if defined(TARGET_BLUE) + +#if defined(TARGET_BLUE) // setup the status bar colors (remembered after wards, even more if another app does not resetup after app switch) UX_SET_STATUS_BAR_COLOR(0xFFFFFF, chainConfig->color_header); - #endif // #if defined(TARGET_BLUE) +#endif // #if defined(TARGET_BLUE) - sample_main(); + app_main(); } CATCH(EXCEPTION_IO_RESET) { - // reset IO and UX before continuing - CLOSE_TRY; - continue; + // reset IO and UX before continuing + CLOSE_TRY; + continue; } CATCH_ALL { - CLOSE_TRY; - break; + CLOSE_TRY; + break; } FINALLY { } } END_TRY; } - app_exit(); + app_exit(); +} + +void init_coin_config(chain_config_t *coin_config) { + os_memset(coin_config, 0, sizeof(chain_config_t)); + strcpy(coin_config->coinName, CHAINID_COINNAME " "); + coin_config->chainId = CHAIN_ID; + coin_config->kind = CHAIN_KIND; +#ifdef TARGET_BLUE + coin_config.color_header = COLOR_APP; + coin_config.color_dashboard = COLOR_APP_LIGHT; + strcpy(coin_config->header_text, CHAINID_UPCASE); +#endif // TARGET_BLUE +} + +void coin_main() { + chain_config_t coin_config; + init_coin_config(&coin_config); + coin_main_with_config(&coin_config); +} + +void library_main_with_config(chain_config_t *config, unsigned int command, unsigned int* call_parameters) { + BEGIN_TRY { + TRY { + check_api_level(CX_COMPAT_APILEVEL); + PRINTF("Inside a library \n"); + switch (command) { + case CHECK_ADDRESS: + handle_check_address((check_address_parameters_t*)call_parameters, config); + break; + case SIGN_TRANSACTION: + handle_swap_sign_transaction((create_transaction_parameters_t*)call_parameters, config); + break; + case GET_PRINTABLE_AMOUNT: + handle_get_printable_amount((get_printable_amount_parameters_t*)call_parameters, config); + break; + } + os_lib_end(); + } + FINALLY {} + } + END_TRY; +} + +void library_main(unsigned int call_id, unsigned int* call_parameters) { + chain_config_t coin_config; + init_coin_config(&coin_config); + library_main_with_config(&coin_config, call_id, call_parameters); +} + +__attribute__((section(".boot"))) int main(int arg0) { +#ifdef USE_LIB_ETHEREUM + BEGIN_TRY { + TRY { + unsigned int libcall_params[5]; + chain_config_t local_chainConfig; + init_coin_config(&local_chainConfig); + PRINTF("Hello from Eth-clone\n"); + check_api_level(CX_COMPAT_APILEVEL); + // delegate to Ethereum app/lib + libcall_params[0] = "Ethereum"; + libcall_params[1] = 0x100; + libcall_params[2] = RUN_APPLICATION; + libcall_params[3] = &local_chainConfig; + libcall_params[4] = 0; + if (arg0) { + // call as a library + libcall_params[2] = ((unsigned int *)arg0)[1]; + libcall_params[4] = ((unsigned int *)arg0)[3]; // library arguments + os_lib_call(&libcall_params); + ((unsigned int *)arg0)[0] = libcall_params[1]; + os_lib_end(); + } + else { + // launch coin application + libcall_params[1] = 0x100; // use the Init call, as we won't exit + os_lib_call(&libcall_params); + } + } + FINALLY {} + } + END_TRY; + // no return +#else + // exit critical section + __asm volatile("cpsie i"); + + // ensure exception will work as planned + os_boot(); + + if (!arg0) { + // called from dashboard as standalone eth app + coin_main(); + return 0; + } + + if (((unsigned int *)arg0)[0] != 0x100) { + app_exit(); + return 0; + } + unsigned int command = ((unsigned int *)arg0)[1]; + chain_config_t * chain_config = ((unsigned int *)arg0)[2]; + switch (command) { + case RUN_APPLICATION: + // coin application launched from dashboard + if (chain_config == NULL) + app_exit(); + else + coin_main_with_config(chain_config); + break; + default: + if (chain_config == NULL) + // Called as standalone eth library + library_main(command, ((unsigned int *)arg0)[3]);// called as bitcoin library + else + // Called as a library from an altcoin + library_main_with_config(chain_config, command, ((unsigned int *)arg0)[3]);// called as coin library + break; + } #endif return 0; } + + + + + + + + + diff --git a/src/shared_context.h b/src/shared_context.h index 2cc24b6..adc3b9f 100644 --- a/src/shared_context.h +++ b/src/shared_context.h @@ -125,11 +125,11 @@ typedef enum { #endif } contract_call_t; -typedef struct strData_t { +typedef struct txStringProperties_t { char fullAddress[43]; char fullAmount[50]; char maxFee[50]; -} strData_t; +} txStringProperties_t; typedef struct strDataTmp_t { char tmp[100]; @@ -137,7 +137,7 @@ typedef struct strDataTmp_t { } strDataTmp_t; typedef union { - strData_t common; + txStringProperties_t common; strDataTmp_t tmp; } strings_t; @@ -148,7 +148,7 @@ extern txContext_t txContext; extern tmpContent_t tmpContent; extern dataContext_t dataContext; extern strings_t strings; -extern cx_sha3_t sha3; +extern cx_sha3_t global_sha3; extern const internalStorage_t N_storage_real; #ifdef TARGET_BLUE @@ -156,6 +156,9 @@ extern bagl_element_t tmp_element; extern char addressSummary[32]; #endif +extern bool called_from_swap; +extern uint8_t dataAllowed; +extern uint8_t contractDetails; extern bool dataPresent; extern uint8_t appState; extern contract_call_t contractProvisioned; diff --git a/src/swap_lib_calls.h b/src/swap_lib_calls.h new file mode 100644 index 0000000..989c158 --- /dev/null +++ b/src/swap_lib_calls.h @@ -0,0 +1,52 @@ +#ifndef SWAP_LIB_CALLS +#define SWAP_LIB_CALLS + +#include "stdbool.h" + +#define RUN_APPLICATION 1 + +#define SIGN_TRANSACTION 2 + +#define CHECK_ADDRESS 3 + +#define GET_PRINTABLE_AMOUNT 4 + +// structure that should be send to specific coin application to get address +typedef struct check_address_parameters_s { + // IN + unsigned char* coin_configuration; + unsigned char coin_configuration_length; + // serialized path, segwit, version prefix, hash used, dictionary etc. + // fields and serialization format depends on spesific coin app + unsigned char* address_parameters; + unsigned char address_parameters_length; + char *address_to_check; + char *extra_id_to_check; + // OUT + int result; +} check_address_parameters_t; + +// structure that should be send to specific coin application to get printable amount +typedef struct get_printable_amount_parameters_s { + // IN + unsigned char* coin_configuration; + unsigned char coin_configuration_length; + unsigned char* amount; + unsigned char amount_length; + bool is_fee; + // OUT + char printable_amount[30]; +} get_printable_amount_parameters_t; + +typedef struct create_transaction_parameters_s { + unsigned char* coin_configuration; + unsigned char coin_configuration_length; + unsigned char* amount; + unsigned char amount_length; + unsigned char* fee_amount; + unsigned char fee_amount_length; + char *destination_address; + char *destination_address_extra_id; +} create_transaction_parameters_t; + +#endif diff --git a/src/tokens.h b/src/tokens.h index 5db37e7..e12f6de 100644 --- a/src/tokens.h +++ b/src/tokens.h @@ -20,12 +20,14 @@ #include +#define MAX_TICKER_LEN 12 // 10 characters + ' ' + '\0' + typedef struct tokenDefinition_t { #ifdef HAVE_CONTRACT_NAME_IN_DESCRIPTOR uint8_t contractName[20]; #endif uint8_t address[20]; - uint8_t ticker[12]; // 10 characters + ' \0' + uint8_t ticker[MAX_TICKER_LEN]; uint8_t decimals; } tokenDefinition_t; diff --git a/src/ui_flow.c b/src/ui_flow.c index 12f0a03..baa3d7b 100644 --- a/src/ui_flow.c +++ b/src/ui_flow.c @@ -39,13 +39,13 @@ UX_FLOW_DEF_VALID( &C_icon_dashboard_x, "Quit", }); -const ux_flow_step_t * const ux_idle_flow [] = { +UX_FLOW(ux_idle_flow, &ux_idle_flow_1_step, &ux_idle_flow_2_step, &ux_idle_flow_3_step, &ux_idle_flow_4_step, - FLOW_END_STEP, -}; + FLOW_LOOP +); #if defined(TARGET_NANOS) diff --git a/src/utils.c b/src/utils.c index e40c8ed..b991f5f 100644 --- a/src/utils.c +++ b/src/utils.c @@ -19,7 +19,9 @@ #include #include "ethUstream.h" +#include "ethUtils.h" #include "uint256.h" +#include "tokens.h" static const unsigned char hex_digits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; @@ -75,4 +77,40 @@ uint32_t getV(txContent_t *txContent) { THROW(EXCEPTION); } return v; +} + +void amountToString(uint8_t* amount, uint8_t amount_size, uint8_t decimals, char* ticker, char* out_buffer, uint8_t out_buffer_size){ + uint256_t amount_256; + char tmp_buffer[100]; + convertUint256BE(amount, amount_size, &amount_256); + tostring256(&amount_256, 10, tmp_buffer, 100); + + uint8_t amount_len = strnlen(tmp_buffer, sizeof(tmp_buffer)); + uint8_t ticker_len = strnlen(ticker, MAX_TICKER_LEN); + + memcpy(out_buffer, ticker, MIN(out_buffer_size, ticker_len)); + + adjustDecimals(tmp_buffer, amount_len, out_buffer + ticker_len, out_buffer_size - ticker_len -1, decimals); + out_buffer[out_buffer_size-1] = '\0'; +} + +bool parse_swap_config(uint8_t* config, uint8_t config_len, char* ticker, uint8_t* decimals){ + uint8_t ticker_len, offset = 0; + if (config_len == 0){ + return false; + } + ticker_len = config[offset++]; + if(ticker_len == 0 || ticker_len > MAX_TICKER_LEN - 2 || config_len - offset < ticker_len){ + return false; + } + memcpy(ticker, config+offset, ticker_len); + offset += ticker_len; + ticker[ticker_len] = ' '; + ticker[ticker_len+1] = '\0'; + + if(config_len - offset < 1){ + return false; + } + *decimals = config[offset]; + return true; } \ No newline at end of file diff --git a/src/utils.h b/src/utils.h index d918475..ea8b5de 100644 --- a/src/utils.h +++ b/src/utils.h @@ -30,4 +30,8 @@ int local_strchr(char *string, char ch); uint32_t getV(txContent_t *txContent); +void amountToString(uint8_t* amount, uint8_t amount_len, uint8_t decimals, char* ticker, char* out_buffer, uint8_t out_buffer_size); + +bool parse_swap_config(uint8_t* config, uint8_t config_len, char* ticker, uint8_t* decimals); + #endif /* _UTILS_H_ */ \ No newline at end of file diff --git a/src_common/ethUtils.c b/src_common/ethUtils.c index 5bb79f9..8e7ae08 100644 --- a/src_common/ethUtils.c +++ b/src_common/ethUtils.c @@ -32,8 +32,6 @@ #include "ethUtils.h" #include "chainConfig.h" -extern chain_config_t *chainConfig; - bool rlpCanDecode(uint8_t *buffer, uint32_t bufferLength, bool *valid) { if (*buffer <= 0x7f) { } else if (*buffer <= 0xb7) { @@ -156,15 +154,16 @@ char convertDigit(uint8_t *address, uint8_t index, uint8_t *hash) { } void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out, - cx_sha3_t *sha3Context) { + cx_sha3_t *sha3Context, chain_config_t* chain_config) { uint8_t hashAddress[32]; cx_keccak_init(sha3Context, 256); cx_hash((cx_hash_t*)sha3Context, CX_LAST, publicKey->W + 1, 64, hashAddress, 32); - getEthAddressStringFromBinary(hashAddress + 12, out, sha3Context); + getEthAddressStringFromBinary(hashAddress + 12, out, sha3Context, chain_config); } void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out, - cx_sha3_t *sha3Context) { + cx_sha3_t *sha3Context, chain_config_t* chain_config) { + UNUSED(chain_config); uint8_t hashChecksum[32]; uint8_t i; cx_keccak_init(sha3Context, 256); @@ -180,37 +179,43 @@ void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out, static const uint8_t const HEXDIGITS[] = "0123456789abcdef"; void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out, - cx_sha3_t *sha3Context) { + cx_sha3_t *sha3Context, chain_config_t* chain_config) { uint8_t hashAddress[32]; cx_keccak_init(sha3Context, 256); cx_hash((cx_hash_t*)sha3Context, CX_LAST, publicKey->W + 1, 64, hashAddress, 32); - getEthAddressStringFromBinary(hashAddress + 12, out, sha3Context); + getEthAddressStringFromBinary(hashAddress + 12, out, sha3Context, chain_config); } void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out, - cx_sha3_t *sha3Context) { - uint8_t hashChecksum[32]; - uint8_t tmp[100]; + cx_sha3_t *sha3Context, chain_config_t* chain_config) { + + // save some precious stack space + union locals_union + { + uint8_t hashChecksum[32]; + uint8_t tmp[51]; + } locals_union; + uint8_t i; bool eip1191 = false; uint32_t offset = 0; - switch(chainConfig->chainId) { + switch(chain_config->chainId) { case 30: case 31: eip1191 = true; break; } if (eip1191) { - snprintf((char*)tmp, sizeof(tmp), "%d0x", chainConfig->chainId); - offset = strlen((char*)tmp); + snprintf((char*)locals_union.tmp, sizeof(locals_union.tmp), "%d0x", chain_config->chainId); + offset = strlen((char*)locals_union.tmp); } for (i = 0; i < 20; i++) { uint8_t digit = address[i]; - tmp[offset + 2 * i] = HEXDIGITS[(digit >> 4) & 0x0f]; - tmp[offset + 2 * i + 1] = HEXDIGITS[digit & 0x0f]; + locals_union.tmp[offset + 2 * i] = HEXDIGITS[(digit >> 4) & 0x0f]; + locals_union.tmp[offset + 2 * i + 1] = HEXDIGITS[digit & 0x0f]; } cx_keccak_init(sha3Context, 256); - cx_hash((cx_hash_t*)sha3Context, CX_LAST, tmp, offset + 40, hashChecksum, 32); + cx_hash((cx_hash_t*)sha3Context, CX_LAST, locals_union.tmp, offset + 40, locals_union.hashChecksum, 32); for (i = 0; i < 40; i++) { uint8_t digit = address[i / 2]; if ((i % 2) == 0) { @@ -222,7 +227,7 @@ void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out, out[i] = HEXDIGITS[digit]; } else { - int v = (hashChecksum[i / 2] >> (4 * (1 - i % 2))) & 0x0f; + int v = (locals_union.hashChecksum[i / 2] >> (4 * (1 - i % 2))) & 0x0f; if (v >= 8) { out[i] = HEXDIGITS[digit] - 'a' + 'A'; } diff --git a/src_common/ethUtils.h b/src_common/ethUtils.h index d788acc..5213a6f 100644 --- a/src_common/ethUtils.h +++ b/src_common/ethUtils.h @@ -21,7 +21,7 @@ #include #include "cx.h" - +#include "chainConfig.h" /** * @brief Decode an RLP encoded field - see * https://github.com/ethereum/wiki/wiki/RLP @@ -43,14 +43,17 @@ void getEthAddressFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out, cx_sha3_t *sha3Context); void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out, - cx_sha3_t *sha3Context); + cx_sha3_t *sha3Context, + chain_config_t* chain_config); void getEthAddressStringFromBinary(uint8_t *address, uint8_t *out, - cx_sha3_t *sha3Context); + cx_sha3_t *sha3Context, + chain_config_t* chain_config); bool adjustDecimals(char *src, uint32_t srcLength, char *target, uint32_t targetLength, uint8_t decimals); +__attribute__((no_instrument_function)) inline int allzeroes(uint8_t *buf, int n) { for (int i = 0; i < n; ++i) { if (buf[i]) { @@ -59,7 +62,7 @@ inline int allzeroes(uint8_t *buf, int n) { } return 1; } - +__attribute__((no_instrument_function)) inline int ismaxint(uint8_t *buf, int n) { for (int i = 0; i < n; ++i) { if (buf[i] != 0xff) { diff --git a/src_common/uint256.c b/src_common/uint256.c index 54ac8ba..e67f195 100644 --- a/src_common/uint256.c +++ b/src_common/uint256.c @@ -325,98 +325,40 @@ void mul128(uint128_t *number1, uint128_t *number2, uint128_t *target) { add128(&tmp, &tmp2, target); } +void write_u64_be(uint8_t *buffer, uint64_t value) { + buffer[0] = ((value >> 56) & 0xff); + buffer[1] = ((value >> 48) & 0xff); + buffer[2] = ((value >> 40) & 0xff); + buffer[3] = ((value >> 32) & 0xff); + buffer[4] = ((value >> 24) & 0xff); + buffer[5] = ((value >> 16) & 0xff); + buffer[6] = ((value >> 8) & 0xff); + buffer[7] = (value & 0xff); +} + +void read_u64_be(uint8_t *in, uint64_t *out) { + uint8_t *out_ptr = (uint8_t*)out; + *out_ptr++ = in[7]; + *out_ptr++ = in[6]; + *out_ptr++ = in[5]; + *out_ptr++ = in[4]; + *out_ptr++ = in[3]; + *out_ptr++ = in[2]; + *out_ptr++ = in[1]; + *out_ptr = in[0]; +} + void mul256(uint256_t *number1, uint256_t *number2, uint256_t *target) { - uint128_t top[4]; - uint128_t bottom[4]; - uint128_t products[4][4]; - uint128_t tmp, tmp2, fourth64, third64, second64, first64; - uint256_t target1, target2; - UPPER(top[0]) = 0; - LOWER(top[0]) = UPPER(UPPER_P(number1)); - UPPER(top[1]) = 0; - LOWER(top[1]) = LOWER(UPPER_P(number1)); - UPPER(top[2]) = 0; - LOWER(top[2]) = UPPER(LOWER_P(number1)); - UPPER(top[3]) = 0; - LOWER(top[3]) = LOWER(LOWER_P(number1)); - UPPER(bottom[0]) = 0; - LOWER(bottom[0]) = UPPER(UPPER_P(number2)); - UPPER(bottom[1]) = 0; - LOWER(bottom[1]) = LOWER(UPPER_P(number2)); - UPPER(bottom[2]) = 0; - LOWER(bottom[2]) = UPPER(LOWER_P(number2)); - UPPER(bottom[3]) = 0; - LOWER(bottom[3]) = LOWER(LOWER_P(number2)); - - for (int y = 3; y > -1; y--) { - for (int x = 3; x > -1; x--) { - mul128(&top[x], &bottom[y], &products[3 - x][y]); - } + uint8_t num1[32], num2[32], result[64]; + os_memset(&result, 0, sizeof(result)); + for(uint8_t i = 0; i<4; i++){ + write_u64_be(num1+i*sizeof(uint64_t), number1->elements[i/2].elements[i%2]); + write_u64_be(num2+i*sizeof(uint64_t), number2->elements[i/2].elements[i%2]); + } + cx_math_mult(result, num1, num2, sizeof(num1)); + for(uint8_t i = 0; i<4; i++){ + read_u64_be(result+32+i*sizeof(uint64_t), &target->elements[i/2].elements[i%2]); } - - UPPER(fourth64) = 0; - LOWER(fourth64) = LOWER(products[0][3]); - UPPER(tmp) = 0; - LOWER(tmp) = LOWER(products[0][2]); - UPPER(tmp2) = 0; - LOWER(tmp2) = UPPER(products[0][3]); - add128(&tmp, &tmp2, &third64); - UPPER(tmp) = 0; - LOWER(tmp) = LOWER(products[0][1]); - UPPER(tmp2) = 0; - LOWER(tmp2) = UPPER(products[0][2]); - add128(&tmp, &tmp2, &second64); - UPPER(tmp) = 0; - LOWER(tmp) = LOWER(products[0][0]); - UPPER(tmp2) = 0; - LOWER(tmp2) = UPPER(products[0][1]); - add128(&tmp, &tmp2, &first64); - - UPPER(tmp) = 0; - LOWER(tmp) = LOWER(products[1][3]); - add128(&tmp, &third64, &tmp2); - copy128(&third64, &tmp2); - UPPER(tmp) = 0; - LOWER(tmp) = LOWER(products[1][2]); - add128(&tmp, &second64, &tmp2); - UPPER(tmp) = 0; - LOWER(tmp) = UPPER(products[1][3]); - add128(&tmp, &tmp2, &second64); - UPPER(tmp) = 0; - LOWER(tmp) = LOWER(products[1][1]); - add128(&tmp, &first64, &tmp2); - UPPER(tmp) = 0; - LOWER(tmp) = UPPER(products[1][2]); - add128(&tmp, &tmp2, &first64); - - UPPER(tmp) = 0; - LOWER(tmp) = LOWER(products[2][3]); - add128(&tmp, &second64, &tmp2); - copy128(&second64, &tmp2); - UPPER(tmp) = 0; - LOWER(tmp) = LOWER(products[2][2]); - add128(&tmp, &first64, &tmp2); - UPPER(tmp) = 0; - LOWER(tmp) = UPPER(products[2][3]); - add128(&tmp, &tmp2, &first64); - - UPPER(tmp) = 0; - LOWER(tmp) = LOWER(products[3][3]); - add128(&tmp, &first64, &tmp2); - copy128(&first64, &tmp2); - - clear256(&target1); - shiftl128(&first64, 64, &UPPER(target1)); - clear256(&target2); - UPPER(UPPER(target2)) = UPPER(third64); - shiftl128(&third64, 64, &LOWER(target2)); - add256(&target1, &target2, target); - clear256(&target1); - copy128(&UPPER(target1), &second64); - add256(&target1, target, &target2); - clear256(&target1); - copy128(&LOWER(target1), &fourth64); - add256(&target1, &target2, target); } void divmod128(uint128_t *l, uint128_t *r, uint128_t *retDiv, diff --git a/src_common/uint256.h b/src_common/uint256.h index 2db6832..db054ec 100644 --- a/src_common/uint256.h +++ b/src_common/uint256.h @@ -22,6 +22,8 @@ #include #include +#include "os.h" +#include "cx.h" typedef struct uint128_t { uint64_t elements[2]; } uint128_t; diff --git a/src_features/getPublicKey/cmd_getPublicKey.c b/src_features/getPublicKey/cmd_getPublicKey.c index d6e7497..91ee23d 100644 --- a/src_features/getPublicKey/cmd_getPublicKey.c +++ b/src_features/getPublicKey/cmd_getPublicKey.c @@ -40,7 +40,7 @@ void handleGetPublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t da os_memset(&privateKey, 0, sizeof(privateKey)); os_memset(privateKeyData, 0, sizeof(privateKeyData)); io_seproxyhal_io_heartbeat(); - getEthAddressStringFromKey(&tmpCtx.publicKeyContext.publicKey, tmpCtx.publicKeyContext.address, &sha3); + getEthAddressStringFromKey(&tmpCtx.publicKeyContext.publicKey, tmpCtx.publicKeyContext.address, &global_sha3, chainConfig); #ifndef NO_CONSENT if (p1 == P1_NON_CONFIRM) #endif // NO_CONSENT diff --git a/src_features/signMessage/cmd_signMessage.c b/src_features/signMessage/cmd_signMessage.c index 9440d9e..9e1d057 100644 --- a/src_features/signMessage/cmd_signMessage.c +++ b/src_features/signMessage/cmd_signMessage.c @@ -53,8 +53,8 @@ void handleSignPersonalMessage(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint workBuffer += 4; dataLength -= 4; // Initialize message header + length - cx_keccak_init(&sha3, 256); - cx_hash((cx_hash_t *)&sha3, 0, (uint8_t*)SIGN_MAGIC, sizeof(SIGN_MAGIC) - 1, NULL, 0); + cx_keccak_init(&global_sha3, 256); + cx_hash((cx_hash_t *)&global_sha3, 0, (uint8_t*)SIGN_MAGIC, sizeof(SIGN_MAGIC) - 1, NULL, 0); for (index = 1; (((index * base) <= tmpCtx.messageSigningContext.remainingLength) && (((index * base) / base) == index)); index *= base); @@ -62,7 +62,7 @@ void handleSignPersonalMessage(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint tmp[pos++] = '0' + ((tmpCtx.messageSigningContext.remainingLength / index) % base); } tmp[pos] = '\0'; - cx_hash((cx_hash_t *)&sha3, 0, (uint8_t*)tmp, pos, NULL, 0); + cx_hash((cx_hash_t *)&global_sha3, 0, (uint8_t*)tmp, pos, NULL, 0); cx_sha256_init(&tmpContent.sha2); } else if (p1 != P1_MORE) { @@ -78,11 +78,11 @@ void handleSignPersonalMessage(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint if (dataLength > tmpCtx.messageSigningContext.remainingLength) { THROW(0x6A80); } - cx_hash((cx_hash_t *)&sha3, 0, workBuffer, dataLength, NULL, 0); + cx_hash((cx_hash_t *)&global_sha3, 0, workBuffer, dataLength, NULL, 0); cx_hash((cx_hash_t *)&tmpContent.sha2, 0, workBuffer, dataLength, NULL, 0); tmpCtx.messageSigningContext.remainingLength -= dataLength; if (tmpCtx.messageSigningContext.remainingLength == 0) { - cx_hash((cx_hash_t *)&sha3, CX_LAST, workBuffer, 0, tmpCtx.messageSigningContext.hash, 32); + cx_hash((cx_hash_t *)&global_sha3, CX_LAST, workBuffer, 0, tmpCtx.messageSigningContext.hash, 32); cx_hash((cx_hash_t *)&tmpContent.sha2, CX_LAST, workBuffer, 0, hashMessage, 32); snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "%.*H", sizeof(hashMessage), hashMessage); diff --git a/src_features/signTx/cmd_signTx.c b/src_features/signTx/cmd_signTx.c index ee685b5..d1e4898 100644 --- a/src_features/signTx/cmd_signTx.c +++ b/src_features/signTx/cmd_signTx.c @@ -40,7 +40,7 @@ void handleSign(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength } dataPresent = false; contractProvisioned = CONTRACT_NONE; - initTx(&txContext, &sha3, &tmpContent.txContent, customProcessor, NULL); + initTx(&txContext, &global_sha3, &tmpContent.txContent, customProcessor, NULL); } else if (p1 != P1_MORE) { diff --git a/src_features/signTx/logic_signTx.c b/src_features/signTx/logic_signTx.c index e2899b9..5ab17e9 100644 --- a/src_features/signTx/logic_signTx.c +++ b/src_features/signTx/logic_signTx.c @@ -17,6 +17,8 @@ static const uint8_t const TOKEN_TRANSFER_ID[] = { 0xa9, 0x05, 0x9c, 0xbb }; #define ALLOWANCE_DATA_SIZE 4 + 32 + 32 static const uint8_t const ALLOWANCE_ID[] = { 0x09, 0x5e, 0xa7, 0xb3 }; +#define ERR_SILENT_MODE_CHECK_FAILED 0x6001 + #ifdef HAVE_STARKWARE #define STARKWARE_REGISTER_DATA_SIZE 4 + 32 @@ -130,7 +132,7 @@ customStatus_e customProcessor(txContext_t *context) { } else if ((context->currentFieldLength == STARKWARE_ESCAPE_DATA_SIZE) && - (os_memcmp(context->workBuffer, STARKWARE_ESCAPE_ID, 4) == 0) && + (os_memcmp(context->workBuffer, STARKWARE_ESCAPE_ID, 4) == 0) && quantumSet) { contractProvisioned = CONTRACT_STARKWARE_ESCAPE; } @@ -143,11 +145,11 @@ customStatus_e customProcessor(txContext_t *context) { } // Sanity check // Also handle exception that only need to process the beginning of the data - if ((contractProvisioned != CONTRACT_NONE) && -#ifdef HAVE_STARKWARE + if ((contractProvisioned != CONTRACT_NONE) && +#ifdef HAVE_STARKWARE (contractProvisioned != CONTRACT_STARKWARE_VERIFY_ESCAPE) && (contractProvisioned != CONTRACT_STARKWARE_REGISTER) && -#endif +#endif (context->currentFieldLength > sizeof(dataContext.tokenContext.data))) { PRINTF("Data field overflow - dropping customization\n"); contractProvisioned = CONTRACT_NONE; @@ -155,7 +157,7 @@ customStatus_e customProcessor(txContext_t *context) { PRINTF("contractProvisioned %d\n", contractProvisioned); if (contractProvisioned != CONTRACT_NONE) { if (context->currentFieldPos < context->currentFieldLength) { - uint32_t copySize = MIN(context->commandLength, + uint32_t copySize = MIN(context->commandLength, context->currentFieldLength - context->currentFieldPos); // Handle the case where we only need to handle the beginning of the data parameter if ((context->currentFieldPos + copySize) < sizeof(dataContext.tokenContext.data)) { @@ -262,10 +264,21 @@ customStatus_e customProcessor(txContext_t *context) { return CUSTOM_NOT_HANDLED; } +void compareOrCopy(char* preapproved_string, char* parsed_string, bool silent_mode){ + if(silent_mode){ + if(os_memcmp(preapproved_string, parsed_string, strlen(preapproved_string))){ + THROW(ERR_SILENT_MODE_CHECK_FAILED); + } + } + else{ + strcpy(preapproved_string, parsed_string); + } +} + void finalizeParsing(bool direct) { uint256_t gasPrice, startGas, uint256; uint32_t i; - uint8_t address[41]; + char displayBuffer[50]; uint8_t decimals = WEI_TO_ETHER; uint8_t *ticker = (uint8_t *)PIC(chainConfig->coinName); uint8_t *feeTicker = (uint8_t *)PIC(chainConfig->coinName); @@ -288,7 +301,7 @@ void finalizeParsing(bool direct) { } } // Store the hash - cx_hash((cx_hash_t *)&sha3, CX_LAST, tmpCtx.transactionContext.hash, 0, tmpCtx.transactionContext.hash, 32); + cx_hash((cx_hash_t *)&global_sha3, CX_LAST, tmpCtx.transactionContext.hash, 0, tmpCtx.transactionContext.hash, 32); #ifdef HAVE_STARKWARE if ((contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_ETH) || (contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_TOKEN) || @@ -301,7 +314,7 @@ void finalizeParsing(bool direct) { if (dataContext.tokenContext.quantumIndex != MAX_TOKEN) { currentToken = &tmpCtx.transactionContext.tokens[dataContext.tokenContext.quantumIndex]; } - compute_token_id(&sha3, + compute_token_id(&global_sha3, (currentToken != NULL ? currentToken->address : NULL), dataContext.tokenContext.quantum, G_io_apdu_buffer + 100); if (os_memcmp(dataContext.tokenContext.data + tokenIdOffset, G_io_apdu_buffer + 100, 32) != 0) { @@ -346,20 +359,10 @@ void finalizeParsing(bool direct) { } // Add address if (tmpContent.txContent.destinationLength != 0) { - getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &sha3); - /* - addressSummary[0] = '0'; - addressSummary[1] = 'x'; - os_memmove((unsigned char *)(addressSummary + 2), address, 4); - os_memmove((unsigned char *)(addressSummary + 6), "...", 3); - os_memmove((unsigned char *)(addressSummary + 9), address + 40 - 4, 4); - addressSummary[13] = '\0'; - */ - - strings.common.fullAddress[0] = '0'; - strings.common.fullAddress[1] = 'x'; - os_memmove((unsigned char *)strings.common.fullAddress+2, address, 40); - strings.common.fullAddress[42] = '\0'; + displayBuffer[0] = '0'; + displayBuffer[1] = 'x'; + getEthAddressStringFromBinary(tmpContent.txContent.destination, (uint8_t*)displayBuffer+2, &global_sha3, chainConfig); + compareOrCopy(strings.common.fullAddress, displayBuffer, called_from_swap); } else { @@ -372,28 +375,18 @@ void finalizeParsing(bool direct) { (contractProvisioned == CONTRACT_ALLOWANCE)) { // Add amount in ethers or tokens if ((contractProvisioned == CONTRACT_ALLOWANCE) && ismaxint(tmpContent.txContent.value.value, 32)) { - strcpy((char*)G_io_apdu_buffer, "Unlimited"); + i = 0; + tickerOffset = 0; + while (ticker[tickerOffset]) { + displayBuffer[tickerOffset] = ticker[tickerOffset]; + tickerOffset++; + } + strcpy(displayBuffer + tickerOffset, "Unlimited"); } else { - convertUint256BE(tmpContent.txContent.value.value, tmpContent.txContent.value.length, &uint256); - tostring256(&uint256, 10, (char *)(G_io_apdu_buffer + 100), 100); - i = 0; - while (G_io_apdu_buffer[100 + i]) { - i++; - } - adjustDecimals((char *)(G_io_apdu_buffer + 100), i, (char *)G_io_apdu_buffer, 100, decimals); + amountToString(tmpContent.txContent.value.value, tmpContent.txContent.value.length, decimals, (char*)ticker, displayBuffer, sizeof(displayBuffer)); } - i = 0; - tickerOffset = 0; - while (ticker[tickerOffset]) { - strings.common.fullAmount[tickerOffset] = ticker[tickerOffset]; - tickerOffset++; - } - while (G_io_apdu_buffer[i]) { - strings.common.fullAmount[tickerOffset + i] = G_io_apdu_buffer[i]; - i++; - } - strings.common.fullAmount[tickerOffset + i] = '\0'; + compareOrCopy(strings.common.fullAmount, displayBuffer, called_from_swap); } // Compute maximum fee PRINTF("Max fee\n"); @@ -410,75 +403,86 @@ void finalizeParsing(bool direct) { adjustDecimals((char *)(G_io_apdu_buffer + 100), i, (char *)G_io_apdu_buffer, 100, WEI_TO_ETHER); i = 0; tickerOffset=0; + memset(displayBuffer, 0, sizeof(displayBuffer)); while (feeTicker[tickerOffset]) { - strings.common.maxFee[tickerOffset] = feeTicker[tickerOffset]; + displayBuffer[tickerOffset] = feeTicker[tickerOffset]; tickerOffset++; } - tickerOffset++; while (G_io_apdu_buffer[i]) { - strings.common.maxFee[tickerOffset + i] = G_io_apdu_buffer[i]; + displayBuffer[tickerOffset + i] = G_io_apdu_buffer[i]; i++; } - strings.common.maxFee[tickerOffset + i] = '\0'; + displayBuffer[tickerOffset + i] = '\0'; + compareOrCopy(strings.common.maxFee, displayBuffer, called_from_swap); + + bool no_consent = false; + + no_consent = called_from_swap; #ifdef NO_CONSENT - io_seproxyhal_touch_tx_ok(NULL); -#else // NO_CONSENT + no_consent = true; +#endif // NO_CONSENT + + if(no_consent){ + io_seproxyhal_touch_tx_ok(NULL); + } + else{ #if defined(TARGET_BLUE) - ui_approval_transaction_blue_init(); + ui_approval_transaction_blue_init(); #else #ifdef HAVE_STARKWARE - if (contractProvisioned == CONTRACT_STARKWARE_REGISTER) { - ux_flow_init(0, ux_approval_starkware_register_flow, NULL); - return; - } - else - if (contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_TOKEN) { - ux_flow_init(0, ux_approval_starkware_deposit_flow, NULL); - return; - } - else - if (contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_ETH) { - ux_flow_init(0, ux_approval_starkware_deposit_flow, NULL); - return; - } - else - if ((contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_CANCEL) || - (contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_RECLAIM) || - (contractProvisioned == CONTRACT_STARKWARE_FULL_WITHDRAWAL) || - (contractProvisioned == CONTRACT_STARKWARE_FREEZE)) { - ux_flow_init(0, ux_approval_starkware_verify_vault_id_flow, NULL); - return; - } - else - if (contractProvisioned == CONTRACT_STARKWARE_WITHDRAW) { - ux_flow_init(0, ux_approval_starkware_withdraw_flow, NULL); - return; - } - else - if (contractProvisioned == CONTRACT_STARKWARE_ESCAPE) { - ux_flow_init(0, ux_approval_starkware_escape_flow, NULL); - return; - } - else - if (contractProvisioned == CONTRACT_STARKWARE_VERIFY_ESCAPE) { - ux_flow_init(0, ux_approval_starkware_verify_escape_flow, NULL); - return; - } + if (contractProvisioned == CONTRACT_STARKWARE_REGISTER) { + ux_flow_init(0, ux_approval_starkware_register_flow, NULL); + return; + } + else + if (contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_TOKEN) { + ux_flow_init(0, ux_approval_starkware_deposit_flow, NULL); + return; + } + else + if (contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_ETH) { + ux_flow_init(0, ux_approval_starkware_deposit_flow, NULL); + return; + } + else + if ((contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_CANCEL) || + (contractProvisioned == CONTRACT_STARKWARE_DEPOSIT_RECLAIM) || + (contractProvisioned == CONTRACT_STARKWARE_FULL_WITHDRAWAL) || + (contractProvisioned == CONTRACT_STARKWARE_FREEZE)) { + ux_flow_init(0, ux_approval_starkware_verify_vault_id_flow, NULL); + return; + } + else + if (contractProvisioned == CONTRACT_STARKWARE_WITHDRAW) { + ux_flow_init(0, ux_approval_starkware_withdraw_flow, NULL); + return; + } + else + if (contractProvisioned == CONTRACT_STARKWARE_ESCAPE) { + ux_flow_init(0, ux_approval_starkware_escape_flow, NULL); + return; + } + else + if (contractProvisioned == CONTRACT_STARKWARE_VERIFY_ESCAPE) { + ux_flow_init(0, ux_approval_starkware_verify_escape_flow, NULL); + return; + } #endif - if (contractProvisioned == CONTRACT_ALLOWANCE) { - ux_flow_init(0, ux_approval_allowance_flow, NULL); - return; + if (contractProvisioned == CONTRACT_ALLOWANCE) { + ux_flow_init(0, ux_approval_allowance_flow, NULL); + return; + } + + ux_flow_init(0, + ((dataPresent && !N_storage.contractDetails) ? ux_approval_tx_data_warning_flow : ux_approval_tx_flow), + NULL); +#endif // #if TARGET_ID } - ux_flow_init(0, - ((dataPresent && !N_storage.contractDetails) ? ux_approval_tx_data_warning_flow : ux_approval_tx_flow), - NULL); -#endif // #if TARGET_ID -#endif // NO_CONSENT } diff --git a/src_features/signTx/ui_common_signTx.c b/src_features/signTx/ui_common_signTx.c index 9218e4c..102de66 100644 --- a/src_features/signTx/ui_common_signTx.c +++ b/src_features/signTx/ui_common_signTx.c @@ -43,9 +43,12 @@ unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e) { tx = 65; G_io_apdu_buffer[tx++] = 0x90; G_io_apdu_buffer[tx++] = 0x00; - reset_app_context(); // Send back the response, do not restart the event loop io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx); + if(called_from_swap){ + os_sched_exit(0); + } + reset_app_context(); // Display back the original UX ui_idle(); return 0; // do not redraw the widget diff --git a/src_features/stark_contract_deposit/ui_flow_stark_deposit.c b/src_features/stark_contract_deposit/ui_flow_stark_deposit.c index 7fb646b..49f52db 100644 --- a/src_features/stark_contract_deposit/ui_flow_stark_deposit.c +++ b/src_features/stark_contract_deposit/ui_flow_stark_deposit.c @@ -6,7 +6,7 @@ void prepare_deposit_3() { uint8_t address[41]; - getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &sha3); + getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &global_sha3, chainConfig); strings.common.fullAddress[0] = '0'; strings.common.fullAddress[1] = 'x'; os_memmove((unsigned char *)strings.common.fullAddress+2, address, 40); diff --git a/src_features/stark_contract_escape/ui_flow_stark_escape.c b/src_features/stark_contract_escape/ui_flow_stark_escape.c index 409a355..9e55ef6 100644 --- a/src_features/stark_contract_escape/ui_flow_stark_escape.c +++ b/src_features/stark_contract_escape/ui_flow_stark_escape.c @@ -5,7 +5,7 @@ void prepare_escape_3() { uint8_t address[41]; - getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &sha3); + getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &global_sha3, chainConfig); strings.common.fullAddress[0] = '0'; strings.common.fullAddress[1] = 'x'; os_memmove((unsigned char *)strings.common.fullAddress+2, address, 40); diff --git a/src_features/stark_contract_register/ui_flow_stark_register.c b/src_features/stark_contract_register/ui_flow_stark_register.c index e3ac50e..efa8d6b 100644 --- a/src_features/stark_contract_register/ui_flow_stark_register.c +++ b/src_features/stark_contract_register/ui_flow_stark_register.c @@ -5,7 +5,7 @@ void prepare_register_3() { uint8_t address[41]; - getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &sha3); + getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &global_sha3, chainConfig); strings.common.fullAddress[0] = '0'; strings.common.fullAddress[1] = 'x'; os_memmove((unsigned char *)strings.common.fullAddress+2, address, 40); @@ -26,7 +26,7 @@ void prepare_register_4() { os_memset(&privateKey, 0, sizeof(privateKey)); os_memset(privateKeyData, 0, sizeof(privateKeyData)); io_seproxyhal_io_heartbeat(); - getEthAddressStringFromKey(&publicKey, address, &sha3); + getEthAddressStringFromKey(&publicKey, address, &global_sha3, chainConfig); strings.common.fullAddress[0] = '0'; strings.common.fullAddress[1] = 'x'; os_memmove((unsigned char *)strings.common.fullAddress+2, address, 40); diff --git a/src_features/stark_contract_verifyEscape/ui_flow_stark_verify_escape.c b/src_features/stark_contract_verifyEscape/ui_flow_stark_verify_escape.c index 0af588c..3be2be3 100644 --- a/src_features/stark_contract_verifyEscape/ui_flow_stark_verify_escape.c +++ b/src_features/stark_contract_verifyEscape/ui_flow_stark_verify_escape.c @@ -5,7 +5,7 @@ void prepare_verify_escape_3() { uint8_t address[41]; - getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &sha3); + getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &global_sha3, chainConfig); strings.common.fullAddress[0] = '0'; strings.common.fullAddress[1] = 'x'; os_memmove((unsigned char *)strings.common.fullAddress+2, address, 40); diff --git a/src_features/stark_contract_verifyVaultId/ui_flow_stark_verifyVaultId.c b/src_features/stark_contract_verifyVaultId/ui_flow_stark_verifyVaultId.c index 47870bf..ca9e289 100644 --- a/src_features/stark_contract_verifyVaultId/ui_flow_stark_verifyVaultId.c +++ b/src_features/stark_contract_verifyVaultId/ui_flow_stark_verifyVaultId.c @@ -23,7 +23,7 @@ void prepare_verify_vault_id_2() { void prepare_verify_vault_id_3() { uint8_t address[41]; - getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &sha3); + getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &global_sha3, chainConfig); strings.common.fullAddress[0] = '0'; strings.common.fullAddress[1] = 'x'; os_memmove((unsigned char *)strings.common.fullAddress+2, address, 40); diff --git a/src_features/stark_contract_withdrawal/ui_flow_stark_withdrawal.c b/src_features/stark_contract_withdrawal/ui_flow_stark_withdrawal.c index 4043638..b2e61c6 100644 --- a/src_features/stark_contract_withdrawal/ui_flow_stark_withdrawal.c +++ b/src_features/stark_contract_withdrawal/ui_flow_stark_withdrawal.c @@ -7,7 +7,7 @@ void prepare_register_4(); void prepare_withdraw_3() { uint8_t address[41]; - getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &sha3); + getEthAddressStringFromBinary(tmpContent.txContent.destination, address, &global_sha3, chainConfig); strings.common.fullAddress[0] = '0'; strings.common.fullAddress[1] = 'x'; os_memmove((unsigned char *)strings.common.fullAddress+2, address, 40); diff --git a/src_features/stark_sign/cmd_stark_sign.c b/src_features/stark_sign/cmd_stark_sign.c index 32734ef..f4855e9 100644 --- a/src_features/stark_sign/cmd_stark_sign.c +++ b/src_features/stark_sign/cmd_stark_sign.c @@ -68,10 +68,10 @@ void handleStarkwareSignMessage(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uin } // Prepare the Stark parameters io_seproxyhal_io_heartbeat(); - compute_token_id(&sha3, dataBuffer, dataBuffer + 20, dataContext.starkContext.w1); + compute_token_id(&global_sha3, dataBuffer, dataBuffer + 20, dataContext.starkContext.w1); if (p1 == P1_STARK_ORDER) { io_seproxyhal_io_heartbeat(); - compute_token_id(&sha3, dataBuffer + 20 + 32, dataBuffer + 20 + 32 + 20, dataContext.starkContext.w2); + compute_token_id(&global_sha3, dataBuffer + 20 + 32, dataBuffer + 20 + 32 + 20, dataContext.starkContext.w2); offset = 20 + 32 + 20 + 32; } else { From ac202a4a25e4ddd5d26f35f75ae6da72a6e1d529 Mon Sep 17 00:00:00 2001 From: TamtamHero <10632523+TamtamHero@users.noreply.github.com> Date: Mon, 6 Jul 2020 14:30:38 +0200 Subject: [PATCH 2/5] Fix case sensitivity issue for silent mode --- Makefile | 5 +++++ src_features/signTx/logic_signTx.c | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/Makefile b/Makefile index b3800a5..a0bb021 100755 --- a/Makefile +++ b/Makefile @@ -29,8 +29,13 @@ APP_LOAD_PARAMS += --path "45'" #APP_LOAD_PARAMS += --path "1517992542'/1101353413'" APPVERSION_M=1 +<<<<<<< HEAD APPVERSION_N=3 APPVERSION_P=7 +======= +APPVERSION_N=4 +APPVERSION_P=2 +>>>>>>> f9ebc6d... Fix case sensitivity issue for silent mode + bump version 1.4.2 APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) APP_LOAD_FLAGS= --appFlags 0x240 --dep Ethereum:$(APPVERSION) diff --git a/src_features/signTx/logic_signTx.c b/src_features/signTx/logic_signTx.c index 5ab17e9..2dcf9ba 100644 --- a/src_features/signTx/logic_signTx.c +++ b/src_features/signTx/logic_signTx.c @@ -264,8 +264,19 @@ customStatus_e customProcessor(txContext_t *context) { return CUSTOM_NOT_HANDLED; } +void to_uppercase(char* str, unsigned char size){ + for (unsigned char i = 0; i < size && str[i] != 0; i++) + { + str[i] = str[i] > 'a' ? str[i] - ('a' - 'A') : str[i]; + } +} + void compareOrCopy(char* preapproved_string, char* parsed_string, bool silent_mode){ if(silent_mode){ + /* ETH address are not fundamentally case sensitive but might + have some for checksum purpose, so let's get rid of these diffs */ + to_uppercase(preapproved_string, strlen(preapproved_string)); + to_uppercase(parsed_string, strlen(parsed_string)); if(os_memcmp(preapproved_string, parsed_string, strlen(preapproved_string))){ THROW(ERR_SILENT_MODE_CHECK_FAILED); } From c2e3d753284e982e7229e7d7bee0128c66ae5534 Mon Sep 17 00:00:00 2001 From: TamtamHero <10632523+TamtamHero@users.noreply.github.com> Date: Tue, 7 Jul 2020 23:54:18 +0200 Subject: [PATCH 3/5] Fix broken error reporting --- Makefile | 5 ----- src_features/signTx/cmd_signTx.c | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index a0bb021..b3800a5 100755 --- a/Makefile +++ b/Makefile @@ -29,13 +29,8 @@ APP_LOAD_PARAMS += --path "45'" #APP_LOAD_PARAMS += --path "1517992542'/1101353413'" APPVERSION_M=1 -<<<<<<< HEAD APPVERSION_N=3 APPVERSION_P=7 -======= -APPVERSION_N=4 -APPVERSION_P=2 ->>>>>>> f9ebc6d... Fix case sensitivity issue for silent mode + bump version 1.4.2 APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) APP_LOAD_FLAGS= --appFlags 0x240 --dep Ethereum:$(APPVERSION) diff --git a/src_features/signTx/cmd_signTx.c b/src_features/signTx/cmd_signTx.c index d1e4898..990929a 100644 --- a/src_features/signTx/cmd_signTx.c +++ b/src_features/signTx/cmd_signTx.c @@ -72,10 +72,10 @@ void handleSign(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength THROW(0x6A80); } - *flags |= IO_ASYNCH_REPLY; - if (txResult == USTREAM_FINISHED) { finalizeParsing(false); } + + *flags |= IO_ASYNCH_REPLY; } From 94b501b8b28bd28b8060bec4b85321dad3323bd0 Mon Sep 17 00:00:00 2001 From: TamtamHero <10632523+TamtamHero@users.noreply.github.com> Date: Thu, 9 Jul 2020 15:56:52 +0200 Subject: [PATCH 4/5] Fix uppercasing function + swap flag issue --- src_features/getPublicKey/cmd_getPublicKey.c | 4 +++- src_features/signTx/logic_signTx.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src_features/getPublicKey/cmd_getPublicKey.c b/src_features/getPublicKey/cmd_getPublicKey.c index 91ee23d..96a02f7 100644 --- a/src_features/getPublicKey/cmd_getPublicKey.c +++ b/src_features/getPublicKey/cmd_getPublicKey.c @@ -15,7 +15,9 @@ void handleGetPublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t da uint32_t i; uint8_t bip32PathLength = *(dataBuffer++); cx_ecfp_private_key_t privateKey; - reset_app_context(); + if(!called_from_swap){ + reset_app_context(); + } if ((bip32PathLength < 0x01) || (bip32PathLength > MAX_BIP32_PATH)) { PRINTF("Invalid path\n"); diff --git a/src_features/signTx/logic_signTx.c b/src_features/signTx/logic_signTx.c index 2dcf9ba..73bdb68 100644 --- a/src_features/signTx/logic_signTx.c +++ b/src_features/signTx/logic_signTx.c @@ -267,7 +267,7 @@ customStatus_e customProcessor(txContext_t *context) { void to_uppercase(char* str, unsigned char size){ for (unsigned char i = 0; i < size && str[i] != 0; i++) { - str[i] = str[i] > 'a' ? str[i] - ('a' - 'A') : str[i]; + str[i] = str[i] >= 'a' ? str[i] - ('a' - 'A') : str[i]; } } From 95168fd5ab949626d8e18bbd9a6f2a2fcf47569c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Colas?= Date: Wed, 12 Aug 2020 16:57:18 +0200 Subject: [PATCH 5/5] Fix bad check of fee_amount_length --- src/handle_swap_sign_transaction.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/handle_swap_sign_transaction.c b/src/handle_swap_sign_transaction.c index cd24f2e..a8b873c 100644 --- a/src/handle_swap_sign_transaction.c +++ b/src/handle_swap_sign_transaction.c @@ -12,7 +12,7 @@ void copy_transaction_parameters(create_transaction_parameters_t* sign_transacti memset(&stack_data, 0, sizeof(stack_data)); strncpy(stack_data.fullAddress, sign_transaction_params->destination_address, sizeof(stack_data.fullAddress)); if ((stack_data.fullAddress[sizeof(stack_data.fullAddress) - 1] != '\0') || - (sign_transaction_params->amount_length > 8) || + (sign_transaction_params->amount_length > 32) || (sign_transaction_params->fee_amount_length > 8)) { os_lib_end(); }