diff --git a/Makefile b/Makefile index 60e30bd..a261ce5 100755 --- a/Makefile +++ b/Makefile @@ -46,9 +46,11 @@ DEFINES += CHAINID_UPCASE=\"ETHEREUM\" CHAINID_COINNAME=\"ETH\" CHAIN_KIND=CHAIN APP_LOAD_PARAMS += --path "2645'/579218131'" DEFINES += HAVE_STARKWARE DEFINES += STARK_BIP32_PATH_0=0x80000A55 STARK_BIP32_PATH_1=0xA2862AD3 +ifeq ($(TARGET_NAME), TARGET_NANOX) # Allow to derive ETH 2 public keys APP_LOAD_PARAMS += --path "12381/3600" --curve bls12381g1 DEFINES += HAVE_ETH2 +endif APPNAME = "Ethereum" DEFINES_LIB= APP_LOAD_FLAGS=--appFlags 0xa40 @@ -61,9 +63,11 @@ DEFINES += HAVE_STARKWARE # Keep for Starkware Ropsten tests DEFINES += HAVE_TOKENS_EXTRA_LIST DEFINES += STARK_BIP32_PATH_0=0x80000A55 STARK_BIP32_PATH_1=0xA2862AD3 +ifeq ($(TARGET_NAME), TARGET_NANOX) # Allow to derive ETH 2 public keys APP_LOAD_PARAMS += --path "12381/3600" --curve bls12381g1 DEFINES += HAVE_ETH2 +endif APPNAME = "Eth Ropsten" DEFINES_LIB= APP_LOAD_FLAGS=--appFlags 0xa40 diff --git a/doc/eth_contract_support_embedded.asc b/doc/eth_contract_support_embedded.asc index 4302dad..67c27c0 100644 --- a/doc/eth_contract_support_embedded.asc +++ b/doc/eth_contract_support_embedded.asc @@ -72,7 +72,7 @@ CONTRACT_STARKWARE_DEPOSIT_TOKEN ```C if ((context->currentFieldLength == STARKWARE_DEPOSIT_TOKEN_DATA_SIZE) && - (os_memcmp(context->workBuffer, STARKWARE_DEPOSIT_TOKEN_ID, 4) == 0) && + (memcmp(context->workBuffer, STARKWARE_DEPOSIT_TOKEN_ID, 4) == 0) && quantumSet) { contractProvisioned = CONTRACT_STARKWARE_DEPOSIT_TOKEN; } diff --git a/doc/ethapp.asc b/doc/ethapp.asc index 878223c..d57e13c 100644 --- a/doc/ethapp.asc +++ b/doc/ethapp.asc @@ -322,7 +322,7 @@ This command has been supported since firmware version 1.5.0 This command returns an Ethereum 2 BLS12-381 public key derived following EIP 2333 specification (https://eips.ethereum.org/EIPS/eip-2333) -This command has been supported since firmware version 1.5.0 +This command has been supported since firmware version 1.6.0 #### Coding diff --git a/src/apdu_constants.h b/src/apdu_constants.h index ee8b784..78e9f6e 100644 --- a/src/apdu_constants.h +++ b/src/apdu_constants.h @@ -3,6 +3,7 @@ #define APP_FLAG_DATA_ALLOWED 0x01 #define APP_FLAG_EXTERNAL_TOKEN_NEEDED 0x02 #define APP_FLAG_STARKWARE 0x04 +#define APP_FLAG_STARKWARE_V2 0x08 #define CLA 0xE0 #define INS_GET_PUBLIC_KEY 0x02 @@ -29,12 +30,17 @@ #define STARKWARE_INS_GET_PUBLIC_KEY 0x02 #define STARKWARE_INS_SIGN_MESSAGE 0x04 #define STARKWARE_INS_PROVIDE_QUANTUM 0x08 +#define STARKWARE_INS_UNSAFE_SIGN 0x0A #define P1_STARK_ORDER 0x01 #define P1_STARK_TRANSFER 0x02 +#define P1_STARK_ORDER_V2 0x03 +#define P1_STARK_TRANSFER_V2 0x04 +#define P1_STARK_CONDITIONAL_TRANSFER 0x05 #define STARK_ORDER_TYPE 0 #define STARK_TRANSFER_TYPE 1 +#define STARK_CONDITIONAL_TRANSFER_TYPE 2 #endif @@ -64,6 +70,7 @@ void handleSetEth2WinthdrawalIndex(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, void handleStarkwareGetPublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx); void handleStarkwareSignMessage(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx); void handleStarkwareProvideQuantum(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx); +void handleStarkwareUnsafeSign(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx); #endif diff --git a/src/eth_plugin_handler.c b/src/eth_plugin_handler.c index 1d40487..4b98ebc 100644 --- a/src/eth_plugin_handler.c +++ b/src/eth_plugin_handler.c @@ -57,10 +57,13 @@ int eth_plugin_perform_init(uint8_t *contractAddress, ethPluginInitContract_t *i } for (j=0; ((jselector, PIC(selectors[j]), SELECTOR_SIZE) == 0) { - strcpy(dataContext.tokenContext.pluginName, INTERNAL_ETH_PLUGINS[i].alias); - dataContext.tokenContext.pluginAvailable = 1; - contractAddress = NULL; - break; + if ((INTERNAL_ETH_PLUGINS[i].availableCheck == NULL) || + ((PluginAvailableCheck)PIC(INTERNAL_ETH_PLUGINS[i].availableCheck))()) { + strcpy(dataContext.tokenContext.pluginName, INTERNAL_ETH_PLUGINS[i].alias); + dataContext.tokenContext.pluginAvailable = 1; + contractAddress = NULL; + break; + } } } } diff --git a/src/eth_plugin_internal.c b/src/eth_plugin_internal.c index 4108c75..5be1fb3 100644 --- a/src/eth_plugin_internal.c +++ b/src/eth_plugin_internal.c @@ -1,6 +1,10 @@ #include "eth_plugin_internal.h" +bool erc20_plugin_available_check(void); +bool erc721_plugin_available_check(void); + void erc20_plugin_call(int message, void *parameters); +void erc721_plugin_call(int message, void *parameters); void compound_plugin_call(int message, void *parameters); #ifdef HAVE_STARKWARE void starkware_plugin_call(int message, void *parameters); @@ -16,6 +20,13 @@ const uint8_t* const ERC20_SELECTORS[NUM_ERC20_SELECTORS] = { ERC20_TRANSFER_SELECTOR, ERC20_APPROVE_SELECTOR }; + +static const uint8_t const ERC721_APPROVE_SELECTOR[SELECTOR_SIZE] = { 0x09, 0x5e, 0xa7, 0xb3 }; + +const uint8_t* const ERC721_SELECTORS[NUM_ERC721_SELECTORS] = { + ERC721_APPROVE_SELECTOR +}; + static const uint8_t const COMPOUND_REDEEM_UNDERLYING_SELECTOR[SELECTOR_SIZE] = { 0x85, 0x2a, 0x12, 0xe3 }; static const uint8_t const COMPOUND_REDEEM_SELECTOR[SELECTOR_SIZE] = { 0xdb, 0x00, 0x6a, 0x75 }; static const uint8_t const COMPOUND_MINT_SELECTOR[SELECTOR_SIZE] = { 0xa0, 0x71, 0x2d, 0x68 }; @@ -38,22 +49,32 @@ const uint8_t* const ETH2_SELECTORS[NUM_ETH2_SELECTORS] = { #ifdef HAVE_STARKWARE -static const uint8_t const STARKWARE_REGISTER_ID[SELECTOR_SIZE] = { 0x76, 0x57, 0x18, 0xd7 }; -static const uint8_t const STARKWARE_DEPOSIT_TOKEN_ID[SELECTOR_SIZE] = { 0x00, 0xae, 0xef, 0x8a }; -static const uint8_t const STARKWARE_DEPOSIT_ETH_ID[SELECTOR_SIZE] = { 0xe2, 0xbb, 0xb1, 0x58 }; -static const uint8_t const STARKWARE_DEPOSIT_CANCEL_ID[SELECTOR_SIZE] = { 0xc7, 0xfb, 0x11, 0x7c }; -static const uint8_t const STARKWARE_DEPOSIT_RECLAIM_ID[SELECTOR_SIZE] = { 0x4e, 0xab, 0x38, 0xf4 }; -static const uint8_t const STARKWARE_WITHDRAW_ID[SELECTOR_SIZE] = { 0x2e, 0x1a, 0x7d, 0x4d }; -static const uint8_t const STARKWARE_FULL_WITHDRAWAL_ID[SELECTOR_SIZE] = { 0x27, 0x6d, 0xd1, 0xde }; -static const uint8_t const STARKWARE_FREEZE_ID[SELECTOR_SIZE] = { 0xb9, 0x10, 0x72, 0x09 }; +static const uint8_t const STARKWARE_REGISTER_ID[SELECTOR_SIZE] = { 0xdd, 0x24, 0x14, 0xd4 }; +static const uint8_t const STARKWARE_DEPOSIT_TOKEN_ID[SELECTOR_SIZE] = { 0x25, 0x05, 0xc3, 0xd9 }; +static const uint8_t const STARKWARE_DEPOSIT_ETH_ID[SELECTOR_SIZE] = { 0x00, 0xae, 0xef, 0x8a }; +static const uint8_t const STARKWARE_DEPOSIT_CANCEL_ID[SELECTOR_SIZE] = { 0x7d, 0xf7, 0xdc, 0x04 }; +static const uint8_t const STARKWARE_DEPOSIT_RECLAIM_ID[SELECTOR_SIZE] = { 0xae, 0x87, 0x38, 0x16 }; +static const uint8_t const STARKWARE_WITHDRAW_ID[SELECTOR_SIZE] = { 0x44, 0x1a, 0x3e, 0x70 }; +static const uint8_t const STARKWARE_FULL_WITHDRAWAL_ID[SELECTOR_SIZE] = { 0xa9, 0x33, 0x10, 0xc4 }; +static const uint8_t const STARKWARE_FREEZE_ID[SELECTOR_SIZE] = { 0x93, 0xc1, 0xe4, 0x66 }; static const uint8_t const STARKWARE_ESCAPE_ID[SELECTOR_SIZE] = { 0x9e, 0x3a, 0xda, 0xc4 }; static const uint8_t const STARKWARE_VERIFY_ESCAPE_ID[SELECTOR_SIZE] = { 0x2d, 0xd5, 0x30, 0x06 }; +static const uint8_t const STARKWARE_WITHDRAW_TO_ID[SELECTOR_SIZE] = { 0x14, 0xcd, 0x70, 0xe4 }; +static const uint8_t const STARKWARE_DEPOSIT_NFT_ID[SELECTOR_SIZE] = { 0xae, 0x1c, 0xdd, 0xe6 }; +static const uint8_t const STARKWARE_DEPOSIT_NFT_RECLAIM_ID[SELECTOR_SIZE] = { 0xfc, 0xb0, 0x58, 0x22 }; +static const uint8_t const STARKWARE_WITHDRAW_AND_MINT_ID[SELECTOR_SIZE] = { 0xd9, 0x14, 0x43, 0xb7 }; +static const uint8_t const STARKWARE_WITHDRAW_NFT_ID[SELECTOR_SIZE] = { 0x01, 0x9b, 0x41, 0x7a }; +static const uint8_t const STARKWARE_WITHDRAW_NFT_TO_ID[SELECTOR_SIZE] = { 0xeb, 0xef, 0x0f, 0xd0 }; + + const uint8_t* const STARKWARE_SELECTORS[NUM_STARKWARE_SELECTORS] = { STARKWARE_REGISTER_ID, STARKWARE_DEPOSIT_TOKEN_ID, STARKWARE_DEPOSIT_ETH_ID, STARKWARE_DEPOSIT_CANCEL_ID, STARKWARE_DEPOSIT_RECLAIM_ID, STARKWARE_WITHDRAW_ID, STARKWARE_FULL_WITHDRAWAL_ID, STARKWARE_FREEZE_ID, STARKWARE_ESCAPE_ID, - STARKWARE_VERIFY_ESCAPE_ID + STARKWARE_VERIFY_ESCAPE_ID, STARKWARE_WITHDRAW_TO_ID, STARKWARE_DEPOSIT_NFT_ID, + STARKWARE_DEPOSIT_NFT_RECLAIM_ID, STARKWARE_WITHDRAW_AND_MINT_ID, STARKWARE_WITHDRAW_NFT_ID, + STARKWARE_WITHDRAW_NFT_TO_ID }; #endif @@ -62,6 +83,7 @@ const uint8_t* const STARKWARE_SELECTORS[NUM_STARKWARE_SELECTORS] = { const internalEthPlugin_t const INTERNAL_ETH_PLUGINS[] = { { + erc20_plugin_available_check, ERC20_SELECTORS, NUM_ERC20_SELECTORS, "-erc20", @@ -69,6 +91,15 @@ const internalEthPlugin_t const INTERNAL_ETH_PLUGINS[] = { }, { + erc721_plugin_available_check, + ERC721_SELECTORS, + NUM_ERC721_SELECTORS, + "-er721", + erc721_plugin_call + }, + + { + NULL, COMPOUND_SELECTORS, NUM_COMPOUND_SELECTORS, "-cmpd", @@ -78,6 +109,7 @@ const internalEthPlugin_t const INTERNAL_ETH_PLUGINS[] = { #ifdef HAVE_ETH2 { + NULL, ETH2_SELECTORS, NUM_ETH2_SELECTORS, "-eth2", @@ -89,6 +121,7 @@ const internalEthPlugin_t const INTERNAL_ETH_PLUGINS[] = { #ifdef HAVE_STARKWARE { + NULL, STARKWARE_SELECTORS, 10, "-strk", @@ -98,6 +131,7 @@ const internalEthPlugin_t const INTERNAL_ETH_PLUGINS[] = { #endif { + NULL, NULL, 0, "", diff --git a/src/eth_plugin_internal.h b/src/eth_plugin_internal.h index 065dad9..3a8c966 100644 --- a/src/eth_plugin_internal.h +++ b/src/eth_plugin_internal.h @@ -4,7 +4,10 @@ #define SELECTOR_SIZE 4 +typedef bool (*PluginAvailableCheck)(void); + typedef struct internalEthPlugin_t { + PluginAvailableCheck availableCheck; const uint8_t **selectors; uint8_t num_selectors; char alias[7]; @@ -14,6 +17,9 @@ typedef struct internalEthPlugin_t { #define NUM_ERC20_SELECTORS 2 extern const uint8_t* const ERC20_SELECTORS[NUM_ERC20_SELECTORS]; +#define NUM_ERC721_SELECTORS 1 +extern const uint8_t* const ERC721_SELECTORS[NUM_ERC721_SELECTORS]; + #define NUM_COMPOUND_SELECTORS 4 extern const uint8_t* const COMPOUND_SELECTORS[NUM_COMPOUND_SELECTORS]; @@ -26,7 +32,7 @@ extern const uint8_t* const ETH2_SELECTORS[NUM_ETH2_SELECTORS]; #ifdef HAVE_STARKWARE -#define NUM_STARKWARE_SELECTORS 10 +#define NUM_STARKWARE_SELECTORS 16 extern const uint8_t* const STARKWARE_SELECTORS[NUM_STARKWARE_SELECTORS]; #endif diff --git a/src/handle_check_address.c b/src/handle_check_address.c index 7279b88..703ebe2 100644 --- a/src/handle_check_address.c +++ b/src/handle_check_address.c @@ -4,7 +4,7 @@ #include "ethUtils.h" #include "string.h" -#define ZERO(x) os_memset(x, 0, sizeof(x)) +#define ZERO(x) 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); @@ -60,10 +60,10 @@ void handle_check_address(check_address_parameters_t* params, chain_config_t* ch } 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) { + memcmp(locals_union1.address, params->address_to_check + offset_0x, strlen(locals_union1.address)) != 0) { 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_get_printable_amount.c b/src/handle_get_printable_amount.c index 6f7d36d..0d5e0dd 100644 --- a/src/handle_get_printable_amount.c +++ b/src/handle_get_printable_amount.c @@ -10,7 +10,7 @@ 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)); + 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(); @@ -30,4 +30,4 @@ void handle_get_printable_amount( get_printable_amount_parameters_t* params, cha } 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/main.c b/src/main.c index e6d5638..f47fff6 100644 --- a/src/main.c +++ b/src/main.c @@ -69,7 +69,7 @@ chain_config_t *chainConfig; void reset_app_context() { //PRINTF("!!RESET_APP_CONTEXT\n"); appState = APP_STATE_IDLE; - os_memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN); + memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN); called_from_swap = false; #ifdef HAVE_STARKWARE quantumSet = false; @@ -77,8 +77,8 @@ void reset_app_context() { #ifdef HAVE_ETH2 eth2WithdrawalIndex = 0; #endif - os_memset((uint8_t*)&txContext, 0, sizeof(txContext)); - os_memset((uint8_t*)&tmpContent, 0, sizeof(tmpContent)); + memset((uint8_t*)&txContext, 0, sizeof(txContext)); + memset((uint8_t*)&tmpContent, 0, sizeof(tmpContent)); } void ui_idle(void) { @@ -118,7 +118,7 @@ void io_seproxyhal_send_status(uint32_t sw) { } void format_signature_out(const uint8_t* signature) { - os_memset(G_io_apdu_buffer + 1, 0x00, 64); + memset(G_io_apdu_buffer + 1, 0x00, 64); uint8_t offset = 1; uint8_t xoffset = 4; //point to r value //copy r @@ -355,14 +355,14 @@ tokenDefinition_t* getKnownToken(uint8_t *contractAddress) { currentToken = (tokenDefinition_t *)PIC(&TOKENS_THUNDERCORE[i]); break } - if (os_memcmp(currentToken->address, tmpContent.txContent.destination, 20) == 0) { + if (memcmp(currentToken->address, tmpContent.txContent.destination, 20) == 0) { return currentToken; } } #endif for(size_t i=0; iaddress, contractAddress, 20) == 0)) { + if (tmpCtx.transactionContext.tokenSet[i] && (memcmp(currentToken->address, contractAddress, 20) == 0)) { PRINTF("Token found at index %d\n", i); return currentToken; } @@ -390,6 +390,9 @@ void handleApdu(unsigned int *flags, unsigned int *tx) { case STARKWARE_INS_PROVIDE_QUANTUM: handleStarkwareProvideQuantum(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx); break; + case STARKWARE_INS_UNSAFE_SIGN: + handleStarkwareUnsafeSign(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx); + break; default: THROW(0x6D00); break; @@ -406,7 +409,7 @@ void handleApdu(unsigned int *flags, unsigned int *tx) { switch (G_io_apdu_buffer[OFFSET_INS]) { case INS_GET_PUBLIC_KEY: - os_memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN); + memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN); handleGetPublicKey(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx); break; @@ -423,19 +426,19 @@ void handleApdu(unsigned int *flags, unsigned int *tx) { break; case INS_SIGN_PERSONAL_MESSAGE: - os_memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN); + memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN); handleSignPersonalMessage(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx); break; case INS_SIGN_EIP_712_MESSAGE: - os_memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN); + memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN); handleSignEIP712Message(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx); break; #ifdef HAVE_ETH2 case INS_GET_ETH2_PUBLIC_KEY: - os_memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN); + memset(tmpCtx.transactionContext.tokenSet, 0, MAX_TOKEN); handleGetEth2PublicKey(G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2], G_io_apdu_buffer + OFFSET_CDATA, G_io_apdu_buffer[OFFSET_LC], flags, tx); break; @@ -675,7 +678,7 @@ void coin_main_with_config(chain_config_t *config) { } void init_coin_config(chain_config_t *coin_config) { - os_memset(coin_config, 0, sizeof(chain_config_t)); + memset(coin_config, 0, sizeof(chain_config_t)); strcpy(coin_config->coinName, CHAINID_COINNAME " "); coin_config->chainId = CHAIN_ID; coin_config->kind = CHAIN_KIND; diff --git a/src/poorstream.c b/src/poorstream.c index bd371aa..24e4d59 100644 --- a/src/poorstream.c +++ b/src/poorstream.c @@ -3,7 +3,7 @@ #include "poorstream.h" void poorstream_init(poorstream_t *stream, uint8_t *buffer) { - os_memset((void*)stream, 0, sizeof(poorstream_t)); + memset((void*)stream, 0, sizeof(poorstream_t)); stream->pointer = buffer; } diff --git a/src/shared_context.h b/src/shared_context.h index 23d78d7..5c6d151 100644 --- a/src/shared_context.h +++ b/src/shared_context.h @@ -30,6 +30,21 @@ typedef struct internalStorage_t { uint8_t initialized; } internalStorage_t; +#ifdef HAVE_STARKWARE + +typedef enum starkQuantumType_e { + + STARK_QUANTUM_LEGACY = 0x00, + STARK_QUANTUM_ETH, + STARK_QUANTUM_ERC20, + STARK_QUANTUM_ERC721, + STARK_QUANTUM_MINTABLE_ERC20, + STARK_QUANTUM_MINTABLE_ERC721 + +} starkQuantumType_e; + +#endif + typedef struct tokenContext_t { char pluginName[PLUGIN_ID_LENGTH]; uint8_t pluginAvailable; @@ -46,7 +61,9 @@ typedef struct tokenContext_t { #ifdef HAVE_STARKWARE uint8_t quantum[32]; + uint8_t mintingBlob[32]; uint8_t quantumIndex; + uint8_t quantumType; #endif } tokenContext_t; @@ -101,6 +118,11 @@ typedef struct starkContext_t { uint8_t w1[32]; uint8_t w2[32]; uint8_t w3[32]; + uint8_t w4[32]; + uint8_t conditional; + uint8_t transferDestination[32]; + uint8_t fact[32]; + uint8_t conditionAddress[20]; } starkContext_t; #endif diff --git a/src/stark_crypto.c b/src/stark_crypto.c index 3bbc61d..eb1ccd2 100644 --- a/src/stark_crypto.c +++ b/src/stark_crypto.c @@ -9,21 +9,21 @@ static unsigned char const C_cx_Stark256_n[] = { //n: 0x0800000000000010ffffffffffffffffb781126dcae7b2321e66a241adc64d2f 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x81, 0x12, 0x6d, 0xca, 0xe7, 0xb2, 0x32, 0x1e, 0x66, 0xa2, 0x41, 0xad, 0xc6, 0x4d, 0x2f}; - + // C_cx_secp256k1_n - (C_cx_secp256k1_n % C_cx_Stark256_n) static unsigned char const STARK_DERIVE_BIAS[] = { 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x38, 0xa1, 0x3b, 0x4b, 0x92, 0x0e, 0x94, 0x11, 0xae, 0x6d, 0xa5, 0xf4, 0x0b, 0x03, 0x58, 0xb1 -}; +}; -void starkDerivePrivateKey(uint32_t *bip32Path, uint32_t bip32PathLength, uint8_t *privateKeyData) { -#if 0 - // Sanity check +void starkDerivePrivateKey(uint32_t *bip32Path, uint32_t bip32PathLength, uint8_t *privateKeyData) { +#if 0 + // Sanity check if (bip32Path[0] != STARK_BIP32_PATH_0) { PRINTF("Invalid Stark derivation path %d\n", bip32Path[0]); THROW(0x6a80); } - os_perso_derive_node_bip32(CX_CURVE_256K1, bip32Path, bip32PathLength, privateKeyData, NULL); + os_perso_derive_node_bip32(CX_CURVE_256K1, bip32Path, bip32PathLength, privateKeyData, NULL); PRINTF("Private key before processing %.*H\n", 32, privateKeyData); // TODO - support additional schemes cx_math_modm(privateKeyData, 32, C_cx_Stark256_n, 32); @@ -31,30 +31,32 @@ void starkDerivePrivateKey(uint32_t *bip32Path, uint32_t bip32PathLength, uint8_ #else uint8_t tmp[33]; uint8_t index = 0; - // Sanity check + // Sanity check if ((bip32PathLength < 2) || (bip32Path[0] != STARK_BIP32_PATH_0) || (bip32Path[1] != STARK_BIP32_PATH_1)) { PRINTF("Invalid Stark derivation path %d %d\n", bip32Path[0], bip32Path[1]); THROW(0x6a80); } - os_perso_derive_node_bip32(CX_CURVE_256K1, bip32Path, bip32PathLength, tmp, NULL); + os_perso_derive_node_bip32(CX_CURVE_256K1, bip32Path, bip32PathLength, tmp, NULL); PRINTF("Private key before processing %.*H\n", 32, tmp); for(;;) { tmp[32] = index; cx_hash_sha256(tmp, 33, privateKeyData, 32); + PRINTF("Key hash %.*H\n", 32, privateKeyData); if (cx_math_cmp(privateKeyData, STARK_DERIVE_BIAS, 32) < 0) { cx_math_modm(privateKeyData, 32, C_cx_Stark256_n, 32); break; } index++; } + PRINTF("Key result %.*H\n", 32, privateKeyData); -#endif +#endif } void stark_get_amount_string(uint8_t *contractAddress, uint8_t *quantum256, uint8_t *amount64, char *tmp100, char *target100) { uint256_t amountPre, quantum, amount; - uint8_t decimals; - char *ticker = (char*)PIC(chainConfig->coinName); + uint8_t decimals; + char *ticker = (char*)PIC(chainConfig->coinName); PRINTF("stark_get_amount_string %.*H\n", 20, contractAddress); diff --git a/src/stark_crypto.h b/src/stark_crypto.h index 91b7df2..b4e58a9 100644 --- a/src/stark_crypto.h +++ b/src/stark_crypto.h @@ -18,8 +18,4 @@ typedef unsigned char ECPoint[EC_POINT_SIZE]; void pedersen(FieldElement res, /* out */ FieldElement a, FieldElement b); -int stark_sign(uint8_t *signautre, /* out */ - uint8_t *privateKeyData, FieldElement token1, - FieldElement token2, FieldElement msg); - -#endif +#endif diff --git a/src/stark_utils.c b/src/stark_utils.c index 1ded1f6..8b5673b 100644 --- a/src/stark_utils.c +++ b/src/stark_utils.c @@ -1,6 +1,7 @@ #ifdef HAVE_STARKWARE #include "stark_crypto.h" +#include "shared_context.h" #include "ethUtils.h" #include "os_io_seproxyhal.h" @@ -81,7 +82,7 @@ void pedersen(FieldElement res, /* out */ ECPoint hash; memcpy(hash, PEDERSEN_SHIFT, sizeof(hash)); - + accum_ec_mul(&hash, a, 1, 1); accum_ec_mul(&hash, a+1, FIELD_ELEMENT_SIZE-1, 0); accum_ec_mul(&hash, b, 1, 3); @@ -94,15 +95,23 @@ int stark_sign(uint8_t *signature, /* out */ uint8_t *privateKeyData, FieldElement token1, FieldElement token2, - FieldElement msg) { + FieldElement msg, + FieldElement condition) { unsigned int info = 0; FieldElement hash; cx_ecfp_private_key_t privateKey; PRINTF("Stark sign msg w1 %.*H\n", 32, token1); PRINTF("Stark sign msg w2 %.*H\n", 32, token2); PRINTF("Stark sign w3 %.*H\n", 32, msg); + if (condition != NULL) { + PRINTF("Stark sign w4 %.*H\n", 32, condition); + } pedersen(hash, token1, token2); PRINTF("Pedersen hash 1 %.*H\n", 32, hash); + if (condition != NULL) { + pedersen(hash, hash, condition); + PRINTF("Pedersen hash condition %.*H\n", 32, hash); + } pedersen(hash, hash, msg); PRINTF("Pedersen hash 2 %.*H\n", 32, hash); cx_ecfp_init_private_key(CX_CURVE_Stark256, privateKeyData, 32, &privateKey); @@ -114,27 +123,90 @@ int stark_sign(uint8_t *signature, /* out */ } // ERC20Token(address) -static const uint8_t ERC20_SELECTOR[] = { 0xf4, 0x72, 0x61, 0xb0 }; +static const uint8_t ERC20_SELECTOR[] = { 0xf4, 0x72, 0x61, 0xb0 }; // ETH() static const uint8_t ETH_SELECTOR[] = { 0x83, 0x22, 0xff, 0xf2 }; +// ERC721Token(address, uint256) +static const uint8_t ERC721_SELECTOR[] = { 0x02, 0x57, 0x17, 0x92 }; +// MintableERC20Token(address) +static const uint8_t MINTABLE_ERC20_SELECTOR[] = { 0x68, 0x64, 0x6e, 0x2d }; +// MintableERC721Token(address,uint256) +static const uint8_t MINTABLE_ERC721_SELECTOR[] = { 0xb8, 0xb8, 0x66, 0x72 }; +static const char NFT_ASSET_ID_PREFIX[] = { 'N', 'F', 'T', ':', 0 }; +static const char MINTABLE_ASSET_ID_PREFIX[] = { 'M', 'I', 'N', 'T', 'A', 'B', 'L', 'E', ':', 0 }; -void compute_token_id(cx_sha3_t *sha3, uint8_t *contractAddress, uint8_t *quantum, uint8_t *output) { +void compute_token_id(cx_sha3_t *sha3, uint8_t *contractAddress, uint8_t quantumType, uint8_t *quantum, uint8_t *mintingBlob, bool assetTypeOnly, uint8_t *output) { uint8_t tmp[36]; cx_keccak_init(sha3, 256); if ((contractAddress != NULL) && (!allzeroes(contractAddress, 20))) { + const uint8_t *selector = NULL; + switch(quantumType) { + case STARK_QUANTUM_ERC20: + case STARK_QUANTUM_LEGACY: + selector = ERC20_SELECTOR; + break; + case STARK_QUANTUM_ERC721: + selector = ERC721_SELECTOR; + break; + case STARK_QUANTUM_MINTABLE_ERC20: + selector = MINTABLE_ERC20_SELECTOR; + break; + case STARK_QUANTUM_MINTABLE_ERC721: + selector = MINTABLE_ERC721_SELECTOR; + break; + default: + PRINTF("Unsupported quantum type %d\n", quantumType); + return; + } PRINTF("compute_token_id for %.*H\n", 20, contractAddress); - os_memset(tmp, 0, sizeof(tmp)); - os_memmove(tmp, ERC20_SELECTOR, 4); - os_memmove(tmp + 16, contractAddress, 20); - cx_hash((cx_hash_t*)sha3, 0, tmp, sizeof(tmp), NULL, 0); + memset(tmp, 0, sizeof(tmp)); + memmove(tmp, selector, 4); + memmove(tmp + 16, contractAddress, 20); + cx_hash((cx_hash_t*)sha3, 0, tmp, sizeof(tmp), NULL, 0); } else { PRINTF("compute_token_id for ETH\n"); - cx_hash((cx_hash_t*)sha3, 0, ETH_SELECTOR, sizeof(ETH_SELECTOR), NULL, 0); + cx_hash((cx_hash_t*)sha3, 0, ETH_SELECTOR, sizeof(ETH_SELECTOR), NULL, 0); + } + if ((quantumType == STARK_QUANTUM_ERC721) || (quantumType == STARK_QUANTUM_MINTABLE_ERC721)) { + memset(tmp, 0, 32); + tmp[31] = 1; + PRINTF("compute_token_id quantum %.*H\n", 32, tmp); + cx_hash((cx_hash_t*)sha3, CX_LAST, tmp, 32, output, 32); + } + else { + PRINTF("compute_token_id quantum %.*H\n", 32, quantum); + cx_hash((cx_hash_t*)sha3, CX_LAST, quantum, 32, output, 32); + } + if (!assetTypeOnly && ((quantumType != STARK_QUANTUM_LEGACY) && + (quantumType != STARK_QUANTUM_ETH) && + (quantumType != STARK_QUANTUM_ERC20))) { + const char *prefix = NULL; + output[0] &= 0x03; + cx_keccak_init(sha3, 256); + switch(quantumType) { + case STARK_QUANTUM_ERC721: + prefix = NFT_ASSET_ID_PREFIX; + break; + case STARK_QUANTUM_MINTABLE_ERC20: + case STARK_QUANTUM_MINTABLE_ERC721: + prefix = MINTABLE_ASSET_ID_PREFIX; + break; + default: + PRINTF("Unsupported non default quantum type %d\n", quantumType); + return; + } + cx_hash((cx_hash_t*)sha3, 0, (const uint8_t*)prefix, strlen(prefix), NULL, 0); + cx_hash((cx_hash_t*)sha3, 0, output, 32, NULL, 0); + cx_hash((cx_hash_t*)sha3, CX_LAST, mintingBlob, 32, output, 32); + } + if (!assetTypeOnly && ((quantumType == STARK_QUANTUM_MINTABLE_ERC20) || (quantumType == STARK_QUANTUM_MINTABLE_ERC721))) { + output[0] = 0x04; + output[1] = 0x00; + } + else { + output[0] &= 0x03; } - PRINTF("compute_token_id quantum %.*H\n", 32, quantum); - cx_hash((cx_hash_t*)sha3, CX_LAST, quantum, 32, output, 32); - output[0] &= 0x03; PRINTF("compute_token_id computed token %.*H\n", 32, output); } diff --git a/src/stark_utils.h b/src/stark_utils.h index 0edb5e4..c02ca76 100644 --- a/src/stark_utils.h +++ b/src/stark_utils.h @@ -9,7 +9,7 @@ #include "cx.h" #include "stark_crypto.h" -void compute_token_id(cx_sha3_t *sha3, uint8_t *contractAddress, uint8_t *quantum, uint8_t *output); +void compute_token_id(cx_sha3_t *sha3, uint8_t *contractAddress, uint8_t quantumType, uint8_t *quantum, uint8_t *mintingBlob, bool assetTypeOnly, uint8_t *output); void starkDerivePrivateKey(uint32_t *bip32Path, uint32_t bip32PathLength, uint8_t *privateKeyData); @@ -19,7 +19,8 @@ int stark_sign(uint8_t *signature, /* out */ uint8_t *privateKeyData, FieldElement token1, FieldElement token2, - FieldElement msg); + FieldElement msg, + FieldElement condition); #endif diff --git a/src/tokens.c b/src/tokens.c index cd57236..1d79941 100644 --- a/src/tokens.c +++ b/src/tokens.c @@ -22,6 +22,7 @@ const tokenDefinition_t const TOKENS_EXTRA[NUM_TOKENS_EXTRA] = { {{0x4c,0x5f,0x66,0x59,0x61,0x97,0xa8,0x6f,0xb3,0x0a,0x24,0x35,0xe2,0xef,0x4d,0xdc,0xb3,0x93,0x42,0xc9}, "tUSDT ", 6}, + {{0x1c,0x0f,0x17,0x43,0x67,0x40,0xbf,0xb9,0x2c,0x10,0x70,0xee,0x86,0x32,0x2d,0xe8,0x90,0x83,0x7c,0x6a}, "tUSDT ", 6}, {{0xcd,0x07,0x7a,0xbe,0xdd,0x83,0x1a,0x34,0x43,0xff,0xbe,0x24,0xfb,0x76,0x66,0x1b,0xbb,0x17,0xeb,0x69}, "tZRX ", 18}, {{0x40,0xd8,0x97,0x85,0x00,0xbf,0x68,0x32,0x4a,0x51,0x53,0x3c,0xd6,0xa2,0x1e,0x3e,0x59,0xbe,0x32,0x4a}, "tBTC ", 18}, diff --git a/src/tokens.h b/src/tokens.h index aa8d367..f103576 100644 --- a/src/tokens.h +++ b/src/tokens.h @@ -33,7 +33,7 @@ typedef struct tokenDefinition_t { #ifdef HAVE_TOKENS_EXTRA_LIST -#define NUM_TOKENS_EXTRA 3 +#define NUM_TOKENS_EXTRA 4 extern tokenDefinition_t const TOKENS_EXTRA[NUM_TOKENS_EXTRA]; diff --git a/src/ui_flow.h b/src/ui_flow.h index 67ef94a..f768b54 100644 --- a/src/ui_flow.h +++ b/src/ui_flow.h @@ -34,6 +34,10 @@ extern const ux_flow_step_t * const ux_stark_transfer_flow []; extern const ux_flow_step_t * const ux_stark_self_transfer_flow []; +extern const ux_flow_step_t * const ux_stark_transfer_conditional_flow []; + +extern const ux_flow_step_t * const ux_stark_self_transfer_conditional_flow []; + extern const ux_flow_step_t * const ux_approval_starkware_register_flow []; extern const ux_flow_step_t * const ux_approval_starkware_deposit_flow []; @@ -46,5 +50,7 @@ extern const ux_flow_step_t * const ux_approval_starkware_escape_flow []; extern const ux_flow_step_t * const ux_approval_starkware_verify_escape_flow []; +extern const ux_flow_step_t * const ux_stark_unsafe_sign_flow []; + #endif diff --git a/src/utils.c b/src/utils.c index b991f5f..8747f3c 100644 --- a/src/utils.c +++ b/src/utils.c @@ -37,8 +37,8 @@ void array_hexstr(char *strbuf, const void *bin, unsigned int len) { void convertUint256BE(uint8_t *data, uint32_t length, uint256_t *target) { uint8_t tmp[32]; - os_memset(tmp, 0, 32); - os_memmove(tmp + 32 - length, data, length); + memset(tmp, 0, 32); + memmove(tmp + 32 - length, data, length); readu256BE(tmp, target); } @@ -113,4 +113,4 @@ bool parse_swap_config(uint8_t* config, uint8_t config_len, char* ticker, uint8_ } *decimals = config[offset]; return true; -} \ No newline at end of file +} diff --git a/src_common/ethUstream.c b/src_common/ethUstream.c index c081c2a..a024986 100644 --- a/src_common/ethUstream.c +++ b/src_common/ethUstream.c @@ -26,7 +26,7 @@ void initTx(txContext_t *context, cx_sha3_t *sha3, txContent_t *content, ustreamProcess_t customProcessor, void *extra) { - os_memset(context, 0, sizeof(txContext_t)); + memset(context, 0, sizeof(txContext_t)); context->sha3 = sha3; context->content = content; context->customProcessor = customProcessor; @@ -59,7 +59,7 @@ void copyTxData(txContext_t *context, uint8_t *out, uint32_t length) { THROW(EXCEPTION); } if (out != NULL) { - os_memmove(out, context->workBuffer, length); + memmove(out, context->workBuffer, length); } if (!(context->processingField && context->fieldSingleByte)) { cx_hash((cx_hash_t*)context->sha3, 0, context->workBuffer, length, NULL, 0); diff --git a/src_common/ethUtils.c b/src_common/ethUtils.c index 8e7ae08..3da9087 100644 --- a/src_common/ethUtils.c +++ b/src_common/ethUtils.c @@ -123,7 +123,7 @@ void getEthAddressFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out, uint8_t hashAddress[32]; cx_keccak_init(sha3Context, 256); cx_hash((cx_hash_t*)sha3Context, CX_LAST, publicKey->W + 1, 64, hashAddress, 32); - os_memmove(out, hashAddress + 12, 20); + memmove(out, hashAddress + 12, 20); } diff --git a/src_common/uint256.c b/src_common/uint256.c index e67f195..6d585a4 100644 --- a/src_common/uint256.c +++ b/src_common/uint256.c @@ -350,7 +350,7 @@ void read_u64_be(uint8_t *in, uint64_t *out) { void mul256(uint256_t *number1, uint256_t *number2, uint256_t *target) { uint8_t num1[32], num2[32], result[64]; - os_memset(&result, 0, sizeof(result)); + 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]); diff --git a/src_features/getAppConfiguration/cmd_getAppConfiguration.c b/src_features/getAppConfiguration/cmd_getAppConfiguration.c index ed674dd..f6a34a7 100644 --- a/src_features/getAppConfiguration/cmd_getAppConfiguration.c +++ b/src_features/getAppConfiguration/cmd_getAppConfiguration.c @@ -15,6 +15,7 @@ void handleGetAppConfiguration(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint #endif #ifdef HAVE_STARKWARE G_io_apdu_buffer[0] |= APP_FLAG_STARKWARE; + G_io_apdu_buffer[0] |= APP_FLAG_STARKWARE_V2; #endif G_io_apdu_buffer[1] = LEDGER_MAJOR_VERSION; G_io_apdu_buffer[2] = LEDGER_MINOR_VERSION; diff --git a/src_features/getEth2PublicKey/cmd_getEth2PublicKey.c b/src_features/getEth2PublicKey/cmd_getEth2PublicKey.c index 34696b0..b6c5618 100644 --- a/src_features/getEth2PublicKey/cmd_getEth2PublicKey.c +++ b/src_features/getEth2PublicKey/cmd_getEth2PublicKey.c @@ -22,8 +22,8 @@ void getEth2PublicKey(uint32_t *bip32Path, uint8_t bip32PathLength, uint8_t *out memmove(tmp + 16, privateKeyData, 32); cx_ecfp_init_private_key(CX_CURVE_BLS12_381_G1, tmp, 48, &privateKey); cx_ecfp_generate_pair(CX_CURVE_BLS12_381_G1, &publicKey, &privateKey, 1); - memset(tmp, 0, 96); - memset((void*)&privateKey, 0, sizeof(cx_ecfp_256_extended_private_key_t)); + explicit_bzero(tmp, 96); + explicit_bzero((void*)&privateKey, sizeof(cx_ecfp_256_extended_private_key_t)); tmp[47] = 2; cx_math_mult(tmp, publicKey.W + 1 + 48, tmp, 48); if (cx_math_cmp(tmp + 48, BLS12_381_FIELD_MODULUS, 48) > 0) { diff --git a/src_features/getEth2PublicKey/logic_getEth2PublicKey.c b/src_features/getEth2PublicKey/logic_getEth2PublicKey.c index 91ae7ab..33d005a 100644 --- a/src_features/getEth2PublicKey/logic_getEth2PublicKey.c +++ b/src_features/getEth2PublicKey/logic_getEth2PublicKey.c @@ -4,7 +4,7 @@ uint32_t set_result_get_eth2_publicKey() { uint32_t tx = 0; - os_memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.publicKey.W, 48); + memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.publicKey.W, 48); tx += 48; return tx; } diff --git a/src_features/getPublicKey/cmd_getPublicKey.c b/src_features/getPublicKey/cmd_getPublicKey.c index 72dabb6..9a2aa60 100644 --- a/src_features/getPublicKey/cmd_getPublicKey.c +++ b/src_features/getPublicKey/cmd_getPublicKey.c @@ -35,8 +35,8 @@ void handleGetPublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t da cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey); io_seproxyhal_io_heartbeat(); cx_ecfp_generate_pair(CX_CURVE_256K1, &tmpCtx.publicKeyContext.publicKey, &privateKey, 1); - os_memset(&privateKey, 0, sizeof(privateKey)); - os_memset(privateKeyData, 0, sizeof(privateKeyData)); + explicit_bzero(&privateKey, sizeof(privateKey)); + explicit_bzero(privateKeyData, sizeof(privateKeyData)); io_seproxyhal_io_heartbeat(); getEthAddressStringFromKey(&tmpCtx.publicKeyContext.publicKey, tmpCtx.publicKeyContext.address, &global_sha3, chainConfig); #ifndef NO_CONSENT diff --git a/src_features/getPublicKey/logic_getPublicKey.c b/src_features/getPublicKey/logic_getPublicKey.c index 32a7ef0..a538d96 100644 --- a/src_features/getPublicKey/logic_getPublicKey.c +++ b/src_features/getPublicKey/logic_getPublicKey.c @@ -3,13 +3,13 @@ uint32_t set_result_get_publicKey() { uint32_t tx = 0; G_io_apdu_buffer[tx++] = 65; - os_memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.publicKey.W, 65); + memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.publicKey.W, 65); tx += 65; G_io_apdu_buffer[tx++] = 40; - os_memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.address, 40); + memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.address, 40); tx += 40; if (tmpCtx.publicKeyContext.getChaincode) { - os_memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.chainCode, 32); + memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.chainCode, 32); tx += 32; } return tx; diff --git a/src_features/provideErc20TokenInformation/cmd_provideTokenInfo.c b/src_features/provideErc20TokenInformation/cmd_provideTokenInfo.c index 887cfeb..1b825dd 100644 --- a/src_features/provideErc20TokenInformation/cmd_provideTokenInfo.c +++ b/src_features/provideErc20TokenInformation/cmd_provideTokenInfo.c @@ -47,7 +47,7 @@ void handleProvideErc20TokenInformation(uint8_t p1, uint8_t p2, uint8_t *workBuf THROW(0x6A80); } cx_hash((cx_hash_t*)&sha256, 0, workBuffer + offset, tickerLength, NULL, 0); - os_memmove(token->ticker, workBuffer + offset, tickerLength); + memmove(token->ticker, workBuffer + offset, tickerLength); token->ticker[tickerLength] = ' '; token->ticker[tickerLength + 1] = '\0'; offset += tickerLength; @@ -59,12 +59,12 @@ void handleProvideErc20TokenInformation(uint8_t p1, uint8_t p2, uint8_t *workBuf THROW(0x6A80); } cx_hash((cx_hash_t*)&sha256, CX_LAST, workBuffer + offset, contractNameLength + 20 + 4 + 4, hash, 32); - os_memmove(token->contractName, workBuffer + offset, MIN(contractNameLength, sizeof(token->contractName)-1)); + memmove(token->contractName, workBuffer + offset, MIN(contractNameLength, sizeof(token->contractName)-1)); token->contractName[MIN(contractNameLength, sizeof(token->contractName)-1)] = '\0'; offset += contractNameLength; dataLength -= contractNameLength; - os_memmove(token->address, workBuffer + offset, 20); + memmove(token->address, workBuffer + offset, 20); offset += 20; dataLength -= 20; token->decimals = U4BE(workBuffer, offset); @@ -116,12 +116,12 @@ void handleProvideErc20TokenInformation(uint8_t p1, uint8_t p2, uint8_t *workBuf THROW(0x6A80); } cx_hash_sha256(workBuffer + offset, tickerLength + 20 + 4 + 4, hash, 32); - os_memmove(token->ticker, workBuffer + offset, tickerLength); + memmove(token->ticker, workBuffer + offset, tickerLength); token->ticker[tickerLength] = ' '; token->ticker[tickerLength + 1] = '\0'; offset += tickerLength; dataLength -= tickerLength; - os_memmove(token->address, workBuffer + offset, 20); + memmove(token->address, workBuffer + offset, 20); offset += 20; dataLength -= 20; token->decimals = U4BE(workBuffer, offset); @@ -140,7 +140,7 @@ void handleProvideErc20TokenInformation(uint8_t p1, uint8_t p2, uint8_t *workBuf uint32_t index; for (index=0; index < NUM_TOKENS_EXTRA; index++) { currentToken = (tokenDefinition_t *)PIC(&TOKENS_EXTRA[index]); - if (os_memcmp(currentToken->address, token->address, 20) == 0) { + if (memcmp(currentToken->address, token->address, 20) == 0) { strcpy((char*)token->ticker, (char*)currentToken->ticker); token->decimals = currentToken->decimals; break; diff --git a/src_features/setEth2WithdrawalIndex/cmd_setEth2WithdrawalIndex.c b/src_features/setEth2WithdrawalIndex/cmd_setEth2WithdrawalIndex.c index 1dfa19f..ff1bc03 100644 --- a/src_features/setEth2WithdrawalIndex/cmd_setEth2WithdrawalIndex.c +++ b/src_features/setEth2WithdrawalIndex/cmd_setEth2WithdrawalIndex.c @@ -5,8 +5,6 @@ void handleSetEth2WithdrawalIndex(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) { - UNUSED(dataLength); - if (dataLength != 4) { THROW(0x6700); } diff --git a/src_features/signMessage/ui_common_signMessage.c b/src_features/signMessage/ui_common_signMessage.c index 79c1f4f..306cca9 100644 --- a/src_features/signMessage/ui_common_signMessage.c +++ b/src_features/signMessage/ui_common_signMessage.c @@ -13,14 +13,14 @@ unsigned int io_seproxyhal_touch_signMessage_ok(const bagl_element_t *e) { tmpCtx.messageSigningContext.pathLength, privateKeyData, NULL); io_seproxyhal_io_heartbeat(); cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey); - os_memset(privateKeyData, 0, sizeof(privateKeyData)); + explicit_bzero(privateKeyData, sizeof(privateKeyData)); unsigned int info = 0; io_seproxyhal_io_heartbeat(); signatureLength = cx_ecdsa_sign(&privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256, tmpCtx.messageSigningContext.hash, sizeof(tmpCtx.messageSigningContext.hash), signature, sizeof(signature), &info); - os_memset(&privateKey, 0, sizeof(privateKey)); + explicit_bzero(&privateKey, sizeof(privateKey)); G_io_apdu_buffer[0] = 27; if (info & CX_ECCINFO_PARITY_ODD) { G_io_apdu_buffer[0]++; diff --git a/src_features/signMessageEIP712/ui_common_signMessage712.c b/src_features/signMessageEIP712/ui_common_signMessage712.c index 20954fd..e503642 100644 --- a/src_features/signMessageEIP712/ui_common_signMessage712.c +++ b/src_features/signMessageEIP712/ui_common_signMessage712.c @@ -24,14 +24,14 @@ unsigned int io_seproxyhal_touch_signMessage712_v0_ok(const bagl_element_t *e) { tmpCtx.messageSigningContext712.pathLength, privateKeyData, NULL); io_seproxyhal_io_heartbeat(); cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey); - os_memset(privateKeyData, 0, sizeof(privateKeyData)); + explicit_bzero(privateKeyData, sizeof(privateKeyData)); unsigned int info = 0; io_seproxyhal_io_heartbeat(); signatureLength = cx_ecdsa_sign(&privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256, hash, sizeof(hash), signature, sizeof(signature), &info); - os_memset(&privateKey, 0, sizeof(privateKey)); + explicit_bzero(&privateKey, sizeof(privateKey)); G_io_apdu_buffer[0] = 27; if (info & CX_ECCINFO_PARITY_ODD) { G_io_apdu_buffer[0]++; diff --git a/src_features/signTx/logic_signTx.c b/src_features/signTx/logic_signTx.c index b4c7383..cc1336b 100644 --- a/src_features/signTx/logic_signTx.c +++ b/src_features/signTx/logic_signTx.c @@ -158,7 +158,7 @@ void compareOrCopy(char* preapproved_string, char* parsed_string, bool silent_mo 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))){ + if(memcmp(preapproved_string, parsed_string, strlen(preapproved_string))){ THROW(ERR_SILENT_MODE_CHECK_FAILED); } } diff --git a/src_features/signTx/ui_common_signTx.c b/src_features/signTx/ui_common_signTx.c index 102de66..17efa4c 100644 --- a/src_features/signTx/ui_common_signTx.c +++ b/src_features/signTx/ui_common_signTx.c @@ -15,14 +15,14 @@ unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e) { privateKeyData, NULL); cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey); - os_memset(privateKeyData, 0, sizeof(privateKeyData)); + explicit_bzero(privateKeyData, sizeof(privateKeyData)); unsigned int info = 0; io_seproxyhal_io_heartbeat(); signatureLength = cx_ecdsa_sign(&privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256, tmpCtx.transactionContext.hash, sizeof(tmpCtx.transactionContext.hash), signature, sizeof(signature), &info); - os_memset(&privateKey, 0, sizeof(privateKey)); + explicit_bzero(&privateKey, sizeof(privateKey)); // Parity is present in the sequence tag in the legacy API if (tmpContent.txContent.vLength == 0) { // Legacy API diff --git a/src_features/stark_getPublicKey/cmd_stark_getPublicKey.c b/src_features/stark_getPublicKey/cmd_stark_getPublicKey.c index 1662046..dc0a35f 100644 --- a/src_features/stark_getPublicKey/cmd_stark_getPublicKey.c +++ b/src_features/stark_getPublicKey/cmd_stark_getPublicKey.c @@ -34,8 +34,8 @@ void handleStarkwareGetPublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, ui cx_ecfp_init_private_key(CX_CURVE_Stark256, privateKeyData, 32, &privateKey); io_seproxyhal_io_heartbeat(); cx_ecfp_generate_pair(CX_CURVE_Stark256, &tmpCtx.publicKeyContext.publicKey, &privateKey, 1); - os_memset(&privateKey, 0, sizeof(privateKey)); - os_memset(privateKeyData, 0, sizeof(privateKeyData)); + explicit_bzero(&privateKey, sizeof(privateKey)); + explicit_bzero(privateKeyData, sizeof(privateKeyData)); io_seproxyhal_io_heartbeat(); #ifndef NO_CONSENT if (p1 == P1_NON_CONFIRM) diff --git a/src_features/stark_getPublicKey/logic_stark_getPublicKey.c b/src_features/stark_getPublicKey/logic_stark_getPublicKey.c index bd03ca4..20fb704 100644 --- a/src_features/stark_getPublicKey/logic_stark_getPublicKey.c +++ b/src_features/stark_getPublicKey/logic_stark_getPublicKey.c @@ -5,7 +5,7 @@ uint32_t set_result_get_stark_publicKey() { uint32_t tx = 0; - os_memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.publicKey.W, 65); + memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.publicKey.W, 65); tx += 65; return tx; } diff --git a/src_features/stark_provideQuantum/cmd_stark_provideQuantum.c b/src_features/stark_provideQuantum/cmd_stark_provideQuantum.c index 1a90b59..076c6f6 100644 --- a/src_features/stark_provideQuantum/cmd_stark_provideQuantum.c +++ b/src_features/stark_provideQuantum/cmd_stark_provideQuantum.c @@ -6,17 +6,35 @@ void handleStarkwareProvideQuantum(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) { size_t i = 0; + uint8_t expectedDataSize = 20 + 32; + uint8_t addressZero = 0; tokenDefinition_t *currentToken = NULL; if (appState != APP_STATE_IDLE) { reset_app_context(); } - if (dataLength != 20 + 32) { + switch(p1) { + case STARK_QUANTUM_LEGACY: + break; + case STARK_QUANTUM_ETH: + case STARK_QUANTUM_ERC20: + case STARK_QUANTUM_ERC721: + case STARK_QUANTUM_MINTABLE_ERC20: + case STARK_QUANTUM_MINTABLE_ERC721: + expectedDataSize += 32; + break; + default: + THROW(0x6B00); + } + if (dataLength != expectedDataSize) { THROW(0x6700); } - if (!allzeroes(dataBuffer, 20)) { + if (p1 == STARK_QUANTUM_LEGACY) { + addressZero = allzeroes(dataBuffer, 20); + } + if ((p1 != STARK_QUANTUM_ETH) && !addressZero) { for(i=0; iaddress, dataBuffer, 20) == 0)) { + if (tmpCtx.transactionContext.tokenSet[i] && (memcmp(currentToken->address, dataBuffer, 20) == 0)) { break; } } @@ -28,8 +46,12 @@ void handleStarkwareProvideQuantum(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, else { i = MAX_TOKEN; } - os_memmove(dataContext.tokenContext.quantum, dataBuffer + 20, 32); + memmove(dataContext.tokenContext.quantum, dataBuffer + 20, 32); + if (p1 != STARK_QUANTUM_LEGACY) { + memmove(dataContext.tokenContext.mintingBlob, dataBuffer + 20 + 32, 32); + } dataContext.tokenContext.quantumIndex = i; + dataContext.tokenContext.quantumType = p1; quantumSet = true; THROW(0x9000); } diff --git a/src_features/stark_sign/cmd_stark_sign.c b/src_features/stark_sign/cmd_stark_sign.c index 0185a00..b2c3b3b 100644 --- a/src_features/stark_sign/cmd_stark_sign.c +++ b/src_features/stark_sign/cmd_stark_sign.c @@ -18,6 +18,10 @@ void handleStarkwareSignMessage(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uin cx_ecfp_private_key_t privateKey; poorstream_t bitstream; bool selfTransfer = false; + uint8_t order = 1; + uint8_t protocol = 2; + uint8_t preOffset, postOffset; + uint8_t zeroTest; // Initial checks if (appState != APP_STATE_IDLE) { reset_app_context(); @@ -29,18 +33,35 @@ void handleStarkwareSignMessage(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uin } switch(p1) { case P1_STARK_ORDER: - if (dataLength != (20 + 32 + 20 + 32 + 4 + 4 + 8 + 8 + 4 + 4 + 1 + 4 * bip32PathLength)) { - THROW(0x6700); - } + protocol = 1; break; case P1_STARK_TRANSFER: - if (dataLength != (20 + 32 + 32 + 4 + 4 + 8 + 4 + 4 + 1 + 4 * bip32PathLength)) { - THROW(0x6700); - } + protocol = 1; + order = 0; + break; + case P1_STARK_ORDER_V2: + break; + case P1_STARK_TRANSFER_V2: + case P1_STARK_CONDITIONAL_TRANSFER: + order = 0; break; default: THROW(0x6B00); } + postOffset = (protocol == 2 ? 1 + 32 : 0); + preOffset = (protocol == 2 ? 1 : 0); + if (order) { + if (dataLength != (20 + 32 + 20 + 32 + 4 + 4 + 8 + 8 + 4 + 4 + 1 + 4 * bip32PathLength + + 2 * postOffset)) { + THROW(0x6700); + } + } + else { + if (dataLength != (20 + 32 + 32 + 4 + 4 + 8 + 4 + 4 + 1 + 4 * bip32PathLength + + postOffset + (p1 == P1_STARK_CONDITIONAL_TRANSFER ? 32 + 20 : 0))) { + THROW(0x6700); + } + } if (p2 != 0) { THROW(0x6B00); } @@ -51,35 +72,63 @@ void handleStarkwareSignMessage(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uin offset += 4; } // Discard the path to use part of dataBuffer as a temporary buffer - os_memmove(dataBuffer, dataBuffer + offset, dataLength - offset); - // Fail immediately if the contract is unknown - if (!allzeroes(dataBuffer, 20) && getKnownToken(dataBuffer) == NULL) { - PRINTF("stark - cannot process unknown token %.*H", 20, dataBuffer); + memmove(dataBuffer, dataBuffer + offset, dataLength - offset); + dataContext.starkContext.conditional = (p1 == P1_STARK_CONDITIONAL_TRANSFER); + if (dataContext.starkContext.conditional) { + memmove(dataContext.starkContext.fact, dataBuffer + 20 + 32 + postOffset + 32 + 4 + 4 + 8 + 4 + 4, 32); + memmove(dataContext.starkContext.conditionAddress, dataBuffer + 20 + 32 + postOffset + 32 + 4 + 4 + 8 + 4 + 4 + 32, 20); + PRINTF("Fact %.*H\n", 32, dataContext.starkContext.fact); + PRINTF("Address %.*H\n", 20, dataContext.starkContext.conditionAddress); + } + + zeroTest = allzeroes(dataBuffer + preOffset, 20); + if (zeroTest && (protocol == 2) && (dataBuffer[0] != STARK_QUANTUM_ETH)) { + PRINTF("stark - unexpected quantum descriptor type for null first address %d\n", dataBuffer[0]); + THROW(0x6A80); + } + if (!zeroTest && getKnownToken(dataBuffer + preOffset) == NULL) { + PRINTF("stark - cannot process unknown token %.*H", 20, dataBuffer + preOffset); THROW(0x6A80); } - if ((p1 == P1_STARK_ORDER) && (!allzeroes(dataBuffer + 20 + 32, 20) && getKnownToken(dataBuffer + 20 + 32) == NULL)) { - PRINTF("stark - cannot process unknown token %.*H", 20, dataBuffer + 20 + 32); + if (order) { + zeroTest = allzeroes(dataBuffer + 20 + 32 + postOffset + preOffset, 20); + if (zeroTest && (protocol == 2) && (dataBuffer[1 + 20 + 32 + 32] != STARK_QUANTUM_ETH)) { + PRINTF("stark - unexpected quantum descriptor type for null second address %d\n", dataBuffer[1 + 20 + 32 + 32]); THROW(0x6A80); + } + if (!zeroTest && getKnownToken(dataBuffer + 20 + 32 + postOffset + preOffset) == NULL) { + PRINTF("stark - cannot process unknown token %.*H", 20, dataBuffer + 20 + 32 + postOffset + preOffset); + THROW(0x6A80); + } } // Prepare the Stark parameters - io_seproxyhal_io_heartbeat(); - compute_token_id(&global_sha3, dataBuffer, dataBuffer + 20, dataContext.starkContext.w1); - if (p1 == P1_STARK_ORDER) { + io_seproxyhal_io_heartbeat(); + compute_token_id(&global_sha3, dataBuffer + preOffset, + (protocol == 2 ? dataBuffer[0] : STARK_QUANTUM_LEGACY), + dataBuffer + preOffset + 20, + (protocol == 2 ? dataBuffer + 1 + 20 + 32 : NULL), false, dataContext.starkContext.w1); + if (order) { io_seproxyhal_io_heartbeat(); - compute_token_id(&global_sha3, dataBuffer + 20 + 32, dataBuffer + 20 + 32 + 20, dataContext.starkContext.w2); - offset = 20 + 32 + 20 + 32; + compute_token_id(&global_sha3, dataBuffer + 20 + 32 + postOffset + preOffset, + (protocol == 2 ? dataBuffer[1 + 20 + 32 + 32] : STARK_QUANTUM_LEGACY), + dataBuffer + 20 + 32 + postOffset + preOffset + 20, + (protocol == 2 ? dataBuffer + 1 + 20 + 32 + 32 + 1 + 20 + 32 : NULL), false, dataContext.starkContext.w2); + offset = 20 + 32 + postOffset + 20 + 32 + postOffset; } - else { - os_memmove(dataContext.starkContext.w2, dataBuffer + 20 + 32, 32); - offset = 20 + 32 + 32; + else { + memmove(dataContext.starkContext.w2, dataBuffer + 20 + 32 + postOffset, 32); + offset = 20 + 32 + postOffset + 32; } + poorstream_init(&bitstream, dataContext.starkContext.w3); poorstream_write_bits(&bitstream, 0, 11); // padding - poorstream_write_bits(&bitstream, (p1 == P1_STARK_ORDER ? STARK_ORDER_TYPE : STARK_TRANSFER_TYPE), 4); + poorstream_write_bits(&bitstream, + (p1 == P1_STARK_CONDITIONAL_TRANSFER ? STARK_CONDITIONAL_TRANSFER_TYPE : + order ? STARK_ORDER_TYPE : STARK_TRANSFER_TYPE), 4); poorstream_write_bits(&bitstream, U4BE(dataBuffer, offset), 31); poorstream_write_bits(&bitstream, U4BE(dataBuffer, offset + 4), 31); poorstream_write_bits(&bitstream, U8BE(dataBuffer, offset + 4 + 4), 63); - if (p1 == P1_STARK_ORDER) { + if (order) { poorstream_write_bits(&bitstream, U8BE(dataBuffer, offset + 4 + 4 + 8), 63); offset += 4 + 4 + 8 + 8; } @@ -93,16 +142,31 @@ void handleStarkwareSignMessage(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uin PRINTF("stark w1 %.*H\n", 32, dataContext.starkContext.w1); PRINTF("stark w2 %.*H\n", 32, dataContext.starkContext.w2); PRINTF("stark w3 %.*H\n", 32, dataContext.starkContext.w3); + + if (dataContext.starkContext.conditional) { + cx_keccak_init(&global_sha3, 256); + cx_hash((cx_hash_t*)&global_sha3, 0, dataContext.starkContext.conditionAddress, 20, NULL, 0); + cx_hash((cx_hash_t*)&global_sha3, CX_LAST, dataContext.starkContext.fact, 32, dataContext.starkContext.w4, 32); + dataContext.starkContext.w4[0] &= 0x03; + PRINTF("stark w4 %.*H\n", 32, dataContext.starkContext.w4); + } // Prepare the UI - if (p1 == P1_STARK_ORDER) { + if (order) { io_seproxyhal_io_heartbeat(); // amount to sell - stark_get_amount_string(dataBuffer, dataBuffer + 20, dataBuffer + 20 + 32 + 20 + 32 + 4 + 4, (char*)(dataBuffer + TMP_OFFSET), strings.common.fullAmount); + stark_get_amount_string(dataBuffer + preOffset, + dataBuffer + preOffset + 20, + dataBuffer + 20 + 32 + postOffset + 20 + 32 + postOffset + 4 + 4, + (char*)(dataBuffer + TMP_OFFSET), strings.common.fullAmount); io_seproxyhal_io_heartbeat(); // amount to buy - stark_get_amount_string(dataBuffer + 20 + 32, dataBuffer + 20 + 32 + 20, dataBuffer + 20 + 32 + 20 + 32 + 4 + 4 + 8, (char*)(dataBuffer + TMP_OFFSET), strings.common.maxFee); + stark_get_amount_string(dataBuffer + 20 + 32 + postOffset + preOffset, + dataBuffer + 20 + 32 + postOffset + preOffset + 20, + dataBuffer + 20 + 32 + postOffset + 20 + 32 + postOffset + 4 + 4 + 8, + (char*)(dataBuffer + TMP_OFFSET), strings.common.maxFee); // src vault ID - snprintf(strings.common.fullAddress, sizeof(strings.common.fullAddress), "%d", U4BE(dataBuffer, 20 + 32 + 20 + 32)); + snprintf(strings.common.fullAddress, sizeof(strings.common.fullAddress), "%d", + U4BE(dataBuffer, 20 + 32 + postOffset + 20 + 32 + postOffset)); } else { cx_ecfp_public_key_t publicKey; @@ -112,22 +176,37 @@ void handleStarkwareSignMessage(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uin cx_ecfp_init_private_key(CX_CURVE_Stark256, privateKeyData, 32, &privateKey); io_seproxyhal_io_heartbeat(); cx_ecfp_generate_pair(CX_CURVE_Stark256, &publicKey, &privateKey, 1); - os_memset(&privateKey, 0, sizeof(privateKey)); - os_memset(privateKeyData, 0, sizeof(privateKeyData)); + explicit_bzero(&privateKey, sizeof(privateKey)); + explicit_bzero(privateKeyData, sizeof(privateKeyData)); io_seproxyhal_io_heartbeat(); - selfTransfer = (os_memcmp(publicKey.W + 1, dataBuffer + 20 + 32, 32) == 0); + selfTransfer = (memcmp(publicKey.W + 1, dataBuffer + 20 + 32 + postOffset, 32) == 0); PRINTF("self transfer %d\n", selfTransfer); io_seproxyhal_io_heartbeat(); // amount to transfer - stark_get_amount_string(dataBuffer, dataBuffer + 20, dataBuffer + 20 + 32 + 32 + 4 + 4, (char*)(dataBuffer + TMP_OFFSET), tmpContent.tmp); + stark_get_amount_string(dataBuffer + preOffset, + dataBuffer + preOffset + 20, + dataBuffer + 20 + 32 + postOffset + 32 + 4 + 4, (char*)(dataBuffer + TMP_OFFSET), tmpContent.tmp); // dest vault ID - snprintf(strings.tmp.tmp2, sizeof(strings.tmp.tmp2), "%d", U4BE(dataBuffer, 20 + 32 + 32 + 4)); + snprintf(strings.tmp.tmp2, sizeof(strings.tmp.tmp2), "%d", + U4BE(dataBuffer, 20 + 32 + postOffset + 32 + 4)); if (!selfTransfer) { - snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataBuffer + 20 + 32); + memmove(dataContext.starkContext.transferDestination, dataBuffer + 20 + 32 + postOffset, 32); + snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataBuffer + 20 + 32 + postOffset); + } + } + if (order) { + ux_flow_init(0, ux_stark_limit_order_flow, NULL); + } + else { + if (selfTransfer) { + ux_flow_init(0, (dataContext.starkContext.conditional ? ux_stark_self_transfer_conditional_flow : + ux_stark_self_transfer_flow), NULL); + } + else { + ux_flow_init(0, (dataContext.starkContext.conditional ? ux_stark_transfer_conditional_flow : + ux_stark_transfer_flow), NULL); } } - ux_flow_init(0, p1 == P1_STARK_ORDER ? ux_stark_limit_order_flow : selfTransfer ? - ux_stark_self_transfer_flow : ux_stark_transfer_flow, NULL); *flags |= IO_ASYNCH_REPLY; } diff --git a/src_features/stark_sign/ui_common_stark_sign.c b/src_features/stark_sign/ui_common_stark_sign.c index d05e4e3..862b97b 100644 --- a/src_features/stark_sign/ui_common_stark_sign.c +++ b/src_features/stark_sign/ui_common_stark_sign.c @@ -11,8 +11,10 @@ unsigned int io_seproxyhal_touch_stark_ok(const bagl_element_t *e) { io_seproxyhal_io_heartbeat(); starkDerivePrivateKey(tmpCtx.transactionContext.bip32Path, tmpCtx.transactionContext.pathLength, privateKeyData); io_seproxyhal_io_heartbeat(); - stark_sign(signature, privateKeyData, dataContext.starkContext.w1, dataContext.starkContext.w2, dataContext.starkContext.w3); - G_io_apdu_buffer[0] = 0; + stark_sign(signature, privateKeyData, dataContext.starkContext.w1, dataContext.starkContext.w2, + dataContext.starkContext.w3, + (dataContext.starkContext.conditional ? dataContext.starkContext.w4 : NULL)); + G_io_apdu_buffer[0] = 0; format_signature_out(signature); tx = 65; G_io_apdu_buffer[tx++] = 0x90; diff --git a/src_features/stark_sign/ui_flow_stark_sign.c b/src_features/stark_sign/ui_flow_stark_sign.c index 287b151..550d31c 100644 --- a/src_features/stark_sign/ui_flow_stark_sign.c +++ b/src_features/stark_sign/ui_flow_stark_sign.c @@ -5,6 +5,21 @@ unsigned int io_seproxyhal_touch_stark_ok(const bagl_element_t *e); +void stark_sign_display_master_account() { + snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.transferDestination); +} + +void stark_sign_display_condition_address() { + strings.tmp.tmp[0] = '0'; + strings.tmp.tmp[1] = 'x'; + getEthAddressStringFromBinary(dataContext.starkContext.conditionAddress, (uint8_t*)(strings.tmp.tmp + 2), &global_sha3, chainConfig); + strings.tmp.tmp[42] = '\0'; +} + +void stark_sign_display_condition_fact() { + snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.fact); +} + UX_STEP_NOCB(ux_stark_limit_order_1_step, pnn, { @@ -44,7 +59,7 @@ UX_STEP_NOCB(ux_stark_limit_order_5_step, UX_STEP_NOCB(ux_stark_limit_order_6_step, bnnn_paging, { - .title = "Token Accont", + .title = "Token Account", .text = strings.common.fullAddress }); @@ -100,6 +115,19 @@ UX_STEP_NOCB(ux_stark_self_transfer_2_step, .text = "Transfer" }); +UX_STEP_NOCB(ux_stark_conditional_transfer_2_step, + bnnn_paging, + { + .title = "Conditional", + .text = "Transfer" + }); + +UX_STEP_NOCB(ux_stark_self_conditional_transfer_2_step, + bnnn_paging, + { + .title = "Conditional", + .text = "Self Transfer" + }); UX_STEP_NOCB(ux_stark_transfer_3_step, bnnn_paging, @@ -118,7 +146,7 @@ UX_STEP_NOCB(ux_stark_transfer_4_step, UX_STEP_NOCB(ux_stark_transfer_5_step, bnnn_paging, { - .title = "Token Accont", + .title = "Token Account", .text = strings.tmp.tmp2 }); @@ -140,6 +168,33 @@ UX_STEP_CB( "Reject", }); +UX_STEP_NOCB_INIT( + ux_stark_conditional_transfer_4_step, + bnnn_paging, + stark_sign_display_master_account(), + { + .title = "Master Account", + .text = strings.tmp.tmp + }); + +UX_STEP_NOCB_INIT( + ux_stark_conditional_transfer_8_step, + bnnn_paging, + stark_sign_display_condition_address(), + { + .title = "Cond. Address", + .text = strings.tmp.tmp + }); + +UX_STEP_NOCB_INIT( + ux_stark_conditional_transfer_9_step, + bnnn_paging, + stark_sign_display_condition_fact(), + { + .title = "Cond. Fact", + .text = strings.tmp.tmp + }); + UX_FLOW(ux_stark_transfer_flow, &ux_stark_transfer_1_step, &ux_stark_transfer_2_step, @@ -159,4 +214,27 @@ UX_FLOW(ux_stark_self_transfer_flow, &ux_stark_transfer_7_step ); +UX_FLOW(ux_stark_transfer_conditional_flow, + &ux_stark_transfer_1_step, + &ux_stark_conditional_transfer_2_step, + &ux_stark_transfer_3_step, + &ux_stark_conditional_transfer_4_step, + &ux_stark_transfer_5_step, + &ux_stark_conditional_transfer_8_step, + &ux_stark_conditional_transfer_9_step, + &ux_stark_transfer_6_step, + &ux_stark_transfer_7_step +); + +UX_FLOW(ux_stark_self_transfer_conditional_flow, + &ux_stark_transfer_1_step, + &ux_stark_self_conditional_transfer_2_step, + &ux_stark_transfer_3_step, + &ux_stark_transfer_5_step, + &ux_stark_conditional_transfer_8_step, + &ux_stark_conditional_transfer_9_step, + &ux_stark_transfer_6_step, + &ux_stark_transfer_7_step +); + #endif diff --git a/src_features/stark_unsafe_sign/cmd_stark_unsafe_sign.c b/src_features/stark_unsafe_sign/cmd_stark_unsafe_sign.c new file mode 100644 index 0000000..89e2b85 --- /dev/null +++ b/src_features/stark_unsafe_sign/cmd_stark_unsafe_sign.c @@ -0,0 +1,54 @@ +#ifdef HAVE_STARKWARE + +#include "shared_context.h" +#include "apdu_constants.h" +#include "stark_utils.h" +#include "ui_flow.h" +#include "ui_callbacks.h" + +void handleStarkwareUnsafeSign(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) { + uint32_t i; + uint8_t privateKeyData[32]; + cx_ecfp_public_key_t publicKey; + cx_ecfp_private_key_t privateKey; + uint8_t bip32PathLength = *(dataBuffer); + uint8_t offset = 1; + // Initial checks + if (appState != APP_STATE_IDLE) { + reset_app_context(); + } + if ((bip32PathLength < 0x01) || + (bip32PathLength > MAX_BIP32_PATH)) { + PRINTF("Invalid path\n"); + THROW(0x6a80); + } + if ((p1 != 0) || (p2 != 0)) { + THROW(0x6B00); + } + + if (dataLength != 32 + 4 * bip32PathLength + 1) { + THROW(0x6700); + } + + tmpCtx.transactionContext.pathLength = bip32PathLength; + for (i = 0; i < bip32PathLength; i++) { + tmpCtx.transactionContext.bip32Path[i] = U4BE(dataBuffer, offset); + PRINTF("Storing path %d %d\n", i, tmpCtx.transactionContext.bip32Path[i]); + offset += 4; + } + memmove(dataContext.starkContext.w2, dataBuffer + offset, 32); + io_seproxyhal_io_heartbeat(); + starkDerivePrivateKey(tmpCtx.transactionContext.bip32Path, bip32PathLength, privateKeyData); + cx_ecfp_init_private_key(CX_CURVE_Stark256, privateKeyData, 32, &privateKey); + io_seproxyhal_io_heartbeat(); + cx_ecfp_generate_pair(CX_CURVE_Stark256, &publicKey, &privateKey, 1); + explicit_bzero(&privateKey, sizeof(privateKey)); + explicit_bzero(privateKeyData, sizeof(privateKeyData)); + io_seproxyhal_io_heartbeat(); + memmove(dataContext.starkContext.w1, publicKey.W + 1, 32); + ux_flow_init(0, ux_stark_unsafe_sign_flow, NULL); + + *flags |= IO_ASYNCH_REPLY; +} + +#endif diff --git a/src_features/stark_unsafe_sign/ui_common_stark_unsafe_sign.c b/src_features/stark_unsafe_sign/ui_common_stark_unsafe_sign.c new file mode 100644 index 0000000..0484d6d --- /dev/null +++ b/src_features/stark_unsafe_sign/ui_common_stark_unsafe_sign.c @@ -0,0 +1,32 @@ +#ifdef HAVE_STARKWARE + +#include "shared_context.h" +#include "stark_utils.h" +#include "ui_callbacks.h" + +unsigned int io_seproxyhal_touch_stark_unsafe_sign_ok(const bagl_element_t *e) { + cx_ecfp_private_key_t privateKey; + uint8_t privateKeyData[32]; + uint8_t signature[72]; + unsigned int info = 0; + uint32_t tx = 0; + io_seproxyhal_io_heartbeat(); + starkDerivePrivateKey(tmpCtx.transactionContext.bip32Path, tmpCtx.transactionContext.pathLength, privateKeyData); + io_seproxyhal_io_heartbeat(); + cx_ecfp_init_private_key(CX_CURVE_Stark256, privateKeyData, 32, &privateKey); + cx_ecdsa_sign(&privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256, + dataContext.starkContext.w2, sizeof(dataContext.starkContext.w2), signature, sizeof(signature), &info); + G_io_apdu_buffer[0] = 0; + format_signature_out(signature); + 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); + // Display back the original UX + ui_idle(); + return 0; // do not redraw the widget +} + +#endif diff --git a/src_features/stark_unsafe_sign/ui_flow_stark_unsafe_sign.c b/src_features/stark_unsafe_sign/ui_flow_stark_unsafe_sign.c new file mode 100644 index 0000000..14448ee --- /dev/null +++ b/src_features/stark_unsafe_sign/ui_flow_stark_unsafe_sign.c @@ -0,0 +1,69 @@ +#ifdef HAVE_STARKWARE + +#include "shared_context.h" +#include "ui_callbacks.h" + +unsigned int io_seproxyhal_touch_stark_unsafe_sign_ok(const bagl_element_t *e); + +void stark_unsafe_sign_display_account() { + snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.w1); +} + +void stark_unsafe_sign_display_hash() { + snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.w2); +} + +UX_STEP_NOCB(ux_stark_unsafe_sign_1_step, + pnn, + { + &C_icon_warning, + "Unsafe", + "Stark Sign", + }); + +UX_STEP_NOCB_INIT( + ux_stark_unsafe_sign_2_step, + bnnn_paging, + stark_unsafe_sign_display_account(), + { + .title = "From Account", + .text = strings.tmp.tmp + }); + +UX_STEP_NOCB_INIT( + ux_stark_unsafe_sign_3_step, + bnnn_paging, + stark_unsafe_sign_display_hash(), + { + .title = "Hash", + .text = strings.tmp.tmp + }); + + +UX_STEP_CB( + ux_stark_unsafe_sign_4_step, + pbb, + io_seproxyhal_touch_stark_unsafe_sign_ok(NULL), + { + &C_icon_validate_14, + "Accept", + "and send", + }); +UX_STEP_CB( + ux_stark_unsafe_sign_5_step, + pb, + io_seproxyhal_touch_tx_cancel(NULL), + { + &C_icon_crossmark, + "Reject", + }); + +UX_FLOW(ux_stark_unsafe_sign_flow, + &ux_stark_unsafe_sign_1_step, + &ux_stark_unsafe_sign_2_step, + &ux_stark_unsafe_sign_3_step, + &ux_stark_unsafe_sign_4_step, + &ux_stark_unsafe_sign_5_step +); + +#endif diff --git a/src_plugins/erc20/erc20_plugin.c b/src_plugins/erc20/erc20_plugin.c index c3b6f1c..201892b 100644 --- a/src_plugins/erc20/erc20_plugin.c +++ b/src_plugins/erc20/erc20_plugin.c @@ -55,6 +55,21 @@ bool check_token_binding(char* ticker1, char* ticker2, const ticker_binding_t* b return false; } +bool erc20_plugin_available_check() { + if (quantumSet) { + switch(dataContext.tokenContext.quantumType) { + case STARK_QUANTUM_LEGACY: + case STARK_QUANTUM_ETH: + case STARK_QUANTUM_ERC20: + case STARK_QUANTUM_MINTABLE_ERC20: + return true; + default: + return false; + } + } + return true; +} + void erc20_plugin_call(int message, void *parameters) { switch(message) { diff --git a/src_plugins/erc721/erc721_plugin.c b/src_plugins/erc721/erc721_plugin.c new file mode 100644 index 0000000..d440b83 --- /dev/null +++ b/src_plugins/erc721/erc721_plugin.c @@ -0,0 +1,146 @@ +#include +#include "eth_plugin_internal.h" +#include "eth_plugin_handler.h" +#include "shared_context.h" +#include "ethUtils.h" +#include "utils.h" + +void starkware_print_stark_key(uint8_t *starkKey, char *destination); +void starkware_print_eth_address(uint8_t *address, char *destination); + +typedef struct erc721_parameters_t { + uint8_t selectorIndex; + uint8_t address[20]; + uint8_t tokenId[32]; + //tokenDefinition_t *tokenSelf; + //tokenDefinition_t *tokenAddress; +} erc721_parameters_t; + +bool erc721_plugin_available_check() { + if (quantumSet) { + switch(dataContext.tokenContext.quantumType) { + case STARK_QUANTUM_ERC721: + case STARK_QUANTUM_MINTABLE_ERC721: + return true; + default: + return false; + } + } + return false; +} + +void erc721_plugin_call(int message, void *parameters) { + + switch(message) { + case ETH_PLUGIN_INIT_CONTRACT: { + ethPluginInitContract_t *msg = (ethPluginInitContract_t*)parameters; + erc721_parameters_t *context = (erc721_parameters_t*)msg->pluginContext; + // enforce that ETH amount should be 0 + if (!allzeroes(msg->pluginSharedRO->txContent->value.value, 32)){ + PRINTF("Err: Transaction amount is not 0 for erc721 approval\n"); + msg->result = ETH_PLUGIN_RESULT_ERROR; + } + else { + size_t i; + for (i=0; iselector, SELECTOR_SIZE) == 0) { + context->selectorIndex = i; + break; + } + } + if (i == NUM_ERC721_SELECTORS) { + PRINTF("Unknown erc721 selector %.*H\n", SELECTOR_SIZE, msg->selector); + break; + } + if (msg->dataSize != 4 + 32 + 32) { + PRINTF("Invalid erc721 approval data size %d\n", msg->dataSize); + break; + } + PRINTF("erc721 plugin init\n"); + msg->result = ETH_PLUGIN_RESULT_OK; + } + } + break; + + case ETH_PLUGIN_PROVIDE_PARAMETER : { + ethPluginProvideParameter_t *msg = (ethPluginProvideParameter_t*)parameters; + erc721_parameters_t *context = (erc721_parameters_t*)msg->pluginContext; + PRINTF("erc721 plugin provide parameter %d %.*H\n", msg->parameterOffset, 32, msg->parameter); + switch(msg->parameterOffset) { + case 4: + memmove(context->address, msg->parameter + 32 - 20, 20); + msg->result = ETH_PLUGIN_RESULT_OK; + break; + case 4 + 32: + memmove(context->tokenId, msg->parameter, 32); + msg->result = ETH_PLUGIN_RESULT_OK; + break; + default: + PRINTF("Unhandled parameter offset\n"); + break; + } + } + break; + + case ETH_PLUGIN_FINALIZE: { + ethPluginFinalize_t *msg = (ethPluginFinalize_t*)parameters; + erc721_parameters_t *context = (erc721_parameters_t*)msg->pluginContext; + PRINTF("erc721 plugin finalize\n"); + msg->tokenLookup1 = msg->pluginSharedRO->txContent->destination; + msg->tokenLookup2 = context->address; + msg->numScreens = 3; + msg->uiType = ETH_UI_TYPE_GENERIC; + msg->result = ETH_PLUGIN_RESULT_OK; + } + break; + + case ETH_PLUGIN_PROVIDE_TOKEN: { + ethPluginProvideToken_t *msg = (ethPluginProvideToken_t*)parameters; + erc721_parameters_t *context = (erc721_parameters_t*)msg->pluginContext; + PRINTF("erc721 plugin provide token dest: %d - address: %d\n", (msg->token1 != NULL), (msg->token2 != NULL)); + //context->tokenSelf = msg->token1; + //context->tokenAddress = msg->token2; + msg->result = ETH_PLUGIN_RESULT_OK; + } + break; + + case ETH_PLUGIN_QUERY_CONTRACT_ID: { + ethQueryContractID_t *msg = (ethQueryContractID_t*)parameters; + strcpy(msg->name, "Allowance"); + strcpy(msg->version, ""); + msg->result = ETH_PLUGIN_RESULT_OK; + } + break; + + case ETH_PLUGIN_QUERY_CONTRACT_UI: { + ethQueryContractUI_t *msg = (ethQueryContractUI_t*)parameters; + erc721_parameters_t *context = (erc721_parameters_t*)msg->pluginContext; + switch(msg->screenIndex) { + case 0: + strcpy(msg->title, "Contract Name"); + starkware_print_eth_address(tmpContent.txContent.destination, msg->msg); + msg->result = ETH_PLUGIN_RESULT_OK; + break; + + case 1: + strcpy(msg->title, "NFT Contract"); + starkware_print_eth_address(context->address, msg->msg); + msg->result = ETH_PLUGIN_RESULT_OK; + break; + + case 2: + strcpy(msg->title, "TokenID"); + starkware_print_stark_key(context->tokenId, msg->msg); + msg->result = ETH_PLUGIN_RESULT_OK; + break; + + default: + break; + } + } + break; + + default: + PRINTF("Unhandled message %d\n", message); + } +} diff --git a/src_plugins/starkware/starkware_plugin.c b/src_plugins/starkware/starkware_plugin.c index a658823..e248bbe 100644 --- a/src_plugins/starkware/starkware_plugin.c +++ b/src_plugins/starkware/starkware_plugin.c @@ -16,33 +16,64 @@ typedef enum { STARKWARE_FULL_WITHDRAW, STARKWARE_FREEZE, STARKWARE_ESCAPE, - STARKWARE_VERIFY_ESCAPE - + STARKWARE_VERIFY_ESCAPE, + STARKWARE_WITHDRAW_TO, + STARKWARE_DEPOSIT_NFT, + STARKWARE_DEPOSIT_NFT_RECLAIM, + STARKWARE_WITHDRAW_AND_MINT, + STARKWARE_WITHDRAW_NFT, + STARKWARE_WITHDRAW_NFT_TO } starkwareSelector_t; -// register : starkkey (32), drop param 2 +#ifndef HAVE_TOKENS_EXTRA_LIST + +static const uint8_t DEVERSIFI_CONTRACT[] = { + 0x01, + 0x5d,0x22,0x04,0x5d,0xac,0xea,0xb0,0x3b,0x15,0x80,0x31,0xec,0xb7,0xd9,0xd0,0x6f,0xad,0x24,0x60,0x9b +}; + +#else + +static const uint8_t DEVERSIFI_CONTRACT[] = { + 0x02, + 0xe7,0x3a,0x39,0x4a,0xde,0x4d,0x94,0xa0,0x73,0x50,0x2d,0xa8,0x70,0x3e,0xa2,0x34,0x90,0xdc,0x7b,0x6a, + 0x69,0xC6,0x39,0x2E,0xb0,0x2a,0x28,0x82,0x31,0x41,0x34,0xc9,0x8D,0xDC,0xBF,0x73,0xB7,0xAd,0xBa,0xb1 +}; + +#endif + +// register : address (20), stark key (32), drop param 3 // Registration // Contract Name // From ETH address // Master account -// deposit token : verify tokenId (32), vaultId (4), quantized Amount (32) +// deposit token : stark key (32), verify assetType (32), vaultId (4), quantized Amount (32) // Deposit // Contract Name + // Master Account // Token Account // Amount -// deposit : verify tokenId (32), vaultId (4) +// deposit : stark key (32), verify assetType (32), vaultId (4) // Flow similar to deposit -// deposit cancel, deposit reclaim : tokenId (32) ignored, vaultId(4) -// full withdrawal, freeze : vaultId (4) +// deposit cancel, deposit reclaim : stark key (32), assetType (reclaim) / assetId (cancel) (32) ignored, vaultId(4) +// full withdrawal, freeze : stark key (32), vaultId (4) // Cancel Deposit | Reclaim Deposit | Full Withdrawal | Freeze // Contract Name + // Master Account // Token Account -// withdrawal : verify tokenId (32) +// withdrawal : stark key (32), verify assetType (32) // Withdrawal // Contract Name + // Master Account // To Eth Address // Token Symbol -// escape : starkkey (32), vaultId (4), verify tokenId (32), quantized Amount (32) +// withdrawal to : stark key (32), verify assetType (32), address (20) + // Withdrawal To + // Contract Name + // Master Account + // To Eth Address + // Token Symbol +// escape : stark key (32), vaultId (4), verify assetType (32), quantized Amount (32) // Escape // Contract Name // Amount @@ -51,31 +82,77 @@ typedef enum { // verify escape : escapeProof (ignore) // Verify Escape // Contract Name +// deposit NFT : stark key (32), verify assetType (32), vault id (4), token id (32) + // Deposit + // Contract Name + // Master Account + // Token Account + // NFT Contract + // Token ID +// deposit NFT reclaim : stark key (32), verify assetType (32), vault id (4), token id (32) + // Reclaim Deposit + // Contract Name + // Master Account + // Token Account + // NFT Contract + // Token ID +// withdraw and mint : stark key (32), verify assetType (32), mintable blob (ignored variable) + // Withdrawal + // Contract Name + // Master Account + // Asset Contract +// withdraw NFT : stark key (32), verify assetType (32), token id (32) + // Withdrawal + // Contract Name + // Master Account + // To Eth Address + // NFT Contract + // Token ID +// withdraw NFT To : stark key (32), verify assetType (32), token id (32), address (20) + // Withdrawal To + // Contract Name + // Master Account + // To Eth Address + // NFT Contract + // Token ID + static const uint8_t STARKWARE_EXPECTED_DATA_SIZE[] = { - 4 + 32, + 0, + 4 + 32 + 32 + 32 + 32, + 4 + 32 + 32 + 32, + 4 + 32 + 32 + 32, 4 + 32 + 32 + 32, 4 + 32 + 32, 4 + 32 + 32, 4 + 32 + 32, - 4 + 32, - 4 + 32, - 4 + 32, 4 + 32 + 32 + 32 + 32, - 0 + 0, + 4 + 32 + 32 + 32, + 4 + 32 + 32 + 32 + 32, + 4 + 32 + 32 + 32 + 32, + 0, + 4 + 32 + 32 + 32, + 4 + 32 + 32 + 32 + 32 }; static const uint8_t STARKWARE_NUM_SCREENS[] = { 4 - 1, - 4 - 1, - 4 - 1, - 3 - 1, - 3 - 1, - 4 - 1, - 3 - 1, - 3 - 1, 5 - 1, - 2 - 1 + 5 - 1, + 4 - 1, + 4 - 1, + 5 - 1, + 4 - 1, + 4 - 1, + 5 - 1, + 2 - 1, + 5 - 1, + 6 - 1, + 6 - 1, + 4 - 1, + 6 - 1, + 6 - 1 }; typedef struct starkware_parameters_t { @@ -88,8 +165,22 @@ typedef struct starkware_parameters_t { } starkware_parameters_t; +bool is_deversify_contract(const uint8_t *address) { + uint32_t offset = 0; + uint8_t size = DEVERSIFI_CONTRACT[0]; + uint8_t i; + + for (i=0; iaddress : NULL), - dataContext.tokenContext.quantum, tmp32); + dataContext.tokenContext.quantumType, + dataContext.tokenContext.quantum, + dataContext.tokenContext.mintingBlob, assetTypeOnly, tmp32); if (memcmp(tokenId, tmp32, 32) != 0) { PRINTF("Token ID not matching - computed %.*H\n", 32, tmp32); PRINTF("Current quantum %.*H\n", 32, dataContext.tokenContext.quantum); @@ -114,6 +207,27 @@ bool starkware_verify_token_id(uint8_t *tmp32, uint8_t *tokenId) { return true; } +bool starkware_verify_nft_token_id(uint8_t *tokenId) { + if (!quantumSet) { + PRINTF("Quantum not set\n"); + return false; + } + switch(dataContext.tokenContext.quantumType) { + case STARK_QUANTUM_ERC721: + case STARK_QUANTUM_MINTABLE_ERC721: + break; + default: + PRINTF("Unexpected quantum type for NFT token id check %d\n", dataContext.tokenContext.quantumType); + return false; + } + if (memcmp(dataContext.tokenContext.quantum, tokenId, 32) != 0) { + PRINTF("Token ID not matching - expected %.*H\n", 32, dataContext.tokenContext.quantum); + PRINTF("Current token ID %.*H\n", 32, tokenId); + return false; + } + return true; +} + void starkware_print_vault_id(uint32_t vaultId, char *destination) { snprintf(destination, 10, "%d", vaultId); } @@ -139,7 +253,7 @@ void starkware_print_amount(uint8_t *amountData, char *destination, bool forEsca if ((amountData == NULL) || (forEscape && (dataContext.tokenContext.quantumIndex == MAX_TOKEN))) { decimals = WEI_TO_ETHER; if (!forEscape) { - convertUint256BE(tmpContent.txContent.value.value, tmpContent.txContent.value.length, &amountPre); + convertUint256BE(tmpContent.txContent.value.value, tmpContent.txContent.value.length, &amount); } else { readu256BE(amountData, &amountPre); @@ -151,8 +265,10 @@ void starkware_print_amount(uint8_t *amountData, char *destination, bool forEsca ticker = (char*)token->ticker; readu256BE(amountData, &amountPre); } - readu256BE(dataContext.tokenContext.quantum, &quantum); - mul256(&amountPre, &quantum, &amount); + if (amountData != NULL) { + readu256BE(dataContext.tokenContext.quantum, &quantum); + mul256(&amountPre, &quantum, &amount); + } tostring256(&amount, 10, (char*)(G_io_apdu_buffer + 100), 100); strcpy(destination, ticker); adjustDecimals((char*)(G_io_apdu_buffer + 100), strlen((char*)(G_io_apdu_buffer + 100)), destination + strlen(ticker), 50 - strlen(ticker), decimals); @@ -169,6 +285,18 @@ void starkware_print_ticker(char *destination) { strcpy(destination, ticker); } +// TODO : rewrite as independant code +void starkware_print_asset_contract(char *destination) { + // token has been validated to be present previously + if (dataContext.tokenContext.quantumIndex != MAX_TOKEN) { + tokenDefinition_t *token = &tmpCtx.transactionContext.tokens[dataContext.tokenContext.quantumIndex]; + starkware_print_eth_address(token->address, destination); + } + else { + strcpy(destination, "UNKNOWN"); + } +} + // TODO : rewrite as independant code void starkware_get_source_address(char *destination) { uint8_t privateKeyData[32]; @@ -180,8 +308,8 @@ void starkware_get_source_address(char *destination) { cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey); io_seproxyhal_io_heartbeat(); cx_ecfp_generate_pair(CX_CURVE_256K1, &publicKey, &privateKey, 1); - os_memset(&privateKey, 0, sizeof(privateKey)); - os_memset(privateKeyData, 0, sizeof(privateKeyData)); + explicit_bzero(&privateKey, sizeof(privateKey)); + explicit_bzero(privateKeyData, sizeof(privateKeyData)); io_seproxyhal_io_heartbeat(); destination[0] = '0'; destination[1] = 'x'; @@ -229,75 +357,134 @@ void starkware_plugin_call(int message, void *parameters) { break; } switch(msg->parameterOffset) { + case 4: switch(context->selectorIndex) { case STARKWARE_REGISTER: - case STARKWARE_ESCAPE: - memmove(context->starkKey, msg->parameter, 32); + memmove(context->amount, msg->parameter + 32 - 20, 20); break; + + case STARKWARE_DEPOSIT_TOKEN: + case STARKWARE_DEPOSIT_ETH: case STARKWARE_DEPOSIT_CANCEL: case STARKWARE_DEPOSIT_RECLAIM: - break; + case STARKWARE_WITHDRAW: case STARKWARE_FULL_WITHDRAW: case STARKWARE_FREEZE: - memmove(context->vaultId, msg->parameter + 32 - 4, 4); - break; - case STARKWARE_DEPOSIT_ETH: - case STARKWARE_DEPOSIT_TOKEN: - case STARKWARE_WITHDRAW: - context->validToken = starkware_verify_token_id(context->amount, msg->parameter); - break; - default: - break; - } - msg->result = ETH_PLUGIN_RESULT_OK; - break; - - case 4 + 32: - switch(context->selectorIndex) { - case STARKWARE_DEPOSIT_CANCEL: - case STARKWARE_DEPOSIT_RECLAIM: - case STARKWARE_DEPOSIT_ETH: - case STARKWARE_DEPOSIT_TOKEN: - case STARKWARE_ESCAPE: - memmove(context->vaultId, msg->parameter + 32 - 4, 4); - break; - default: - break; - } - msg->result = ETH_PLUGIN_RESULT_OK; - break; - - case 4 + 32 + 32: - switch(context->selectorIndex) { - case STARKWARE_DEPOSIT_TOKEN: - memmove(context->amount, msg->parameter, 32); - break; case STARKWARE_ESCAPE: - context->validToken = starkware_verify_token_id(context->amount, msg->parameter); - break; + case STARKWARE_WITHDRAW_TO: + case STARKWARE_DEPOSIT_NFT: + case STARKWARE_DEPOSIT_NFT_RECLAIM: + case STARKWARE_WITHDRAW_AND_MINT: + case STARKWARE_WITHDRAW_NFT: + case STARKWARE_WITHDRAW_NFT_TO: + memmove(context->starkKey, msg->parameter, 32); + break; + default: break; } msg->result = ETH_PLUGIN_RESULT_OK; break; - case 4 + 32 + 32 + 32: - switch(context->selectorIndex) { - case STARKWARE_ESCAPE: - memmove(context->amount, msg->parameter, 32); - break; - default: - break; - } - msg->result = ETH_PLUGIN_RESULT_OK; - break; + case 4 + 32: + switch(context->selectorIndex) { + case STARKWARE_REGISTER: + memmove(context->starkKey, msg->parameter, 32); + break; + + case STARKWARE_ESCAPE: + memmove(context->vaultId, msg->parameter + 32 - 4, 4); + break; + + case STARKWARE_DEPOSIT_CANCEL: + case STARKWARE_DEPOSIT_RECLAIM: + break; + + case STARKWARE_FULL_WITHDRAW: + case STARKWARE_FREEZE: + memmove(context->vaultId, msg->parameter + 32 - 4, 4); + break; + + case STARKWARE_DEPOSIT_ETH: + case STARKWARE_DEPOSIT_TOKEN: + case STARKWARE_WITHDRAW: + case STARKWARE_WITHDRAW_TO: + case STARKWARE_DEPOSIT_NFT: + case STARKWARE_DEPOSIT_NFT_RECLAIM: + case STARKWARE_WITHDRAW_AND_MINT: + case STARKWARE_WITHDRAW_NFT: + case STARKWARE_WITHDRAW_NFT_TO: + context->validToken = starkware_verify_asset_id(context->amount, msg->parameter, true); + break; + + default: + break; + } + msg->result = ETH_PLUGIN_RESULT_OK; + break; + + case 4 + 32 + 32: + switch(context->selectorIndex) { + + case STARKWARE_ESCAPE: + context->validToken = starkware_verify_asset_id(context->amount, msg->parameter, true); + break; + + case STARKWARE_DEPOSIT_CANCEL: + case STARKWARE_DEPOSIT_RECLAIM: + case STARKWARE_DEPOSIT_ETH: + case STARKWARE_DEPOSIT_TOKEN: + case STARKWARE_DEPOSIT_NFT: + case STARKWARE_DEPOSIT_NFT_RECLAIM: + memmove(context->vaultId, msg->parameter + 32 - 4, 4); + break; + + case STARKWARE_WITHDRAW_TO: + memmove(context->amount, msg->parameter + 32 - 20, 20); + break; + + case STARKWARE_WITHDRAW_NFT: + case STARKWARE_WITHDRAW_NFT_TO: + context->validToken = starkware_verify_nft_token_id(msg->parameter); + break; + + default: + break; + } + msg->result = ETH_PLUGIN_RESULT_OK; + break; + + case 4 + 32 + 32 + 32: + switch(context->selectorIndex) { + + case STARKWARE_ESCAPE: + case STARKWARE_DEPOSIT_TOKEN: + memmove(context->amount, msg->parameter, 32); + break; + + case STARKWARE_WITHDRAW_NFT_TO: + memmove(context->amount, msg->parameter + 32 - 20, 20); + break; + + case STARKWARE_DEPOSIT_NFT: + case STARKWARE_DEPOSIT_NFT_RECLAIM: + context->validToken = starkware_verify_nft_token_id(msg->parameter); + break; + + default: + break; + } + msg->result = ETH_PLUGIN_RESULT_OK; + break; default: switch(context->selectorIndex) { + case STARKWARE_REGISTER: case STARKWARE_VERIFY_ESCAPE: - msg->result = ETH_PLUGIN_RESULT_OK; + msg->result = ETH_PLUGIN_RESULT_OK; break; + default: PRINTF("Unhandled parameter offset\n"); break; @@ -331,15 +518,19 @@ void starkware_plugin_call(int message, void *parameters) { break; case STARKWARE_DEPOSIT_TOKEN: case STARKWARE_DEPOSIT_ETH: + case STARKWARE_DEPOSIT_NFT: strcpy(msg->name, "Deposit"); break; case STARKWARE_DEPOSIT_CANCEL: strcpy(msg->name, "Cancel Deposit"); break; case STARKWARE_DEPOSIT_RECLAIM: + case STARKWARE_DEPOSIT_NFT_RECLAIM: strcpy(msg->name, "Reclaim Deposit"); break; case STARKWARE_WITHDRAW: + case STARKWARE_WITHDRAW_NFT: + case STARKWARE_WITHDRAW_AND_MINT: strcpy(msg->name, "Withdrawal"); break; case STARKWARE_FULL_WITHDRAW: @@ -354,10 +545,15 @@ void starkware_plugin_call(int message, void *parameters) { case STARKWARE_VERIFY_ESCAPE: strcpy(msg->name, "Verify Escape"); break; + case STARKWARE_WITHDRAW_TO: + case STARKWARE_WITHDRAW_NFT_TO: + strcpy(msg->name, "Withdrawal To"); + break; + default: break; } - strcpy(msg->version, "Starkware"); + strcpy(msg->version, is_deversify_contract(tmpContent.txContent.destination) ? "DeversiFi" : "Starkware"); msg->result = ETH_PLUGIN_RESULT_OK; } break; @@ -368,47 +564,93 @@ void starkware_plugin_call(int message, void *parameters) { switch(msg->screenIndex) { case 0: strcpy(msg->title, "Contract Name"); - starkware_print_eth_address(tmpContent.txContent.destination, msg->msg); + if (is_deversify_contract(tmpContent.txContent.destination)) { + strcpy(msg->msg, "DeversiFi"); + } + else { + starkware_print_eth_address(tmpContent.txContent.destination, msg->msg); + } msg->result = ETH_PLUGIN_RESULT_OK; break; - case 1: switch(context->selectorIndex) { - case STARKWARE_REGISTER: - strcpy(msg->title, "From ETH Address"); - starkware_get_source_address(msg->msg); - break; + case STARKWARE_REGISTER: + strcpy(msg->title, "From ETH Address"); + starkware_print_eth_address(context->amount, msg->msg); + break; + case STARKWARE_ESCAPE: + strcpy(msg->title, "Amount"); + starkware_print_amount(context->amount, msg->msg, true); + break; + case STARKWARE_DEPOSIT_TOKEN: + case STARKWARE_DEPOSIT_ETH: + case STARKWARE_DEPOSIT_CANCEL: + case STARKWARE_DEPOSIT_RECLAIM: + case STARKWARE_WITHDRAW: + case STARKWARE_FULL_WITHDRAW: + case STARKWARE_FREEZE: + case STARKWARE_VERIFY_ESCAPE: + case STARKWARE_WITHDRAW_TO: + case STARKWARE_DEPOSIT_NFT: + case STARKWARE_DEPOSIT_NFT_RECLAIM: + case STARKWARE_WITHDRAW_AND_MINT: + case STARKWARE_WITHDRAW_NFT: + case STARKWARE_WITHDRAW_NFT_TO: + strcpy(msg->title, "Master Account"); + starkware_print_stark_key(context->starkKey, msg->msg); + break; + default: + PRINTF("Unexpected screen %d for %d\n", msg->screenIndex, context->selectorIndex); + break; + } + msg->result = ETH_PLUGIN_RESULT_OK; + break; + case 2: + switch(context->selectorIndex) { + case STARKWARE_REGISTER: + case STARKWARE_ESCAPE: + strcpy(msg->title, "Master Account"); + starkware_print_stark_key(context->starkKey, msg->msg); + break; + case STARKWARE_DEPOSIT_TOKEN: case STARKWARE_DEPOSIT_ETH: case STARKWARE_DEPOSIT_CANCEL: case STARKWARE_DEPOSIT_RECLAIM: case STARKWARE_FULL_WITHDRAW: case STARKWARE_FREEZE: + case STARKWARE_DEPOSIT_NFT: + case STARKWARE_DEPOSIT_NFT_RECLAIM: strcpy(msg->title, "Token Account"); starkware_print_vault_id(U4BE(context->vaultId, 0), msg->msg); break; case STARKWARE_WITHDRAW: + case STARKWARE_WITHDRAW_NFT: strcpy(msg->title, "To ETH Address"); starkware_get_source_address(msg->msg); break; - case STARKWARE_ESCAPE: - strcpy(msg->title, "Amount"); - starkware_print_amount(context->amount, msg->msg, true); + case STARKWARE_WITHDRAW_TO: + case STARKWARE_WITHDRAW_NFT_TO: + strcpy(msg->title, "To ETH Address"); + starkware_print_eth_address(context->amount, msg->msg); break; + case STARKWARE_WITHDRAW_AND_MINT: + strcpy(msg->title, "Asset Contract"); + starkware_print_asset_contract(msg->msg); + break; + default: PRINTF("Unexpected screen %d for %d\n", msg->screenIndex, context->selectorIndex); - break; + break; } - msg->result = ETH_PLUGIN_RESULT_OK; + msg->result = ETH_PLUGIN_RESULT_OK; break; - case 2: - switch(context->selectorIndex) { - case STARKWARE_REGISTER: + case 3: + switch(context->selectorIndex) { case STARKWARE_ESCAPE: - strcpy(msg->title, "Master Account"); - PRINTF("Master account %s\n", msg->msg); - starkware_print_stark_key(context->starkKey, msg->msg); + strcpy(msg->title, "Token Account"); + starkware_print_vault_id(U4BE(context->vaultId, 0), msg->msg); break; case STARKWARE_DEPOSIT_TOKEN: case STARKWARE_DEPOSIT_ETH: @@ -418,22 +660,19 @@ void starkware_plugin_call(int message, void *parameters) { msg->msg, false); break; case STARKWARE_WITHDRAW: + case STARKWARE_WITHDRAW_TO: strcpy(msg->title, "Token Symbol"); starkware_print_ticker(msg->msg); break; - default: - PRINTF("Unexpected screen %d for %d\n", msg->screenIndex, context->selectorIndex); - break; - } - msg->result = ETH_PLUGIN_RESULT_OK; - break; - case 3: - switch(context->selectorIndex) { - case STARKWARE_ESCAPE: - strcpy(msg->title, "Token Account"); - starkware_print_vault_id(U4BE(context->vaultId, 0), msg->msg); - break; + case STARKWARE_WITHDRAW_NFT: + case STARKWARE_WITHDRAW_NFT_TO: + case STARKWARE_DEPOSIT_NFT: + case STARKWARE_DEPOSIT_NFT_RECLAIM: + strcpy(msg->title, "NFT Contract"); + starkware_print_asset_contract(msg->msg); + break; + default: PRINTF("Unexpected screen %d for %d\n", msg->screenIndex, context->selectorIndex); break; @@ -441,6 +680,24 @@ void starkware_plugin_call(int message, void *parameters) { msg->result = ETH_PLUGIN_RESULT_OK; break; + case 4: + switch(context->selectorIndex) { + + case STARKWARE_WITHDRAW_NFT: + case STARKWARE_WITHDRAW_NFT_TO: + case STARKWARE_DEPOSIT_NFT: + case STARKWARE_DEPOSIT_NFT_RECLAIM: + strcpy(msg->title, "TokenID"); + starkware_print_stark_key(dataContext.tokenContext.quantum, msg->msg); + break; + + default: + PRINTF("Unexpected screen %d for %d\n", msg->screenIndex, context->selectorIndex); + break; + } + msg->result = ETH_PLUGIN_RESULT_OK; + break; + default: PRINTF("Unexpected screen %d for %d\n", msg->screenIndex, context->selectorIndex); break; @@ -453,4 +710,4 @@ void starkware_plugin_call(int message, void *parameters) { } } -#endif \ No newline at end of file +#endif