* Add Artis, Dexon, EWC, Thundercore, Volta, Webchain
* Switch to Flow API for Nano S 1.6.0 * Add extra U2F timeout guards for Windows * Review application flow and parameters checks * Refactor signature padding
81
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
|
||||
|
||||
BIN
artis_sigma1.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
artis_tau1.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
blue_app_artis_sigma1.gif
Normal file
|
After Width: | Height: | Size: 671 B |
BIN
blue_app_artis_tau1.gif
Normal file
|
After Width: | Height: | Size: 663 B |
BIN
blue_app_dexon.gif
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
blue_app_ewc.gif
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
blue_app_thundercore.gif
Normal file
|
After Width: | Height: | Size: 557 B |
BIN
blue_app_volta.gif
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
blue_app_webchain.gif
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
blue_badge_thundercore.gif
Normal file
|
After Width: | Height: | Size: 271 B |
BIN
glyphs/blue_badge_dexon.gif
Normal file
|
After Width: | Height: | Size: 823 B |
BIN
glyphs/blue_badge_thundercore.gif
Normal file
|
After Width: | Height: | Size: 271 B |
BIN
glyphs/blue_badge_webchain.gif
Normal file
|
After Width: | Height: | Size: 791 B |
BIN
glyphs/icon_back_x.gif
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
glyphs/icon_dashboard_x.gif
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
glyphs/nanos_badge_artis_sigma1.gif
Normal file
|
After Width: | Height: | Size: 118 B |
BIN
glyphs/nanos_badge_artis_tau1.gif
Normal file
|
After Width: | Height: | Size: 117 B |
BIN
glyphs/nanos_badge_dexon.gif
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
glyphs/nanos_badge_thundercore.gif
Normal file
|
After Width: | Height: | Size: 87 B |
BIN
glyphs/nanos_badge_webchain.gif
Normal file
|
After Width: | Height: | Size: 68 B |
BIN
nanos_app_artis_sigma1.gif
Normal file
|
After Width: | Height: | Size: 73 B |
BIN
nanos_app_artis_tau1.gif
Normal file
|
After Width: | Height: | Size: 71 B |
BIN
nanos_app_dexon.gif
Normal file
|
After Width: | Height: | Size: 75 B |
BIN
nanos_app_ewc.gif
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
nanos_app_thundercore.gif
Normal file
|
After Width: | Height: | Size: 87 B |
BIN
nanos_app_volta.gif
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
nanos_app_webchain.gif
Normal file
|
After Width: | Height: | Size: 61 B |
BIN
nanox_app_artis_sigma1.gif
Normal file
|
After Width: | Height: | Size: 71 B |
BIN
nanox_app_artis_tau1.gif
Normal file
|
After Width: | Height: | Size: 69 B |
BIN
nanox_app_dexon.gif
Normal file
|
After Width: | Height: | Size: 72 B |
BIN
nanox_app_ewc.gif
Normal file
|
After Width: | Height: | Size: 61 B |
BIN
nanox_app_thundercore.gif
Normal file
|
After Width: | Height: | Size: 92 B |
BIN
nanox_app_volta.gif
Normal file
|
After Width: | Height: | Size: 61 B |
BIN
nanox_app_webchain.gif
Normal file
|
After Width: | Height: | Size: 58 B |
@@ -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 {
|
||||
|
||||
331
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; i<numTokens; i++) {
|
||||
switch(chainConfig->kind) {
|
||||
@@ -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();
|
||||
|
||||
14
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
|
||||
|
||||
16
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_ */
|
||||
|
||||
BIN
thundercore.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
webchain.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |