diff --git a/Makefile b/Makefile index 765e685..10112a2 100755 --- a/Makefile +++ b/Makefile @@ -24,10 +24,12 @@ DEFINES_LIB = USE_LIB_ETHEREUM APP_LOAD_PARAMS= --curve secp256k1 $(COMMON_LOAD_PARAMS) # Allow the app to use path 45 for multi-sig (see BIP45). APP_LOAD_PARAMS += --path "45'" +# Samsung temporary implementation for wallet ID on 0xda7aba5e/0xc1a551c5 +APP_LOAD_PARAMS += --path "1517992542'/1101353413'" APPVERSION_M=1 APPVERSION_N=2 -APPVERSION_P=3 +APPVERSION_P=13 APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) APP_LOAD_FLAGS= --appFlags 0x240 --dep Ethereum:$(APPVERSION) @@ -71,6 +73,14 @@ else ifeq ($(CHAIN),poa) APP_LOAD_PARAMS += --path "44'/60'" DEFINES += CHAINID_UPCASE=\"POA\" CHAINID_COINNAME=\"POA\" CHAIN_KIND=CHAIN_KIND_POA CHAIN_ID=99 APPNAME = "POA" +else ifeq ($(CHAIN),artis_sigma1) +APP_LOAD_PARAMS += --path "44'/246529'" +DEFINES += CHAINID_UPCASE=\"ARTISSIGMA1\" CHAINID_COINNAME=\"ATS\" CHAIN_KIND=CHAIN_KIND_ARTIS_SIGMA1 CHAIN_ID=246529 +APPNAME = "ARTIS sigma1" +else ifeq ($(CHAIN),artis_tau1) +APP_LOAD_PARAMS += --path "44'/246785'" +DEFINES += CHAINID_UPCASE=\"ARTISTAU1\" CHAINID_COINNAME=\"ATS\" CHAIN_KIND=CHAIN_KIND_ARTIS_TAU1 CHAIN_ID=246785 +APPNAME = "ARTIS tau1" else ifeq ($(CHAIN),rsk) APP_LOAD_PARAMS += --path "44'/137'" --path "44'/00'" DEFINES += CHAINID_UPCASE=\"RSK\" CHAINID_COINNAME=\"RBTC\" CHAIN_KIND=CHAIN_KIND_RSK CHAIN_ID=30 @@ -135,9 +145,29 @@ else ifeq ($(CHAIN),tobalaba) APP_LOAD_PARAMS += --path "44'/401697'" DEFINES += CHAINID_UPCASE=\"TOBALABA\" CHAINID_COINNAME=\"TOBALABA\" CHAIN_KIND=CHAIN_KIND_TOBALABA CHAIN_ID=401697 APPNAME = "Tobalaba" +else ifeq ($(CHAIN),webchain) +APP_LOAD_PARAMS += --path "44'/227'" +DEFINES += CHAINID_UPCASE=\"WEBCHAIN\" CHAINID_COINNAME=\"WEB\" CHAIN_KIND=CHAIN_KIND_WEBCHAIN CHAIN_ID=24484 +APPNAME = "Webchain" +else ifeq ($(CHAIN),dexon) +APP_LOAD_PARAMS += --path "44'/237'" +DEFINES += CHAINID_UPCASE=\"DEXON\" CHAINID_COINNAME=\"DXN\" CHAIN_KIND=CHAIN_KIND_DEXON CHAIN_ID=237 +APPNAME = "DEXON" +else ifeq ($(CHAIN),volta) +APP_LOAD_PARAMS += --path "44'/73799'" --path "44'/60'" +DEFINES += CHAINID_UPCASE=\"VOLTA\" CHAINID_COINNAME=\"VOLTA\" CHAIN_KIND=CHAIN_KIND_VOLTA CHAIN_ID=73799 +APPNAME = "Volta" +else ifeq ($(CHAIN),ewc) +APP_LOAD_PARAMS += --path "44'/246'" --path "44'/60'" +DEFINES += CHAINID_UPCASE=\"EWC\" CHAINID_COINNAME=\"EWC\" CHAIN_KIND=CHAIN_KIND_EWC CHAIN_ID=246 +APPNAME = "EnergyWebChain" +else ifeq ($(CHAIN),thundercore) +APP_LOAD_PARAMS += --path "44'/1001'" +DEFINES += CHAINID_UPCASE=\"THUNDERCORE\" CHAINID_COINNAME=\"TT\" CHAIN_KIND=CHAIN_KIND_THUNDERCORE CHAIN_ID=108 +APPNAME = "ThunderCore" else ifeq ($(filter clean,$(MAKECMDGOALS)),) -$(error Unsupported CHAIN - use ethereum, ethereum_classic, expanse, poa, rsk, rsk_testnet, ubiq, wanchain, kusd, musicoin, pirl, akroma, atheios, callisto, ethersocial, ellaism, ether1, ethergem, gochain, mix, reosc, hpb, tomochain, tobalaba) +$(error Unsupported CHAIN - use ethereum, ethereum_classic, expanse, poa, artis_sigma1, artis_tau1, rsk, rsk_testnet, ubiq, wanchain, kusd, musicoin, pirl, akroma, atheios, callisto, ethersocial, ellaism, ether1, ethergem, gochain, mix, reosc, hpb, tomochain, tobalaba, dexon, volta, ewc, webchain, thundercore) endif endif @@ -164,10 +194,8 @@ all: default # Platform # ############ -DEFINES += OS_IO_SEPROXYHAL IO_SEPROXYHAL_BUFFER_SIZE_B=128 +DEFINES += OS_IO_SEPROXYHAL DEFINES += HAVE_BAGL HAVE_SPRINTF -#DEFINES += HAVE_PRINTF PRINTF=screen_printf -DEFINES += PRINTF\(...\)= DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=6 IO_HID_EP_LENGTH=64 HAVE_USB_APDU DEFINES += LEDGER_MAJOR_VERSION=$(APPVERSION_M) LEDGER_MINOR_VERSION=$(APPVERSION_N) LEDGER_PATCH_VERSION=$(APPVERSION_P) @@ -176,32 +204,47 @@ DEFINES += HAVE_U2F HAVE_IO_U2F DEFINES += U2F_PROXY_MAGIC=\"w0w\" DEFINES += USB_SEGMENT_SIZE=64 DEFINES += BLE_SEGMENT_SIZE=32 #max MTU, min 20 - -WEBUSB_URL = www.ledgerwallet.com -DEFINES += HAVE_WEBUSB WEBUSB_URL_SIZE_B=$(shell echo -n $(WEBUSB_URL) | wc -c) WEBUSB_URL=$(shell echo -n $(WEBUSB_URL) | sed -e "s/./\\\'\0\\\',/g") - DEFINES += UNUSED\(x\)=\(void\)x DEFINES += APPVERSION=\"$(APPVERSION)\" -DEFINES += CX_COMPLIANCE_141 +#WEBUSB_URL = www.ledgerwallet.com +#DEFINES += HAVE_WEBUSB WEBUSB_URL_SIZE_B=$(shell echo -n $(WEBUSB_URL) | wc -c) WEBUSB_URL=$(shell echo -n $(WEBUSB_URL) | sed -e "s/./\\\'\0\\\',/g") + +DEFINES += HAVE_WEBUSB WEBUSB_URL_SIZE_B=0 WEBUSB_URL="" ifeq ($(TARGET_NAME),TARGET_NANOX) +DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300 DEFINES += HAVE_BLE BLE_COMMAND_TIMEOUT_MS=2000 DEFINES += HAVE_BLE_APDU # basic ledger apdu transport over BLE -DEFINES += HAVE_GLO096 HAVE_UX_LEGACY +DEFINES += HAVE_GLO096 DEFINES += HAVE_BAGL BAGL_WIDTH=128 BAGL_HEIGHT=64 DEFINES += HAVE_BAGL_ELLIPSIS # long label truncation feature DEFINES += HAVE_BAGL_FONT_OPEN_SANS_REGULAR_11PX DEFINES += HAVE_BAGL_FONT_OPEN_SANS_EXTRABOLD_11PX DEFINES += HAVE_BAGL_FONT_OPEN_SANS_LIGHT_16PX +DEFINES += HAVE_UX_FLOW +else +DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128 +endif + +# Enabling debug PRINTF +DEBUG = 0 +ifneq ($(DEBUG),0) +ifeq ($(TARGET_NAME),TARGET_NANOX) +DEFINES += HAVE_PRINTF PRINTF=mcu_usb_printf +else +DEFINES += HAVE_PRINTF PRINTF=screen_printf +endif +else +DEFINES += PRINTF\(...\)= endif ifneq ($(NOCONSENT),) DEFINES += NO_CONSENT endif -DEFINES += HAVE_TOKENS_LIST # Do not activate external ERC-20 support yet +#DEFINES += HAVE_TOKENS_LIST # Do not activate external ERC-20 support yet ############## # Compiler # @@ -242,6 +285,18 @@ SDK_SOURCE_PATH += lib_blewbxx lib_blewbxx_impl SDK_SOURCE_PATH += lib_ux endif +# If the SDK supports Flow for Nano S, build for it + +ifeq ($(TARGET_NAME),TARGET_NANOS) + + ifneq "$(wildcard $(BOLOS_SDK)/lib_ux/src/ux_flow_engine.c)" "" + SDK_SOURCE_PATH += lib_ux + DEFINES += HAVE_UX_FLOW + DEFINES += HAVE_WALLET_ID_SDK + endif + +endif + load: all python -m ledgerblue.loadApp $(APP_LOAD_PARAMS) @@ -255,4 +310,4 @@ include $(BOLOS_SDK)/Makefile.rules dep/%.d: %.c Makefile listvariants: - @echo VARIANTS CHAIN ethereum ethereum_classic expanse poa rsk rsk_testnet ubiq wanchain kusd pirl akroma atheios callisto ethersocial ether1 gochain musicoin ethergem mix ellaism reosc hpb tomochain tobalaba + @echo VARIANTS CHAIN ethereum ethereum_classic expanse poa artis_sigma1 artis_tau1 rsk rsk_testnet ubiq wanchain kusd pirl akroma atheios callisto ethersocial ether1 gochain musicoin ethergem mix ellaism reosc hpb tomochain tobalaba dexon volta ewc webchain thundercore diff --git a/artis_sigma1.png b/artis_sigma1.png new file mode 100644 index 0000000..f6b47b1 Binary files /dev/null and b/artis_sigma1.png differ diff --git a/artis_tau1.png b/artis_tau1.png new file mode 100644 index 0000000..388009a Binary files /dev/null and b/artis_tau1.png differ diff --git a/blue_app_artis_sigma1.gif b/blue_app_artis_sigma1.gif new file mode 100644 index 0000000..8c47bf3 Binary files /dev/null and b/blue_app_artis_sigma1.gif differ diff --git a/blue_app_artis_tau1.gif b/blue_app_artis_tau1.gif new file mode 100644 index 0000000..3dfdf06 Binary files /dev/null and b/blue_app_artis_tau1.gif differ diff --git a/blue_app_dexon.gif b/blue_app_dexon.gif new file mode 100644 index 0000000..3f51c6b Binary files /dev/null and b/blue_app_dexon.gif differ diff --git a/blue_app_ewc.gif b/blue_app_ewc.gif new file mode 100644 index 0000000..d1c438f Binary files /dev/null and b/blue_app_ewc.gif differ diff --git a/blue_app_thundercore.gif b/blue_app_thundercore.gif new file mode 100644 index 0000000..bfa6ba5 Binary files /dev/null and b/blue_app_thundercore.gif differ diff --git a/blue_app_volta.gif b/blue_app_volta.gif new file mode 100644 index 0000000..d1c438f Binary files /dev/null and b/blue_app_volta.gif differ diff --git a/blue_app_webchain.gif b/blue_app_webchain.gif new file mode 100644 index 0000000..50c5b1f Binary files /dev/null and b/blue_app_webchain.gif differ diff --git a/blue_badge_thundercore.gif b/blue_badge_thundercore.gif new file mode 100644 index 0000000..a31bbe3 Binary files /dev/null and b/blue_badge_thundercore.gif differ diff --git a/dexon.png b/dexon.png new file mode 100644 index 0000000..c6a934a Binary files /dev/null and b/dexon.png differ diff --git a/ewc.png b/ewc.png new file mode 100644 index 0000000..5bda6b7 Binary files /dev/null and b/ewc.png differ diff --git a/glyphs/blue_badge_dexon.gif b/glyphs/blue_badge_dexon.gif new file mode 100644 index 0000000..9b4dd9e Binary files /dev/null and b/glyphs/blue_badge_dexon.gif differ diff --git a/glyphs/blue_badge_thundercore.gif b/glyphs/blue_badge_thundercore.gif new file mode 100644 index 0000000..a31bbe3 Binary files /dev/null and b/glyphs/blue_badge_thundercore.gif differ diff --git a/glyphs/blue_badge_webchain.gif b/glyphs/blue_badge_webchain.gif new file mode 100644 index 0000000..24edd1c Binary files /dev/null and b/glyphs/blue_badge_webchain.gif differ diff --git a/glyphs/icon_back_x.gif b/glyphs/icon_back_x.gif new file mode 100644 index 0000000..ff04361 Binary files /dev/null and b/glyphs/icon_back_x.gif differ diff --git a/glyphs/icon_dashboard_x.gif b/glyphs/icon_dashboard_x.gif new file mode 100644 index 0000000..33d9b0a Binary files /dev/null and b/glyphs/icon_dashboard_x.gif differ diff --git a/glyphs/nanos_badge_artis_sigma1.gif b/glyphs/nanos_badge_artis_sigma1.gif new file mode 100644 index 0000000..3ef0eaa Binary files /dev/null and b/glyphs/nanos_badge_artis_sigma1.gif differ diff --git a/glyphs/nanos_badge_artis_tau1.gif b/glyphs/nanos_badge_artis_tau1.gif new file mode 100644 index 0000000..9e741b5 Binary files /dev/null and b/glyphs/nanos_badge_artis_tau1.gif differ diff --git a/glyphs/nanos_badge_dexon.gif b/glyphs/nanos_badge_dexon.gif new file mode 100644 index 0000000..65021cc Binary files /dev/null and b/glyphs/nanos_badge_dexon.gif differ diff --git a/glyphs/nanos_badge_thundercore.gif b/glyphs/nanos_badge_thundercore.gif new file mode 100644 index 0000000..e723679 Binary files /dev/null and b/glyphs/nanos_badge_thundercore.gif differ diff --git a/glyphs/nanos_badge_webchain.gif b/glyphs/nanos_badge_webchain.gif new file mode 100644 index 0000000..515eed3 Binary files /dev/null and b/glyphs/nanos_badge_webchain.gif differ diff --git a/nanos_app_artis_sigma1.gif b/nanos_app_artis_sigma1.gif new file mode 100644 index 0000000..518d127 Binary files /dev/null and b/nanos_app_artis_sigma1.gif differ diff --git a/nanos_app_artis_tau1.gif b/nanos_app_artis_tau1.gif new file mode 100644 index 0000000..e9525ae Binary files /dev/null and b/nanos_app_artis_tau1.gif differ diff --git a/nanos_app_dexon.gif b/nanos_app_dexon.gif new file mode 100644 index 0000000..e028a0f Binary files /dev/null and b/nanos_app_dexon.gif differ diff --git a/nanos_app_ewc.gif b/nanos_app_ewc.gif new file mode 100644 index 0000000..d15c937 Binary files /dev/null and b/nanos_app_ewc.gif differ diff --git a/nanos_app_thundercore.gif b/nanos_app_thundercore.gif new file mode 100644 index 0000000..e723679 Binary files /dev/null and b/nanos_app_thundercore.gif differ diff --git a/nanos_app_volta.gif b/nanos_app_volta.gif new file mode 100644 index 0000000..d15c937 Binary files /dev/null and b/nanos_app_volta.gif differ diff --git a/nanos_app_webchain.gif b/nanos_app_webchain.gif new file mode 100644 index 0000000..691dbf1 Binary files /dev/null and b/nanos_app_webchain.gif differ diff --git a/nanox_app_artis_sigma1.gif b/nanox_app_artis_sigma1.gif new file mode 100644 index 0000000..c7bf71f Binary files /dev/null and b/nanox_app_artis_sigma1.gif differ diff --git a/nanox_app_artis_tau1.gif b/nanox_app_artis_tau1.gif new file mode 100644 index 0000000..47ceeb5 Binary files /dev/null and b/nanox_app_artis_tau1.gif differ diff --git a/nanox_app_dexon.gif b/nanox_app_dexon.gif new file mode 100644 index 0000000..ebbf24a Binary files /dev/null and b/nanox_app_dexon.gif differ diff --git a/nanox_app_ewc.gif b/nanox_app_ewc.gif new file mode 100644 index 0000000..b0e43f0 Binary files /dev/null and b/nanox_app_ewc.gif differ diff --git a/nanox_app_thundercore.gif b/nanox_app_thundercore.gif new file mode 100644 index 0000000..537e540 Binary files /dev/null and b/nanox_app_thundercore.gif differ diff --git a/nanox_app_volta.gif b/nanox_app_volta.gif new file mode 100644 index 0000000..b0e43f0 Binary files /dev/null and b/nanox_app_volta.gif differ diff --git a/nanox_app_webchain.gif b/nanox_app_webchain.gif new file mode 100644 index 0000000..4d1027c Binary files /dev/null and b/nanox_app_webchain.gif differ diff --git a/src/chainConfig.h b/src/chainConfig.h index fe614dc..7229d9d 100644 --- a/src/chainConfig.h +++ b/src/chainConfig.h @@ -45,7 +45,14 @@ typedef enum chain_kind_e { CHAIN_KIND_REOSC, CHAIN_KIND_HPB, CHAIN_KIND_TOMOCHAIN, - CHAIN_KIND_TOBALABA + CHAIN_KIND_TOBALABA, + CHAIN_KIND_DEXON, + CHAIN_KIND_VOLTA, + CHAIN_KIND_EWC, + CHAIN_KIND_ARTIS_SIGMA1, + CHAIN_KIND_ARTIS_TAU1, + CHAIN_KIND_WEBCHAIN, + CHAIN_KIND_THUNDERCORE } chain_kind_t; typedef struct chain_config_s { diff --git a/src/main.c b/src/main.c index 87c559d..3f52397 100644 --- a/src/main.c +++ b/src/main.c @@ -67,6 +67,9 @@ void finalizeParsing(bool); #define P1_FIRST 0x00 #define P1_MORE 0x80 +#define COMMON_CLA 0xB0 +#define COMMON_INS_GET_WALLET_ID 0x04 + #define OFFSET_CLA 0 #define OFFSET_INS 1 #define OFFSET_P1 2 @@ -144,8 +147,16 @@ union { rawDataContext_t rawDataContext; } dataContext; +typedef enum { + APP_STATE_IDLE, + APP_STATE_SIGNING_TX, + APP_STATE_SIGNING_MESSAGE +} app_state_t; + + volatile uint8_t dataAllowed; volatile uint8_t contractDetails; +volatile uint8_t appState; volatile char addressSummary[32]; volatile bool dataPresent; volatile bool tokenProvisioned; @@ -153,17 +164,17 @@ volatile bool currentTokenSet; bagl_element_t tmp_element; -#ifdef TARGET_NANOX +#ifdef HAVE_UX_FLOW #include "ux.h" ux_state_t G_ux; bolos_ux_params_t G_ux_params; -#else // TARGET_NANOX +#else // HAVE_UX_FLOW ux_state_t ux; // display stepped screens unsigned int ux_step; unsigned int ux_step_count; -#endif // TARGET_NANOX +#endif // HAVE_UX_FLOW typedef struct internalStorage_t { @@ -204,6 +215,13 @@ const bagl_element_t* ui_menu_item_out_over(const bagl_element_t* e) { return e; } +void reset_app_context() { + appState = APP_STATE_IDLE; + currentTokenSet = false; + os_memset((uint8_t*)&txContext, 0, sizeof(txContext)); + os_memset((uint8_t*)&tmpContent, 0, sizeof(tmpContent)); +} + #define BAGL_FONT_OPEN_SANS_LIGHT_16_22PX_AVG_WIDTH 10 #define BAGL_FONT_OPEN_SANS_REGULAR_10_13PX_AVG_WIDTH 8 @@ -267,7 +285,7 @@ unsigned int ui_idle_blue_button(unsigned int button_mask, unsigned int button_m #endif // #if defined(TARGET_BLUE) -#if defined(TARGET_NANOS) +#if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW) const ux_menu_entry_t menu_main[]; @@ -338,7 +356,7 @@ const ux_menu_entry_t menu_main[] = { UX_MENU_END }; -#endif // #if defined(TARGET_NANOS) +#endif // #if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW) #if defined(TARGET_BLUE) const bagl_element_t * ui_settings_blue_toggle_data(const bagl_element_t * e) { @@ -741,7 +759,8 @@ unsigned int ui_address_blue_button(unsigned int button_mask, unsigned int butto } #endif // #if defined(TARGET_BLUE) -#if defined(TARGET_NANOS) +#if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW) + const bagl_element_t ui_address_nanos[] = { // type userid x y w h str rad fill fg bg fid iid txt touchparams... ] {{BAGL_RECTANGLE , 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, NULL, 0, 0, 0, NULL, NULL, NULL}, @@ -776,11 +795,10 @@ unsigned int ui_address_prepro(const bagl_element_t* element) { } unsigned int ui_address_nanos_button(unsigned int button_mask, unsigned int button_mask_counter); -#endif // #if defined(TARGET_NANOS) +#endif // #if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW) - -#if defined(TARGET_NANOS) +#if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW) const bagl_element_t ui_approval_nanos[] = { // type userid x y w h str rad fill fg bg fid iid txt touchparams... ] {{BAGL_RECTANGLE , 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, NULL, 0, 0, 0, NULL, NULL, NULL}, @@ -875,7 +893,7 @@ unsigned int ui_approval_signMessage_prepro(const bagl_element_t *element) { return 1; } -#endif // #if defined(TARGET_NANOS) +#endif // #if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW) #if defined(TARGET_BLUE) const bagl_element_t ui_data_selector_blue[] = { @@ -921,7 +939,7 @@ unsigned int ui_data_selector_blue_button(unsigned int button_mask, unsigned int #endif // #if defined(TARGET_BLUE) -#if defined(TARGET_NANOS) +#if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW) const bagl_element_t ui_data_selector_nanos[] = { // type userid x y w h str rad // fill fg bg fid iid txt touchparams... ] @@ -956,7 +974,7 @@ unsigned int ui_data_selector_prepro(const bagl_element_t *element) { unsigned int ui_data_selector_nanos_button(unsigned int button_mask, unsigned int button_mask_counter); -#endif // #if defined(TARGET_NANOS) +#endif // #if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW) #if defined(TARGET_BLUE) const bagl_element_t ui_data_parameter_blue[] = { @@ -1017,7 +1035,7 @@ unsigned int ui_data_parameter_blue_button(unsigned int button_mask, unsigned in #endif // #if defined(TARGET_BLUE) -#if defined(TARGET_NANOS) +#if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW) const bagl_element_t ui_data_parameter_nanos[] = { // type userid x y w h str rad // fill fg bg fid iid txt touchparams... ] @@ -1054,9 +1072,9 @@ unsigned int ui_data_parameter_prepro(const bagl_element_t *element) { unsigned int ui_data_parameter_nanos_button(unsigned int button_mask, unsigned int button_mask_counter); -#endif // #if defined(TARGET_NANOS) +#endif // #if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW) -#if defined(TARGET_NANOX) +#if defined(HAVE_UX_FLOW) void display_settings(void); void switch_settings_contract_data(void); @@ -1065,9 +1083,9 @@ void switch_settings_display_data(void); ////////////////////////////////////////////////////////////////////// UX_FLOW_DEF_NOCB( ux_idle_flow_1_step, - bnn, //pnn, + nn, //pnn, { - "", //&C_icon_dashboard, + //"", //&C_icon_dashboard, "Application", "is ready", }); @@ -1091,7 +1109,7 @@ UX_FLOW_DEF_VALID( pb, os_sched_exit(-1), { - &C_icon_dashboard, + &C_icon_dashboard_x, "Quit", }); const ux_flow_step_t * const ux_idle_flow [] = { @@ -1102,6 +1120,28 @@ const ux_flow_step_t * const ux_idle_flow [] = { FLOW_END_STEP, }; +#if defined(TARGET_NANOS) + +UX_FLOW_DEF_VALID( + ux_settings_flow_1_step, + bnnn_paging, + switch_settings_contract_data(), + { + .title = "Contract data", + .text = strings.common.fullAddress, + }); + +UX_FLOW_DEF_VALID( + ux_settings_flow_2_step, + bnnn_paging, + switch_settings_display_data(), + { + .title = "Debug data", + .text = strings.common.fullAddress + 20 + }); + +#else + UX_FLOW_DEF_VALID( ux_settings_flow_1_step, bnnn, @@ -1118,18 +1158,20 @@ UX_FLOW_DEF_VALID( bnnn, switch_settings_display_data(), { - "Display data", + "Debug data", "Display contract data", "details", strings.common.fullAddress + 20 }); +#endif + UX_FLOW_DEF_VALID( ux_settings_flow_3_step, pb, ui_idle(), { - &C_icon_back, + &C_icon_back_x, "Back", }); @@ -1403,20 +1445,20 @@ const ux_flow_step_t * const ux_sign_flow [] = { }; -#endif // #if defined(TARGET_NANOX) +#endif // #if defined(HAVE_UX_FLOW) void ui_idle(void) { #if defined(TARGET_BLUE) UX_DISPLAY(ui_idle_blue, ui_idle_blue_prepro); -#elif defined(TARGET_NANOS) - UX_MENU_DISPLAY(0, menu_main, NULL); -#elif defined(TARGET_NANOX) +#elif defined(HAVE_UX_FLOW) // reserve a display stack slot if none yet if(G_ux.stack_count == 0) { ux_stack_push(); } ux_flow_init(0, ux_idle_flow, NULL); +#elif defined(TARGET_NANOS) + UX_MENU_DISPLAY(0, menu_main, NULL); #endif // #if TARGET_ID } @@ -1437,6 +1479,7 @@ unsigned int io_seproxyhal_touch_address_ok(const bagl_element_t *e) { uint32_t tx = set_result_get_publicKey(); 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 @@ -1447,6 +1490,7 @@ unsigned int io_seproxyhal_touch_address_ok(const bagl_element_t *e) { unsigned int io_seproxyhal_touch_address_cancel(const bagl_element_t *e) { G_io_apdu_buffer[0] = 0x69; G_io_apdu_buffer[1] = 0x85; + reset_app_context(); // Send back the response, do not restart the event loop io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2); // Display back the original UX @@ -1476,14 +1520,36 @@ void io_seproxyhal_send_status(uint32_t sw) { io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2); } +void format_signature_out(const uint8_t* signature) { + os_memset(G_io_apdu_buffer + 1, 0x00, 64); + uint8_t offset = 1; + uint8_t xoffset = 4; //point to r value + //copy r + uint8_t xlength = signature[xoffset-1]; + if (xlength == 33) { + xlength = 32; + xoffset ++; + } + memmove(G_io_apdu_buffer+offset+32-xlength, signature+xoffset, xlength); + offset += 32; + xoffset += xlength +2; //move over rvalue and TagLEn + //copy s value + xlength = signature[xoffset-1]; + if (xlength == 33) { + xlength = 32; + xoffset ++; + } + memmove(G_io_apdu_buffer+offset+32-xlength, signature+xoffset, xlength); +} + unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e) { uint8_t privateKeyData[32]; uint8_t signature[100]; uint8_t signatureLength; cx_ecfp_private_key_t privateKey; uint32_t tx = 0; - uint8_t rLength, sLength, rOffset, sOffset; uint32_t v = getV(&tmpContent.txContent); + io_seproxyhal_io_heartbeat(); os_perso_derive_node_bip32(CX_CURVE_256K1, tmpCtx.transactionContext.bip32Path, tmpCtx.transactionContext.pathLength, privateKeyData, NULL); @@ -1491,10 +1557,11 @@ unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e) { &privateKey); os_memset(privateKeyData, 0, 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, &info); + sizeof(tmpCtx.transactionContext.hash), signature, sizeof(signature), &info); os_memset(&privateKey, 0, sizeof(privateKey)); // Parity is present in the sequence tag in the legacy API if (tmpContent.txContent.vLength == 0) { @@ -1512,17 +1579,11 @@ unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e) { if (info & CX_ECCINFO_xGTn) { G_io_apdu_buffer[0] += 2; } - rLength = signature[3]; - sLength = signature[4 + rLength + 1]; - rOffset = (rLength == 33 ? 1 : 0); - sOffset = (sLength == 33 ? 1 : 0); - os_memmove(G_io_apdu_buffer + 1, signature + 4 + rOffset, 32); - os_memmove(G_io_apdu_buffer + 1 + 32, signature + 4 + rLength + 2 + sOffset, - 32); + 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 @@ -1531,6 +1592,7 @@ unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e) { } unsigned int io_seproxyhal_touch_tx_cancel(const bagl_element_t *e) { + reset_app_context(); G_io_apdu_buffer[0] = 0x69; G_io_apdu_buffer[1] = 0x85; // Send back the response, do not restart the event loop @@ -1547,17 +1609,19 @@ unsigned int io_seproxyhal_touch_signMessage_ok(const bagl_element_t *e) { uint8_t signatureLength; cx_ecfp_private_key_t privateKey; uint32_t tx = 0; - uint8_t rLength, sLength, rOffset, sOffset; + io_seproxyhal_io_heartbeat(); os_perso_derive_node_bip32( CX_CURVE_256K1, tmpCtx.messageSigningContext.bip32Path, 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)); 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, &info); + sizeof(tmpCtx.messageSigningContext.hash), signature, sizeof(signature), &info); os_memset(&privateKey, 0, sizeof(privateKey)); G_io_apdu_buffer[0] = 27; if (info & CX_ECCINFO_PARITY_ODD) { @@ -1566,16 +1630,11 @@ unsigned int io_seproxyhal_touch_signMessage_ok(const bagl_element_t *e) { if (info & CX_ECCINFO_xGTn) { G_io_apdu_buffer[0] += 2; } - rLength = signature[3]; - sLength = signature[4 + rLength + 1]; - rOffset = (rLength == 33 ? 1 : 0); - sOffset = (sLength == 33 ? 1 : 0); - os_memmove(G_io_apdu_buffer + 1, signature + 4 + rOffset, 32); - os_memmove(G_io_apdu_buffer + 1 + 32, signature + 4 + rLength + 2 + sOffset, - 32); + 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 @@ -1584,6 +1643,7 @@ unsigned int io_seproxyhal_touch_signMessage_ok(const bagl_element_t *e) { } unsigned int io_seproxyhal_touch_signMessage_cancel(const bagl_element_t *e) { + reset_app_context(); G_io_apdu_buffer[0] = 0x69; G_io_apdu_buffer[1] = 0x85; // Send back the response, do not restart the event loop @@ -1606,11 +1666,13 @@ unsigned int io_seproxyhal_touch_data_ok(const bagl_element_t *e) { ui_idle(); break; case USTREAM_FAULT: + reset_app_context(); io_seproxyhal_send_status(0x6A80); ui_idle(); break; default: PRINTF("Unexpected parser status\n"); + reset_app_context(); io_seproxyhal_send_status(0x6A80); ui_idle(); } @@ -1624,6 +1686,7 @@ unsigned int io_seproxyhal_touch_data_ok(const bagl_element_t *e) { unsigned int io_seproxyhal_touch_data_cancel(const bagl_element_t *e) { + reset_app_context(); io_seproxyhal_send_status(0x6985); // Display back the original UX ui_idle(); @@ -1798,6 +1861,12 @@ tokenDefinition_t* getKnownToken() { case CHAIN_KIND_POA: numTokens = NUM_TOKENS_POA; break; + case CHAIN_KIND_ARTIS_SIGMA1: + numTokens = NUM_TOKENS_ARTIS_SIGMA1; + break; + case CHAIN_KIND_ARTIS_TAU1: + numTokens = NUM_TOKENS_ARTIS_TAU1; + break; case CHAIN_KIND_RSK: numTokens = NUM_TOKENS_RSK; break; @@ -1852,6 +1921,21 @@ tokenDefinition_t* getKnownToken() { case CHAIN_KIND_TOBALABA: numTokens = NUM_TOKENS_TOBALABA; break; + case CHAIN_KIND_DEXON: + numTokens = NUM_TOKENS_DEXON; + break; + case CHAIN_KIND_VOLTA: + numTokens = NUM_TOKENS_VOLTA; + break; + case CHAIN_KIND_EWC: + numTokens = NUM_TOKENS_EWC; + break; + case CHAIN_KIND_WEBCHAIN: + numTokens = NUM_TOKENS_WEBCHAIN; + break; + case CHAIN_KIND_THUNDERCORE: + numTokens = NUM_TOKENS_THUNDERCORE; + break; } for (i=0; ikind) { @@ -1868,8 +1952,14 @@ tokenDefinition_t* getKnownToken() { currentToken = (tokenDefinition_t *)PIC(&TOKENS_PIRL[i]); break; case CHAIN_KIND_POA: - currentToken = (tokenDefinition_t *)PIC(&TOKENS_POA[i]); - break; + currentToken = (tokenDefinition_t *)PIC(&TOKENS_POA[i]); + break; + case CHAIN_KIND_ARTIS_SIGMA1: + currentToken = (tokenDefinition_t *)PIC(&TOKENS_ARTIS_SIGMA1[i]); + break; + case CHAIN_KIND_ARTIS_TAU1: + currentToken = (tokenDefinition_t *)PIC(&TOKENS_ARTIS_TAU1[i]); + break; case CHAIN_KIND_RSK: currentToken = (tokenDefinition_t *)PIC(&TOKENS_RSK[i]); break; @@ -1924,6 +2014,21 @@ tokenDefinition_t* getKnownToken() { case CHAIN_KIND_TOBALABA: currentToken = (tokenDefinition_t *)PIC(&TOKENS_TOBALABA[i]); break; + case CHAIN_KIND_DEXON: + currentToken = (tokenDefinition_t *)PIC(&TOKENS_DEXON[i]); + break; + case CHAIN_KIND_VOLTA: + currentToken = (tokenDefinition_t *)PIC(&TOKENS_VOLTA[i]); + break; + case CHAIN_KIND_EWC: + currentToken = (tokenDefinition_t *)PIC(&TOKENS_EWC[i]); + break; + case CHAIN_KIND_WEBCHAIN: + currentToken = (tokenDefinition_t *)PIC(&TOKENS_WEBCHAIN[i]); + break; + case CHAIN_KIND_THUNDERCORE: + currentToken = (tokenDefinition_t *)PIC(&TOKENS_THUNDERCORE[i]); + break } if (os_memcmp(currentToken->address, tmpContent.txContent.destination, 20) == 0) { return currentToken; @@ -2028,12 +2133,12 @@ customStatus_e customProcessor(txContext_t *context) { array_hexstr(strings.tmp.tmp, dataContext.rawDataContext.data, 4); #if defined(TARGET_BLUE) UX_DISPLAY(ui_data_selector_blue, ui_data_selector_blue_prepro); +#elif defined(HAVE_UX_FLOW) + ux_flow_init(0, ux_confirm_selector_flow, NULL); #elif defined(TARGET_NANOS) ux_step = 0; ux_step_count = 2; UX_DISPLAY(ui_data_selector_nanos, ui_data_selector_prepro); -#elif defined(TARGET_NANOX) - ux_flow_init(0, ux_confirm_selector_flow, NULL); #endif // #if TARGET_ID } else { @@ -2048,12 +2153,12 @@ customStatus_e customProcessor(txContext_t *context) { } #if defined(TARGET_BLUE) UX_DISPLAY(ui_data_parameter_blue, ui_data_parameter_blue_prepro); +#elif defined(HAVE_UX_FLOW) + ux_flow_init(0, ux_confirm_parameter_flow, NULL); #elif defined(TARGET_NANOS) ux_step = 0; ux_step_count = 2; UX_DISPLAY(ui_data_parameter_nanos, ui_data_parameter_prepro); -#elif defined(TARGET_NANOX) - ux_flow_init(0, ux_confirm_parameter_flow, NULL); #endif // #if TARGET_ID } } @@ -2067,6 +2172,31 @@ customStatus_e customProcessor(txContext_t *context) { return CUSTOM_NOT_HANDLED; } +unsigned int const U_os_perso_seed_cookie[] = { + 0xda7aba5e, + 0xc1a551c5, +}; + +#ifndef HAVE_WALLET_ID_SDK + +void handleGetWalletId(volatile unsigned int *tx) { + unsigned char t[64]; + cx_ecfp_256_private_key_t priv; + cx_ecfp_256_public_key_t pub; + // seed => priv key + os_perso_derive_node_bip32(CX_CURVE_256K1, U_os_perso_seed_cookie, 2, t, NULL); + // priv key => pubkey + cx_ecdsa_init_private_key(CX_CURVE_256K1, t, 32, &priv); + cx_ecfp_generate_pair(CX_CURVE_256K1, &pub, &priv, 1); + // pubkey -> sha512 + cx_hash_sha512(pub.W, sizeof(pub.W), t, sizeof(t)); + // ! cookie ! + os_memmove(G_io_apdu_buffer, t, 64); + *tx = 64; + THROW(0x9000); +} + +#endif void handleGetPublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, volatile unsigned int *flags, volatile unsigned int *tx) { UNUSED(dataLength); @@ -2075,7 +2205,7 @@ 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 ((bip32PathLength < 0x01) || (bip32PathLength > MAX_BIP32_PATH)) { PRINTF("Invalid path\n"); @@ -2092,11 +2222,14 @@ void handleGetPublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t da dataBuffer += 4; } tmpCtx.publicKeyContext.getChaincode = (p2 == P2_CHAINCODE); + io_seproxyhal_io_heartbeat(); os_perso_derive_node_bip32(CX_CURVE_256K1, bip32Path, bip32PathLength, privateKeyData, (tmpCtx.publicKeyContext.getChaincode ? tmpCtx.publicKeyContext.chainCode : NULL)); 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)); + io_seproxyhal_io_heartbeat(); getEthAddressStringFromKey(&tmpCtx.publicKeyContext.publicKey, tmpCtx.publicKeyContext.address, &sha3); #ifndef NO_CONSENT if (p1 == P1_NON_CONFIRM) @@ -2121,14 +2254,14 @@ void handleGetPublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t da #if defined(TARGET_BLUE) snprintf(strings.common.fullAddress, sizeof(strings.common.fullAddress), "0x%.*s", 40, tmpCtx.publicKeyContext.address); UX_DISPLAY(ui_address_blue, ui_address_blue_prepro); +#elif defined(HAVE_UX_FLOW) + snprintf(strings.common.fullAddress, sizeof(strings.common.fullAddress), "0x%.*s", 40, tmpCtx.publicKeyContext.address); + ux_flow_init(0, ux_display_public_flow, NULL); #elif defined(TARGET_NANOS) snprintf(strings.common.fullAddress, sizeof(strings.common.fullAddress), "0x%.*s", 40, tmpCtx.publicKeyContext.address); ux_step = 0; ux_step_count = 2; UX_DISPLAY(ui_address_nanos, ui_address_prepro); -#elif defined(TARGET_NANOX) - snprintf(strings.common.fullAddress, sizeof(strings.common.fullAddress), "0x%.*s", 40, tmpCtx.publicKeyContext.address); - ux_flow_init(0, ux_display_public_flow, NULL); #endif // #if TARGET_ID *flags |= IO_ASYNCH_REPLY; @@ -2149,6 +2282,7 @@ void finalizeParsing(bool direct) { if (chainConfig->chainId != 0) { uint32_t v = getV(&tmpContent.txContent); if (chainConfig->chainId != v) { + reset_app_context(); PRINTF("Invalid chainId %d expected %d\n", v, chainConfig->chainId); if (direct) { THROW(0x6A80); @@ -2161,7 +2295,7 @@ void finalizeParsing(bool direct) { } } // Store the hash - cx_hash((cx_hash_t *)&sha3, CX_LAST, tmpCtx.transactionContext.hash, 0, tmpCtx.transactionContext.hash); + cx_hash((cx_hash_t *)&sha3, CX_LAST, tmpCtx.transactionContext.hash, 0, tmpCtx.transactionContext.hash, 32); // If there is a token to process, check if it is well known if (tokenProvisioned) { tokenDefinition_t *currentToken = getKnownToken(); @@ -2177,6 +2311,7 @@ void finalizeParsing(bool direct) { } else { if (dataPresent && !N_storage.dataAllowed) { + reset_app_context(); PRINTF("Data field forbidden\n"); if (direct) { THROW(0x6A80); @@ -2257,14 +2392,14 @@ void finalizeParsing(bool direct) { #else // NO_CONSENT #if defined(TARGET_BLUE) ui_approval_transaction_blue_init(); +#elif defined(HAVE_UX_FLOW) + ux_flow_init(0, + ((dataPresent && !N_storage.contractDetails) ? ux_approval_tx_data_warning_flow : ux_approval_tx_flow), + NULL); #elif defined(TARGET_NANOS) ux_step = 0; ux_step_count = 5; UX_DISPLAY(ui_approval_nanos, ui_approval_prepro); -#elif defined(TARGET_NANOX) - 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 } @@ -2289,10 +2424,10 @@ void handleProvideErc20TokenInformation(uint8_t p1, uint8_t p2, uint8_t *workBuf if (dataLength < tickerLength + 20 + 4 + 4) { THROW(0x6A80); } - cx_hash_sha256(workBuffer + offset, tickerLength + 20 + 4 + 4, hash); + cx_hash_sha256(workBuffer + offset, tickerLength + 20 + 4 + 4, hash, 32); os_memmove(tmpCtx.transactionContext.currentToken.ticker, workBuffer + offset, tickerLength); tmpCtx.transactionContext.currentToken.ticker[tickerLength] = ' '; - tmpCtx.transactionContext.currentToken.ticker[tickerLength + 1] = '\0'; + tmpCtx.transactionContext.currentToken.ticker[tickerLength + 1] = '\0'; offset += tickerLength; dataLength -= tickerLength; os_memmove(tmpCtx.transactionContext.currentToken.address, workBuffer + offset, 20); @@ -2322,6 +2457,14 @@ void handleSign(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength parserStatus_e txResult; uint32_t i; if (p1 == P1_FIRST) { + if (dataLength < 1) { + PRINTF("Invalid data\n"); + THROW(0x6a80); + } + if (appState != APP_STATE_IDLE) { + reset_app_context(); + } + appState = APP_STATE_SIGNING_TX; tmpCtx.transactionContext.pathLength = workBuffer[0]; if ((tmpCtx.transactionContext.pathLength < 0x01) || (tmpCtx.transactionContext.pathLength > MAX_BIP32_PATH)) { @@ -2331,6 +2474,10 @@ void handleSign(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength workBuffer++; dataLength--; for (i = 0; i < tmpCtx.transactionContext.pathLength; i++) { + if (dataLength < 4) { + PRINTF("Invalid data\n"); + THROW(0x6a80); + } tmpCtx.transactionContext.bip32Path[i] = U4BE(workBuffer, 0); workBuffer += 4; dataLength -= 4; @@ -2346,6 +2493,10 @@ void handleSign(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength if (p2 != 0) { THROW(0x6B00); } + if ((p1 == P1_MORE) && (appState != APP_STATE_SIGNING_TX)) { + PRINTF("Signature not initialized\n"); + THROW(0x6985); + } if (txContext.currentField == TX_RLP_NONE) { PRINTF("Parser not initialized\n"); THROW(0x6985); @@ -2398,6 +2549,14 @@ void handleSignPersonalMessage(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint uint32_t base = 10; uint8_t pos = 0; uint32_t i; + if (dataLength < 1) { + PRINTF("Invalid data\n"); + THROW(0x6a80); + } + if (appState != APP_STATE_IDLE) { + reset_app_context(); + } + appState = APP_STATE_SIGNING_MESSAGE; tmpCtx.messageSigningContext.pathLength = workBuffer[0]; if ((tmpCtx.messageSigningContext.pathLength < 0x01) || (tmpCtx.messageSigningContext.pathLength > MAX_BIP32_PATH)) { @@ -2407,16 +2566,24 @@ void handleSignPersonalMessage(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint workBuffer++; dataLength--; for (i = 0; i < tmpCtx.messageSigningContext.pathLength; i++) { + if (dataLength < 4) { + PRINTF("Invalid data\n"); + THROW(0x6a80); + } tmpCtx.messageSigningContext.bip32Path[i] = U4BE(workBuffer, 0); workBuffer += 4; dataLength -= 4; } + if (dataLength < 4) { + PRINTF("Invalid data\n"); + THROW(0x6a80); + } tmpCtx.messageSigningContext.remainingLength = U4BE(workBuffer, 0); workBuffer += 4; dataLength -= 4; // Initialize message header + length cx_keccak_init(&sha3, 256); - cx_hash((cx_hash_t *)&sha3, 0, SIGN_MAGIC, sizeof(SIGN_MAGIC) - 1, NULL); + cx_hash((cx_hash_t *)&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); @@ -2424,7 +2591,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, tmp, pos, NULL); + cx_hash((cx_hash_t *)&sha3, 0, (uint8_t*)tmp, pos, NULL, 0); cx_sha256_init(&tmpContent.sha2); } else if (p1 != P1_MORE) { @@ -2433,15 +2600,19 @@ void handleSignPersonalMessage(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint if (p2 != 0) { THROW(0x6B00); } + if ((p1 == P1_MORE) && (appState != APP_STATE_SIGNING_MESSAGE)) { + PRINTF("Signature not initialized\n"); + THROW(0x6985); + } if (dataLength > tmpCtx.messageSigningContext.remainingLength) { THROW(0x6A80); } - cx_hash((cx_hash_t *)&sha3, 0, workBuffer, dataLength, NULL); - cx_hash((cx_hash_t *)&tmpContent.sha2, 0, workBuffer, dataLength, NULL); + cx_hash((cx_hash_t *)&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); - cx_hash((cx_hash_t *)&tmpContent.sha2, CX_LAST, workBuffer, 0, hashMessage); + cx_hash((cx_hash_t *)&sha3, CX_LAST, workBuffer, 0, tmpCtx.messageSigningContext.hash, 32); + cx_hash((cx_hash_t *)&tmpContent.sha2, CX_LAST, workBuffer, 0, hashMessage, 32); #define HASH_LENGTH 4 array_hexstr(strings.common.fullAddress, hashMessage, HASH_LENGTH / 2); @@ -2455,13 +2626,13 @@ void handleSignPersonalMessage(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint #else NO_CONSENT #if defined(TARGET_BLUE) ui_approval_message_sign_blue_init(); +#elif defined(HAVE_UX_FLOW) + ux_flow_init(0, ux_sign_flow, NULL); #elif defined(TARGET_NANOS) ux_step = 0; ux_step_count = 2; UX_DISPLAY(ui_approval_signMessage_nanos, ui_approval_signMessage_prepro); -#elif defined(TARGET_NANOX) - ux_flow_init(0, ux_sign_flow, NULL); #endif // #if TARGET_ID #endif // NO_CONSENT @@ -2477,6 +2648,16 @@ void handleApdu(volatile unsigned int *flags, volatile unsigned int *tx) { BEGIN_TRY { TRY { + +#ifndef HAVE_WALLET_ID_SDK + + if ((G_io_apdu_buffer[OFFSET_CLA] == COMMON_CLA) && (G_io_apdu_buffer[OFFSET_INS] == COMMON_INS_GET_WALLET_ID)) { + handleGetWalletId(tx); + return; + } + +#endif + if (G_io_apdu_buffer[OFFSET_CLA] != CLA) { THROW(0x6E00); } @@ -2523,7 +2704,7 @@ void handleApdu(volatile unsigned int *flags, volatile unsigned int *tx) { case 0x6000: // Wipe the transaction context and report the exception sw = e; - os_memset(&txContext, 0, sizeof(txContext)); + reset_app_context(); break; case 0x9000: // All is well @@ -2532,6 +2713,7 @@ void handleApdu(volatile unsigned int *flags, volatile unsigned int *tx) { default: // Internal error sw = 0x6800 | (e & 0x7FF); + reset_app_context(); break; } // Unexpected exception => report @@ -2573,6 +2755,8 @@ void sample_main(void) { THROW(0x6982); } + PRINTF("New APDU received:\n%.*H\n", rx, G_io_apdu_buffer); + handleApdu(&flags, &tx); } CATCH(EXCEPTION_IO_RESET) { @@ -2583,7 +2767,7 @@ void sample_main(void) { case 0x6000: // Wipe the transaction context and report the exception sw = e; - os_memset(&txContext, 0, sizeof(txContext)); + reset_app_context(); break; case 0x9000: // All is well @@ -2592,6 +2776,7 @@ void sample_main(void) { default: // Internal error sw = 0x6800 | (e & 0x7FF); + reset_app_context(); break; } if (e != 0x9000) { @@ -2647,7 +2832,7 @@ unsigned char io_event(unsigned char channel) { case SEPROXYHAL_TAG_TICKER_EVENT: UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, { - #ifndef TARGET_NANOX + #ifndef HAVE_UX_FLOW if (UX_ALLOWED) { if (ux_step_count) { // prepare next screen @@ -2656,7 +2841,7 @@ unsigned char io_event(unsigned char channel) { UX_REDISPLAY(); } } - #endif // TARGET_NANOX + #endif // HAVE_UX_FLOW }); break; } @@ -2736,7 +2921,7 @@ __attribute__((section(".boot"))) int main(int arg0) { chainConfig = (chain_config_t *)PIC(&C_chain_config); } - os_memset(&txContext, 0, sizeof(txContext)); + reset_app_context(); // ensure exception will work as planned os_boot(); diff --git a/src/tokens.c b/src/tokens.c index 5b458f6..39387bd 100644 --- a/src/tokens.c +++ b/src/tokens.c @@ -1182,4 +1182,18 @@ const tokenDefinition_t const TOKENS_TOMOCHAIN[NUM_TOKENS_TOMOCHAIN] = {}; const tokenDefinition_t const TOKENS_TOBALABA[NUM_TOKENS_TOBALABA] = {}; +const tokenDefinition_t const TOKENS_DEXON[NUM_TOKENS_DEXON] = {}; + +const tokenDefinition_t const TOKENS_VOLTA[NUM_TOKENS_VOLTA] = {}; + +const tokenDefinition_t const TOKENS_EWC[NUM_TOKENS_EWC] = {}; + +const tokenDefinition_t const TOKENS_ARTIS_SIGMA1[NUM_TOKENS_ARTIS_SIGMA1] = {}; + +const tokenDefinition_t const TOKENS_ARTIS_TAU1[NUM_TOKENS_ARTIS_TAU1] = {}; + +const tokenDefinition_t const TOKENS_WEBCHAIN[NUM_TOKENS_WEBCHAIN] = {}; + +const tokenDefinition_t const TOKENS_THUNDERCORE[NUM_TOKENS_THUNDERCORE] = {}; + #endif diff --git a/src/tokens.h b/src/tokens.h index 488302d..e54a82c 100644 --- a/src/tokens.h +++ b/src/tokens.h @@ -51,6 +51,13 @@ typedef struct tokenDefinition_t { #define NUM_TOKENS_HPB 0 #define NUM_TOKENS_TOMOCHAIN 0 #define NUM_TOKENS_TOBALABA 0 +#define NUM_TOKENS_DEXON 0 +#define NUM_TOKENS_VOLTA 0 +#define NUM_TOKENS_EWC 0 +#define NUM_TOKENS_ARTIS_SIGMA1 0 +#define NUM_TOKENS_ARTIS_TAU1 0 +#define NUM_TOKENS_WEBCHAIN 0 +#define NUM_TOKENS_THUNDERCORE 0 extern tokenDefinition_t const TOKENS_AKROMA[NUM_TOKENS_AKROMA]; extern tokenDefinition_t const TOKENS_ELLAISM[NUM_TOKENS_ELLAISM]; @@ -75,7 +82,14 @@ extern tokenDefinition_t const TOKENS_REOSC[NUM_TOKENS_REOSC]; extern tokenDefinition_t const TOKENS_HPB[NUM_TOKENS_HPB]; extern tokenDefinition_t const TOKENS_TOMOCHAIN[NUM_TOKENS_TOMOCHAIN]; extern tokenDefinition_t const TOKENS_TOBALABA[NUM_TOKENS_TOBALABA]; +extern tokenDefinition_t const TOKENS_DEXON[NUM_TOKENS_DEXON]; +extern tokenDefinition_t const TOKENS_VOLTA[NUM_TOKENS_VOLTA]; +extern tokenDefinition_t const TOKENS_EWC[NUM_TOKENS_EWC]; +extern tokenDefinition_t const TOKENS_ARTIS_SIGMA1[NUM_TOKENS_ARTIS_SIGMA1]; +extern tokenDefinition_t const TOKENS_ARTIS_TAU1[NUM_TOKENS_ARTIS_TAU1]; +extern tokenDefinition_t const TOKENS_WEBCHAIN[NUM_TOKENS_WEBCHAIN]; +extern tokenDefinition_t const TOKENS_THUNDERCORE[NUM_TOKENS_THUNDERCORE]; -#endif +#endif /* HAVE_TOKENS_LIST */ #endif /* _TOKENS_H_ */ diff --git a/thundercore.png b/thundercore.png new file mode 100644 index 0000000..49758ac Binary files /dev/null and b/thundercore.png differ diff --git a/volta.png b/volta.png new file mode 100644 index 0000000..5bda6b7 Binary files /dev/null and b/volta.png differ diff --git a/webchain.png b/webchain.png new file mode 100644 index 0000000..be97f3c Binary files /dev/null and b/webchain.png differ