2016-06-01 21:41:29 +02:00
/*******************************************************************************
2019-01-03 17:00:20 +01:00
* Ledger Ethereum App
* ( c ) 2016 - 2019 Ledger
2016-06-01 21:41:29 +02:00
*
* Licensed under the Apache License , Version 2.0 ( the " License " ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-01-04 10:31:57 +01:00
# include <stdbool.h>
# include <stdint.h>
# include <string.h>
2016-06-01 21:41:29 +02:00
# include "os.h"
# include "cx.h"
# include "ethUstream.h"
# include "ethUtils.h"
# include "uint256.h"
2017-02-04 13:09:46 +01:00
# include "tokens.h"
2018-07-27 21:02:24 +02:00
# include "chainConfig.h"
2016-06-01 21:41:29 +02:00
# include "os_io_seproxyhal.h"
2016-10-17 23:40:31 +02:00
2017-01-22 18:26:27 +01:00
# include "glyphs.h"
2019-01-04 10:43:12 +01:00
# include "utils.h"
2017-01-22 18:26:27 +01:00
2016-06-01 21:41:29 +02:00
unsigned char G_io_seproxyhal_spi_buffer [ IO_SEPROXYHAL_BUFFER_SIZE_B ] ;
2017-01-22 18:26:27 +01:00
unsigned int io_seproxyhal_touch_settings ( const bagl_element_t * e ) ;
2016-07-31 09:36:00 +02:00
unsigned int io_seproxyhal_touch_exit ( const bagl_element_t * e ) ;
unsigned int io_seproxyhal_touch_tx_ok ( const bagl_element_t * e ) ;
unsigned int io_seproxyhal_touch_tx_cancel ( const bagl_element_t * e ) ;
unsigned int io_seproxyhal_touch_address_ok ( const bagl_element_t * e ) ;
unsigned int io_seproxyhal_touch_address_cancel ( const bagl_element_t * e ) ;
2017-03-03 13:49:39 +01:00
unsigned int io_seproxyhal_touch_signMessage_ok ( const bagl_element_t * e ) ;
unsigned int io_seproxyhal_touch_signMessage_cancel ( const bagl_element_t * e ) ;
2018-07-31 19:59:59 +02:00
unsigned int io_seproxyhal_touch_data_ok ( const bagl_element_t * e ) ;
unsigned int io_seproxyhal_touch_data_cancel ( const bagl_element_t * e ) ;
2017-01-22 18:26:27 +01:00
void ui_idle ( void ) ;
2016-06-01 21:41:29 +02:00
uint32_t set_result_get_publicKey ( void ) ;
2018-07-31 19:59:59 +02:00
void finalizeParsing ( bool ) ;
2016-06-01 21:41:29 +02:00
# define MAX_BIP32_PATH 10
2019-02-05 14:50:36 +01:00
# define APP_FLAG_DATA_ALLOWED 0x01
# define APP_FLAG_EXTERNAL_TOKEN_NEEDED 0x02
2016-06-01 21:41:29 +02:00
# define CLA 0xE0
# define INS_GET_PUBLIC_KEY 0x02
# define INS_SIGN 0x04
2016-10-17 23:40:31 +02:00
# define INS_GET_APP_CONFIGURATION 0x06
2017-03-03 13:49:39 +01:00
# define INS_SIGN_PERSONAL_MESSAGE 0x08
2019-02-05 14:50:36 +01:00
# define INS_PROVIDE_ERC20_TOKEN_INFORMATION 0x0A
2016-06-01 21:41:29 +02:00
# define P1_CONFIRM 0x01
# define P1_NON_CONFIRM 0x00
2016-10-17 23:40:31 +02:00
# define P2_NO_CHAINCODE 0x00
# define P2_CHAINCODE 0x01
2016-06-01 21:41:29 +02:00
# define P1_FIRST 0x00
# define P1_MORE 0x80
2020-01-18 12:47:53 +01:00
# define COMMON_CLA 0xB0
# define COMMON_INS_GET_WALLET_ID 0x04
2016-06-01 21:41:29 +02:00
# define OFFSET_CLA 0
# define OFFSET_INS 1
# define OFFSET_P1 2
# define OFFSET_P2 3
# define OFFSET_LC 4
# define OFFSET_CDATA 5
# define WEI_TO_ETHER 18
2018-07-27 21:02:24 +02:00
static const uint8_t const TOKEN_TRANSFER_ID [ ] = { 0xa9 , 0x05 , 0x9c , 0xbb } ;
2019-02-05 14:50:36 +01:00
static const uint8_t const TOKEN_SIGNATURE_PUBLIC_KEY [ ] = {
// production key 2019-01-11 03:07PM (erc20signer)
0x04 ,
2019-03-18 14:03:54 +01:00
2019-02-05 14:50:36 +01:00
0x5e , 0x6c , 0x10 , 0x20 , 0xc1 , 0x4d , 0xc4 , 0x64 ,
0x42 , 0xfe , 0x89 , 0xf9 , 0x7c , 0x0b , 0x68 , 0xcd ,
0xb1 , 0x59 , 0x76 , 0xdc , 0x24 , 0xf2 , 0x4c , 0x31 ,
0x6e , 0x7b , 0x30 , 0xfe , 0x4e , 0x8c , 0xc7 , 0x6b ,
2019-03-18 14:03:54 +01:00
2019-02-05 14:50:36 +01:00
0x14 , 0x89 , 0x15 , 0x0c , 0x21 , 0x51 , 0x4e , 0xbf ,
0x44 , 0x0f , 0xf5 , 0xde , 0xa5 , 0x39 , 0x3d , 0x83 ,
0xde , 0x53 , 0x58 , 0xcd , 0x09 , 0x8f , 0xce , 0x8f ,
0xd0 , 0xf8 , 0x1d , 0xaa , 0x94 , 0x97 , 0x91 , 0x83
} ;
2017-02-04 13:09:46 +01:00
typedef struct tokenContext_t {
uint8_t data [ 4 + 32 + 32 ] ;
2018-12-19 17:02:00 +01:00
uint32_t dataFieldPos ;
2017-02-04 13:09:46 +01:00
} tokenContext_t ;
2018-12-19 17:02:00 +01:00
typedef struct rawDataContext_t {
2018-07-31 19:59:59 +02:00
uint8_t data [ 32 ] ;
uint8_t fieldIndex ;
uint8_t fieldOffset ;
} rawDataContext_t ;
2016-06-01 21:41:29 +02:00
typedef struct publicKeyContext_t {
cx_ecfp_public_key_t publicKey ;
uint8_t address [ 41 ] ;
2016-10-17 23:40:31 +02:00
uint8_t chainCode [ 32 ] ;
bool getChaincode ;
2016-06-01 21:41:29 +02:00
} publicKeyContext_t ;
typedef struct transactionContext_t {
uint8_t pathLength ;
uint32_t bip32Path [ MAX_BIP32_PATH ] ;
uint8_t hash [ 32 ] ;
2019-02-05 14:50:36 +01:00
tokenDefinition_t currentToken ;
2016-06-01 21:41:29 +02:00
} transactionContext_t ;
2017-03-03 13:49:39 +01:00
typedef struct messageSigningContext_t {
uint8_t pathLength ;
uint32_t bip32Path [ MAX_BIP32_PATH ] ;
uint8_t hash [ 32 ] ;
2018-12-19 17:02:00 +01:00
uint32_t remainingLength ;
2017-03-03 13:49:39 +01:00
} messageSigningContext_t ;
2016-06-01 21:41:29 +02:00
union {
publicKeyContext_t publicKeyContext ;
transactionContext_t transactionContext ;
2017-03-03 13:49:39 +01:00
messageSigningContext_t messageSigningContext ;
2016-06-01 21:41:29 +02:00
} tmpCtx ;
txContext_t txContext ;
2017-03-03 13:49:39 +01:00
union {
2018-07-27 21:02:24 +02:00
txContent_t txContent ;
cx_sha256_t sha2 ;
2017-03-03 13:49:39 +01:00
} tmpContent ;
2016-08-12 15:53:40 +02:00
cx_sha3_t sha3 ;
2018-07-31 19:59:59 +02:00
union {
tokenContext_t tokenContext ;
2018-12-19 17:02:00 +01:00
rawDataContext_t rawDataContext ;
2018-07-31 19:59:59 +02:00
} dataContext ;
2020-01-18 12:47:53 +01:00
typedef enum {
APP_STATE_IDLE ,
APP_STATE_SIGNING_TX ,
APP_STATE_SIGNING_MESSAGE
} app_state_t ;
2018-07-27 21:02:24 +02:00
volatile uint8_t dataAllowed ;
2018-08-28 09:12:20 +02:00
volatile uint8_t contractDetails ;
2020-01-18 12:47:53 +01:00
volatile uint8_t appState ;
2017-01-22 18:26:27 +01:00
volatile char addressSummary [ 32 ] ;
2016-10-17 23:40:31 +02:00
volatile bool dataPresent ;
2018-07-31 19:59:59 +02:00
volatile bool tokenProvisioned ;
2019-02-05 14:50:36 +01:00
volatile bool currentTokenSet ;
2016-10-17 23:40:31 +02:00
2017-01-22 18:26:27 +01:00
bagl_element_t tmp_element ;
2020-01-18 12:47:53 +01:00
# ifdef HAVE_UX_FLOW
2019-02-12 20:41:19 +01:00
# include "ux.h"
ux_state_t G_ux ;
bolos_ux_params_t G_ux_params ;
2020-01-18 12:47:53 +01:00
# else // HAVE_UX_FLOW
2016-07-31 09:36:00 +02:00
ux_state_t ux ;
2019-02-12 20:41:19 +01:00
2016-07-31 09:36:00 +02:00
// display stepped screens
unsigned int ux_step ;
unsigned int ux_step_count ;
2020-01-18 12:47:53 +01:00
# endif // HAVE_UX_FLOW
2019-02-12 20:41:19 +01:00
2016-07-31 09:36:00 +02:00
2016-10-17 23:40:31 +02:00
typedef struct internalStorage_t {
2018-07-27 21:02:24 +02:00
unsigned char dataAllowed ;
2018-08-28 09:12:20 +02:00
unsigned char contractDetails ;
2018-07-27 21:02:24 +02:00
uint8_t initialized ;
2016-10-17 23:40:31 +02:00
} internalStorage_t ;
2018-07-31 19:59:59 +02:00
typedef struct strData_t {
char fullAddress [ 43 ] ;
char fullAmount [ 50 ] ;
char maxFee [ 50 ] ;
} strData_t ;
typedef struct strDataTmp_t {
char tmp [ 100 ] ;
char tmp2 [ 40 ] ;
} strDataTmp_t ;
union {
strData_t common ;
strDataTmp_t tmp ;
} strings ;
2019-02-12 20:41:19 +01:00
const internalStorage_t N_storage_real ;
# define N_storage (*(volatile internalStorage_t*) PIC(&N_storage_real))
2016-10-17 23:40:31 +02:00
static const char const CONTRACT_ADDRESS [ ] = " New contract " ;
2017-03-03 13:49:39 +01:00
static const char const SIGN_MAGIC [ ] = " \x19 "
" Ethereum Signed Message: \n " ;
2018-12-19 17:02:00 +01:00
chain_config_t * chainConfig ;
2018-07-27 21:02:24 +02:00
const bagl_element_t * ui_menu_item_out_over ( const bagl_element_t * e ) {
// the selection rectangle is after the none|touchable
e = ( const bagl_element_t * ) ( ( ( unsigned int ) e ) + sizeof ( bagl_element_t ) ) ;
return e ;
2016-10-17 23:40:31 +02:00
}
2020-01-18 12:47:53 +01:00
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 ) ) ;
}
2017-01-22 18:26:27 +01:00
# define BAGL_FONT_OPEN_SANS_LIGHT_16_22PX_AVG_WIDTH 10
# define BAGL_FONT_OPEN_SANS_REGULAR_10_13PX_AVG_WIDTH 8
# define MAX_CHAR_PER_LINE 25
# define COLOR_BG_1 0xF9F9F9
# define COLOR_APP 0x0ebdcf
# define COLOR_APP_LIGHT 0x87dee6
2017-05-31 21:51:11 +02:00
# if defined(TARGET_BLUE)
2018-07-27 21:02:24 +02:00
unsigned int map_color ( unsigned int color ) {
switch ( color ) {
case COLOR_APP :
return chainConfig - > color_header ;
case COLOR_APP_LIGHT :
return chainConfig - > color_dashboard ;
}
return color ;
}
void copy_element_and_map_coin_colors ( const bagl_element_t * element ) {
os_memmove ( & tmp_element , element , sizeof ( bagl_element_t ) ) ;
tmp_element . component . fgcolor = map_color ( tmp_element . component . fgcolor ) ;
tmp_element . component . bgcolor = map_color ( tmp_element . component . bgcolor ) ;
tmp_element . overfgcolor = map_color ( tmp_element . overfgcolor ) ;
tmp_element . overbgcolor = map_color ( tmp_element . overbgcolor ) ;
}
const bagl_element_t * ui_idle_blue_prepro ( const bagl_element_t * element ) {
copy_element_and_map_coin_colors ( element ) ;
if ( element - > component . userid = = 0x01 ) {
tmp_element . text = chainConfig - > header_text ;
}
return & tmp_element ;
}
2017-01-22 18:26:27 +01:00
const bagl_element_t ui_idle_blue [ ] = {
2018-07-27 21:02:24 +02:00
// type userid x y w h str rad fill fg bg fid iid txt touchparams... ]
{ { BAGL_RECTANGLE , 0x00 , 0 , 68 , 320 , 413 , 0 , 0 , BAGL_FILL , COLOR_BG_1 , 0x000000 , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
// erase screen (only under the status bar)
{ { BAGL_RECTANGLE , 0x00 , 0 , 20 , 320 , 48 , 0 , 0 , BAGL_FILL , COLOR_APP , COLOR_APP , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
/// TOP STATUS BAR
{ { BAGL_LABELINE , 0x01 , 0 , 45 , 320 , 30 , 0 , 0 , BAGL_FILL , 0xFFFFFF , COLOR_APP , BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER , 0 } , CHAINID_UPCASE , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE , 0x00 , 0 , 19 , 56 , 44 , 0 , 0 , BAGL_FILL , COLOR_APP , COLOR_APP_LIGHT , BAGL_FONT_SYMBOLS_0 | BAGL_FONT_ALIGNMENT_CENTER | BAGL_FONT_ALIGNMENT_MIDDLE , 0 } , BAGL_FONT_SYMBOLS_0_SETTINGS , 0 , COLOR_APP , 0xFFFFFF , io_seproxyhal_touch_settings , NULL , NULL } ,
{ { BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE , 0x00 , 264 , 19 , 56 , 44 , 0 , 0 , BAGL_FILL , COLOR_APP , COLOR_APP_LIGHT , BAGL_FONT_SYMBOLS_0 | BAGL_FONT_ALIGNMENT_CENTER | BAGL_FONT_ALIGNMENT_MIDDLE , 0 } , BAGL_FONT_SYMBOLS_0_DASHBOARD , 0 , COLOR_APP , 0xFFFFFF , io_seproxyhal_touch_exit , NULL , NULL } ,
{ { BAGL_LABELINE , 0x00 , 0 , 270 , 320 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_LIGHT_16_22PX | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " Open your wallet " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x00 , 0 , 308 , 320 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " Connect your Ledger Blue and open your " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x00 , 0 , 331 , 320 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " preferred wallet to view your accounts. " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x00 , 0 , 450 , 320 , 14 , 0 , 0 , 0 , 0x999999 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_8_11PX | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " Validation requests will show automatically. " , 10 , 0 , COLOR_BG_1 , NULL , NULL , NULL } ,
2017-01-22 18:26:27 +01:00
} ;
2016-07-31 09:36:00 +02:00
2018-07-27 21:02:24 +02:00
unsigned int ui_idle_blue_button ( unsigned int button_mask , unsigned int button_mask_counter ) {
return 0 ;
2016-07-31 09:36:00 +02:00
}
2017-05-31 21:51:11 +02:00
# endif // #if defined(TARGET_BLUE)
2016-07-31 09:36:00 +02:00
2018-07-27 21:02:24 +02:00
2020-01-18 12:47:53 +01:00
# if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW)
2016-07-31 09:36:00 +02:00
2018-07-27 21:02:24 +02:00
2017-03-03 13:49:39 +01:00
const ux_menu_entry_t menu_main [ ] ;
const ux_menu_entry_t menu_settings [ ] ;
2018-07-27 21:02:24 +02:00
//const ux_menu_entry_t menu_settings_browser[];
2017-03-03 13:49:39 +01:00
const ux_menu_entry_t menu_settings_data [ ] ;
2018-08-28 09:12:20 +02:00
const ux_menu_entry_t menu_settings_details [ ] ;
2016-07-31 09:36:00 +02:00
2017-03-03 13:49:39 +01:00
# ifdef HAVE_U2F
2016-10-17 23:40:31 +02:00
2017-03-03 13:49:39 +01:00
// change the setting
void menu_settings_data_change ( unsigned int enabled ) {
2018-07-27 21:02:24 +02:00
dataAllowed = enabled ;
nvm_write ( & N_storage . dataAllowed , ( void * ) & dataAllowed , sizeof ( uint8_t ) ) ;
// go back to the menu entry
UX_MENU_DISPLAY ( 0 , menu_settings , NULL ) ;
2017-03-03 13:49:39 +01:00
}
2016-07-31 09:36:00 +02:00
2018-08-28 09:12:20 +02:00
void menu_settings_details_change ( unsigned int enabled ) {
contractDetails = enabled ;
nvm_write ( & N_storage . contractDetails , ( void * ) & contractDetails , sizeof ( uint8_t ) ) ;
// go back to the menu entry
UX_MENU_DISPLAY ( 0 , menu_settings , NULL ) ;
}
2017-03-03 13:49:39 +01:00
// show the currently activated entry
void menu_settings_data_init ( unsigned int ignored ) {
2018-07-27 21:02:24 +02:00
UNUSED ( ignored ) ;
UX_MENU_DISPLAY ( N_storage . dataAllowed ? 1 : 0 , menu_settings_data , NULL ) ;
2017-03-03 13:49:39 +01:00
}
2018-08-28 09:12:20 +02:00
void menu_settings_details_init ( unsigned int ignored ) {
UNUSED ( ignored ) ;
UX_MENU_DISPLAY ( N_storage . contractDetails ? 1 : 0 , menu_settings_details , NULL ) ;
}
2017-03-03 13:49:39 +01:00
const ux_menu_entry_t menu_settings_data [ ] = {
2018-07-27 21:02:24 +02:00
{ NULL , menu_settings_data_change , 0 , NULL , " No " , NULL , 0 , 0 } ,
{ NULL , menu_settings_data_change , 1 , NULL , " Yes " , NULL , 0 , 0 } ,
UX_MENU_END
} ;
2017-03-03 13:49:39 +01:00
2018-08-28 09:12:20 +02:00
const ux_menu_entry_t menu_settings_details [ ] = {
{ NULL , menu_settings_details_change , 0 , NULL , " No " , NULL , 0 , 0 } ,
{ NULL , menu_settings_details_change , 1 , NULL , " Yes " , NULL , 0 , 0 } ,
UX_MENU_END
} ;
2017-03-03 13:49:39 +01:00
const ux_menu_entry_t menu_settings [ ] = {
2018-07-27 21:02:24 +02:00
{ NULL , menu_settings_data_init , 0 , NULL , " Contract data " , NULL , 0 , 0 } ,
2018-08-28 09:12:20 +02:00
{ NULL , menu_settings_details_init , 0 , NULL , " Display data " , NULL , 0 , 0 } ,
2018-07-27 21:02:24 +02:00
{ menu_main , NULL , 1 , & C_icon_back , " Back " , NULL , 61 , 40 } ,
UX_MENU_END
} ;
2017-03-03 13:49:39 +01:00
# endif // HAVE_U2F
const ux_menu_entry_t menu_about [ ] = {
2018-07-27 21:02:24 +02:00
{ NULL , NULL , 0 , NULL , " Version " , APPVERSION , 0 , 0 } ,
{ menu_main , NULL , 2 , & C_icon_back , " Back " , NULL , 61 , 40 } ,
UX_MENU_END
} ;
2017-03-03 13:49:39 +01:00
const ux_menu_entry_t menu_main [ ] = {
2018-07-27 21:02:24 +02:00
{ NULL , NULL , 0 , NULL , " Use wallet to " , " view accounts " , 0 , 0 } ,
{ menu_settings , NULL , 0 , NULL , " Settings " , NULL , 0 , 0 } ,
{ menu_about , NULL , 0 , NULL , " About " , NULL , 0 , 0 } ,
{ NULL , os_sched_exit , 0 , & C_icon_dashboard , " Quit app " , NULL , 50 , 29 } ,
UX_MENU_END
} ;
2017-03-03 13:49:39 +01:00
2020-01-18 12:47:53 +01:00
# endif // #if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW)
2017-01-22 18:26:27 +01:00
2017-05-31 21:51:11 +02:00
# if defined(TARGET_BLUE)
2018-07-27 21:02:24 +02:00
const bagl_element_t * ui_settings_blue_toggle_data ( const bagl_element_t * e ) {
// swap setting and request redraw of settings elements
uint8_t setting = N_storage . dataAllowed ? 0 : 1 ;
nvm_write ( & N_storage . dataAllowed , ( void * ) & setting , sizeof ( uint8_t ) ) ;
2017-01-22 18:26:27 +01:00
2018-07-27 21:02:24 +02:00
// only refresh settings mutable drawn elements
UX_REDISPLAY_IDX ( 7 ) ;
2017-01-22 18:26:27 +01:00
2018-07-27 21:02:24 +02:00
// won't redisplay the bagl_none
return 0 ;
2017-01-22 18:26:27 +01:00
}
2018-08-28 09:12:20 +02:00
const bagl_element_t * ui_settings_blue_toggle_details ( const bagl_element_t * e ) {
// swap setting and request redraw of settings elements
uint8_t setting = N_storage . contractDetails ? 0 : 1 ;
nvm_write ( & N_storage . contractDetails , ( void * ) & setting , sizeof ( uint8_t ) ) ;
// only refresh settings mutable drawn elements
UX_REDISPLAY_IDX ( 7 ) ;
// won't redisplay the bagl_none
return 0 ;
}
2017-01-22 18:26:27 +01:00
// don't perform any draw/color change upon finger event over settings
2018-07-27 21:02:24 +02:00
const bagl_element_t * ui_settings_out_over ( const bagl_element_t * e ) {
return NULL ;
2017-01-22 18:26:27 +01:00
}
2018-07-27 21:02:24 +02:00
unsigned int ui_settings_back_callback ( const bagl_element_t * e ) {
// go back to idle
ui_idle ( ) ;
return 0 ;
2017-01-22 18:26:27 +01:00
}
const bagl_element_t ui_settings_blue [ ] = {
2018-07-27 21:02:24 +02:00
// type userid x y w h str rad fill fg bg fid iid txt touchparams... ]
{ { BAGL_RECTANGLE , 0x00 , 0 , 68 , 320 , 413 , 0 , 0 , BAGL_FILL , COLOR_BG_1 , 0x000000 , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
2017-01-22 18:26:27 +01:00
2018-07-27 21:02:24 +02:00
// erase screen (only under the status bar)
{ { BAGL_RECTANGLE , 0x00 , 0 , 20 , 320 , 48 , 0 , 0 , BAGL_FILL , COLOR_APP , COLOR_APP , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
/// TOP STATUS BAR
{ { BAGL_LABELINE , 0x00 , 0 , 45 , 320 , 30 , 0 , 0 , BAGL_FILL , 0xFFFFFF , COLOR_APP , BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " SETTINGS " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE , 0x00 , 0 , 19 , 50 , 44 , 0 , 0 , BAGL_FILL , COLOR_APP , COLOR_APP_LIGHT , BAGL_FONT_SYMBOLS_0 | BAGL_FONT_ALIGNMENT_CENTER | BAGL_FONT_ALIGNMENT_MIDDLE , 0 } , BAGL_FONT_SYMBOLS_0_LEFT , 0 , COLOR_APP , 0xFFFFFF , ui_settings_back_callback , NULL , NULL } ,
//{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 264, 19, 56, 44, 0, 0, BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT, BAGL_FONT_SYMBOLS_0|BAGL_FONT_ALIGNMENT_CENTER|BAGL_FONT_ALIGNMENT_MIDDLE, 0 }, BAGL_FONT_SYMBOLS_0_DASHBOARD, 0, COLOR_APP, 0xFFFFFF, io_seproxyhal_touch_exit, NULL, NULL},
{ { BAGL_LABELINE , 0x00 , 30 , 105 , 160 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , " Contract data " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x00 , 30 , 126 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x999999 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_8_11PX , 0 } , " Allow contract data in transactions " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_NONE | BAGL_FLAG_TOUCHABLE , 0x00 , 0 , 78 , 320 , 68 , 0 , 0 , BAGL_FILL , 0xFFFFFF , 0x000000 , 0 , 0 } , NULL , 0 , 0xEEEEEE , 0x000000 , ui_settings_blue_toggle_data , ui_settings_out_over , ui_settings_out_over } ,
2018-08-28 09:12:20 +02:00
{ { BAGL_RECTANGLE , 0x00 , 30 , 146 , 260 , 1 , 1 , 0 , 0 , 0xEEEEEE , COLOR_BG_1 , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x00 , 30 , 174 , 160 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , " Display data " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x00 , 30 , 195 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x999999 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_8_11PX , 0 } , " Display contract data details " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_NONE | BAGL_FLAG_TOUCHABLE , 0x00 , 0 , 147 , 320 , 68 , 0 , 0 , BAGL_FILL , 0xFFFFFF , 0x000000 , 0 , 0 } , NULL , 0 , 0xEEEEEE , 0x000000 , ui_settings_blue_toggle_details , ui_settings_out_over , ui_settings_out_over } ,
{ { BAGL_ICON , 0x02 , 258 , 167 , 32 , 18 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
2018-07-27 21:02:24 +02:00
{ { BAGL_ICON , 0x01 , 258 , 98 , 32 , 18 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
2017-01-22 18:26:27 +01:00
} ;
2018-07-27 21:02:24 +02:00
const bagl_element_t * ui_settings_blue_prepro ( const bagl_element_t * e ) {
copy_element_and_map_coin_colors ( e ) ;
// none elements are skipped
if ( ( e - > component . type & ( ~ BAGL_FLAG_TOUCHABLE ) ) = = BAGL_NONE ) {
return 0 ;
}
// swap icon buffer to be displayed depending on if corresponding setting is enabled or not.
if ( e - > component . userid ) {
switch ( e - > component . userid ) {
case 0x01 :
// swap icon content
if ( N_storage . dataAllowed ) {
tmp_element . text = & C_icon_toggle_set ;
}
else {
tmp_element . text = & C_icon_toggle_reset ;
2017-01-22 18:26:27 +01:00
}
2018-07-27 21:02:24 +02:00
break ;
2018-08-28 09:12:20 +02:00
case 0x02 :
// swap icon content
if ( N_storage . contractDetails ) {
tmp_element . text = & C_icon_toggle_set ;
}
else {
tmp_element . text = & C_icon_toggle_reset ;
}
break ;
2017-01-22 18:26:27 +01:00
}
2018-07-27 21:02:24 +02:00
}
return & tmp_element ;
2017-01-22 18:26:27 +01:00
}
2018-07-27 21:02:24 +02:00
unsigned int ui_settings_blue_button ( unsigned int button_mask , unsigned int button_mask_counter ) {
2018-12-19 17:02:00 +01:00
return 0 ;
2017-01-22 18:26:27 +01:00
}
2017-05-31 21:51:11 +02:00
# endif // #if defined(TARGET_BLUE)
2017-01-22 18:26:27 +01:00
2018-07-27 21:02:24 +02:00
2017-05-31 21:51:11 +02:00
# if defined(TARGET_BLUE)
2017-01-22 18:26:27 +01:00
// reuse addressSummary for each line content
2018-07-27 21:02:24 +02:00
const char * ui_details_title ;
const char * ui_details_content ;
2017-01-22 18:26:27 +01:00
typedef void ( * callback_t ) ( void ) ;
callback_t ui_details_back_callback ;
2018-07-27 21:02:24 +02:00
const bagl_element_t * ui_details_blue_back_callback ( const bagl_element_t * element ) {
ui_details_back_callback ( ) ;
return 0 ;
2017-01-22 18:26:27 +01:00
}
2018-07-27 21:02:24 +02:00
2017-01-22 18:26:27 +01:00
const bagl_element_t ui_details_blue [ ] = {
2018-07-27 21:02:24 +02:00
// erase screen (only under the status bar)
{ { BAGL_RECTANGLE , 0x00 , 0 , 68 , 320 , 413 , 0 , 0 , BAGL_FILL , COLOR_BG_1 , 0x000000 , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_RECTANGLE , 0x00 , 0 , 20 , 320 , 48 , 0 , 0 , BAGL_FILL , COLOR_APP , COLOR_APP , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
/// TOP STATUS BAR
{ { BAGL_LABELINE , 0x01 , 0 , 45 , 320 , 30 , 0 , 0 , BAGL_FILL , 0xFFFFFF , COLOR_APP , BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER , 0 } , addressSummary , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE , 0x00 , 0 , 19 , 50 , 44 , 0 , 0 , BAGL_FILL , COLOR_APP , COLOR_APP_LIGHT , BAGL_FONT_SYMBOLS_0 | BAGL_FONT_ALIGNMENT_CENTER | BAGL_FONT_ALIGNMENT_MIDDLE , 0 } , BAGL_FONT_SYMBOLS_0_LEFT , 0 , COLOR_APP , 0xFFFFFF , ui_details_blue_back_callback , NULL , NULL } ,
//{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 264, 19, 56, 44, 0, 0, BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT, BAGL_FONT_SYMBOLS_0|BAGL_FONT_ALIGNMENT_CENTER|BAGL_FONT_ALIGNMENT_MIDDLE, 0 }, " " /*BAGL_FONT_SYMBOLS_0_DASHBOARD*/, 0, COLOR_APP, 0xFFFFFF, io_seproxyhal_touch_exit, NULL, NULL},
{ { BAGL_LABELINE , 0x00 , 30 , 106 , 320 , 30 , 0 , 0 , BAGL_FILL , 0x999999 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX , 0 } , " VALUE " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x10 , 30 , 136 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , addressSummary , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x11 , 30 , 159 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , addressSummary , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x12 , 30 , 182 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , addressSummary , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x13 , 30 , 205 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , addressSummary , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x14 , 30 , 228 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , addressSummary , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x15 , 30 , 251 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , addressSummary , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x16 , 30 , 274 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , addressSummary , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x17 , 30 , 297 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , addressSummary , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x18 , 30 , 320 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , addressSummary , 0 , 0 , 0 , NULL , NULL , NULL } ,
//"..." at the end if too much
{ { BAGL_LABELINE , 0x19 , 30 , 343 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , addressSummary , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x00 , 0 , 450 , 320 , 14 , 0 , 0 , 0 , 0x999999 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_8_11PX | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " Review the whole value before continuing. " , 10 , 0 , COLOR_BG_1 , NULL , NULL , NULL } ,
2016-06-01 21:41:29 +02:00
} ;
2017-01-22 18:26:27 +01:00
2018-07-27 21:02:24 +02:00
const bagl_element_t * ui_details_blue_prepro ( const bagl_element_t * element ) {
copy_element_and_map_coin_colors ( element ) ;
if ( element - > component . userid = = 1 ) {
tmp_element . text = ui_details_title ;
return & tmp_element ;
}
else if ( element - > component . userid > 0 ) {
unsigned int length = strlen ( ui_details_content ) ;
if ( length > = ( element - > component . userid & 0xF ) * MAX_CHAR_PER_LINE ) {
os_memset ( addressSummary , 0 , MAX_CHAR_PER_LINE + 1 ) ;
os_memmove ( addressSummary , ui_details_content + ( element - > component . userid & 0xF ) * MAX_CHAR_PER_LINE , MIN ( length - ( element - > component . userid & 0xF ) * MAX_CHAR_PER_LINE , MAX_CHAR_PER_LINE ) ) ;
return & tmp_element ;
2017-01-22 18:26:27 +01:00
}
2018-07-27 21:02:24 +02:00
// nothing to draw for this line
return 0 ;
}
return & tmp_element ;
2017-01-22 18:26:27 +01:00
}
2018-07-27 21:02:24 +02:00
unsigned int ui_details_blue_button ( unsigned int button_mask , unsigned int button_mask_counter ) {
return 0 ;
2016-07-31 09:36:00 +02:00
}
2018-07-27 21:02:24 +02:00
void ui_details_init ( const char * title , const char * content , callback_t back_callback ) {
ui_details_title = title ;
ui_details_content = content ;
ui_details_back_callback = back_callback ;
UX_DISPLAY ( ui_details_blue , ui_details_blue_prepro ) ;
2017-01-22 18:26:27 +01:00
}
void ui_approval_blue_init ( void ) ;
2017-05-31 21:51:11 +02:00
bagl_element_callback_t ui_approval_blue_ok ;
bagl_element_callback_t ui_approval_blue_cancel ;
2018-07-27 21:02:24 +02:00
const bagl_element_t * ui_approval_blue_ok_callback ( const bagl_element_t * e ) {
return ui_approval_blue_ok ( e ) ;
2017-05-31 21:51:11 +02:00
}
2018-07-27 21:02:24 +02:00
const bagl_element_t * ui_approval_blue_cancel_callback ( const bagl_element_t * e ) {
return ui_approval_blue_cancel ( e ) ;
2017-05-31 21:51:11 +02:00
}
typedef enum {
2018-12-19 17:02:00 +01:00
APPROVAL_TRANSACTION ,
APPROVAL_MESSAGE ,
2017-05-31 21:51:11 +02:00
} ui_approval_blue_state_t ;
ui_approval_blue_state_t G_ui_approval_blue_state ;
// pointer to value to be displayed
2018-07-27 21:02:24 +02:00
const char * ui_approval_blue_values [ 3 ] ;
2017-05-31 21:51:11 +02:00
// variable part of the structure
2018-07-27 21:02:24 +02:00
const char * const ui_approval_blue_details_name [ ] [ 5 ] = {
2018-12-19 17:02:00 +01:00
/*APPROVAL_TRANSACTION*/
2018-07-27 21:02:24 +02:00
{ " AMOUNT " , " ADDRESS " , " MAX FEES " , " CONFIRM TRANSACTION " , " Transaction details " , } ,
2018-12-19 17:02:00 +01:00
/*APPROVAL_MESSAGE*/
{ " HASH " , NULL , NULL , " SIGN MESSAGE " , " Message signature " , } ,
2017-05-31 21:51:11 +02:00
} ;
2018-07-27 21:02:24 +02:00
const bagl_element_t * ui_approval_blue_1_details ( const bagl_element_t * e ) {
if ( strlen ( ui_approval_blue_values [ 0 ] ) * BAGL_FONT_OPEN_SANS_LIGHT_16_22PX_AVG_WIDTH > = 160 ) {
// display details screen
ui_details_init ( ui_approval_blue_details_name [ G_ui_approval_blue_state ] [ 0 ] , ui_approval_blue_values [ 0 ] , ui_approval_blue_init ) ;
}
return 0 ;
2017-01-22 18:26:27 +01:00
} ;
2018-07-27 21:02:24 +02:00
const bagl_element_t * ui_approval_blue_2_details ( const bagl_element_t * e ) {
if ( strlen ( ui_approval_blue_values [ 1 ] ) * BAGL_FONT_OPEN_SANS_REGULAR_10_13PX_AVG_WIDTH > = 160 ) {
ui_details_init ( ui_approval_blue_details_name [ G_ui_approval_blue_state ] [ 1 ] , ui_approval_blue_values [ 1 ] , ui_approval_blue_init ) ;
}
return 0 ;
2017-01-22 18:26:27 +01:00
} ;
2018-07-27 21:02:24 +02:00
const bagl_element_t * ui_approval_blue_3_details ( const bagl_element_t * e ) {
if ( strlen ( ui_approval_blue_values [ 2 ] ) * BAGL_FONT_OPEN_SANS_REGULAR_10_13PX_AVG_WIDTH > = 160 ) {
ui_details_init ( ui_approval_blue_details_name [ G_ui_approval_blue_state ] [ 2 ] , ui_approval_blue_values [ 2 ] , ui_approval_blue_init ) ;
}
return 0 ;
2017-01-22 18:26:27 +01:00
} ;
const bagl_element_t ui_approval_blue [ ] = {
2018-07-27 21:02:24 +02:00
{ { BAGL_RECTANGLE , 0x00 , 0 , 68 , 320 , 413 , 0 , 0 , BAGL_FILL , COLOR_BG_1 , 0x000000 , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
// erase screen (only under the status bar)
{ { BAGL_RECTANGLE , 0x00 , 0 , 20 , 320 , 48 , 0 , 0 , BAGL_FILL , COLOR_APP , COLOR_APP , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
/// TOP STATUS BAR
{ { BAGL_LABELINE , 0x60 , 0 , 45 , 320 , 30 , 0 , 0 , BAGL_FILL , 0xFFFFFF , COLOR_APP , BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
// BADGE_TRANSACTION.GIF
{ { BAGL_ICON , 0x40 , 30 , 98 , 50 , 50 , 0 , 0 , BAGL_FILL , 0 , COLOR_BG_1 , 0 , 0 } , & C_badge_transaction , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x50 , 100 , 117 , 320 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x00 , 100 , 138 , 320 , 30 , 0 , 0 , BAGL_FILL , 0x999999 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_8_11PX , 0 } , " Check and confirm values " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x70 , 30 , 196 , 100 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } , // AMOUNT
// x-18 when ...
{ { BAGL_LABELINE , 0x10 , 130 , 200 , 160 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_LIGHT_16_22PX | BAGL_FONT_ALIGNMENT_RIGHT , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } , // fullAmount
{ { BAGL_LABELINE , 0x20 , 284 , 196 , 6 , 16 , 0 , 0 , BAGL_FILL , 0x999999 , COLOR_BG_1 , BAGL_FONT_SYMBOLS_0 | BAGL_FONT_ALIGNMENT_RIGHT , 0 } , BAGL_FONT_SYMBOLS_0_MINIRIGHT , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_NONE | BAGL_FLAG_TOUCHABLE , 0x00 , 0 , 168 , 320 , 48 , 0 , 9 , BAGL_FILL , 0xFFFFFF , 0x000000 , 0 , 0 } , NULL , 0 , 0xEEEEEE , 0x000000 , ui_approval_blue_1_details , ui_menu_item_out_over , ui_menu_item_out_over } ,
{ { BAGL_RECTANGLE , 0x20 , 0 , 168 , 5 , 48 , 0 , 0 , BAGL_FILL , COLOR_BG_1 , COLOR_BG_1 , 0 , 0 } , NULL , 0 , 0x41CCB4 , 0 , NULL , NULL , NULL } ,
2018-12-19 17:02:00 +01:00
2018-07-27 21:02:24 +02:00
{ { BAGL_RECTANGLE , 0x31 , 30 , 216 , 260 , 1 , 1 , 0 , 0 , 0xEEEEEE , COLOR_BG_1 , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x71 , 30 , 245 , 100 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } , // ADDRESS
// x-18 when ...
{ { BAGL_LABELINE , 0x11 , 130 , 245 , 160 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } , // fullAddress
{ { BAGL_LABELINE , 0x21 , 284 , 245 , 6 , 16 , 0 , 0 , BAGL_FILL , 0x999999 , COLOR_BG_1 , BAGL_FONT_SYMBOLS_0 | BAGL_FONT_ALIGNMENT_RIGHT , 0 } , BAGL_FONT_SYMBOLS_0_MINIRIGHT , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_NONE | BAGL_FLAG_TOUCHABLE , 0x00 , 0 , 217 , 320 , 48 , 0 , 9 , BAGL_FILL , 0xFFFFFF , 0x000000 , 0 , 0 } , NULL , 0 , 0xEEEEEE , 0x000000 , ui_approval_blue_2_details , ui_menu_item_out_over , ui_menu_item_out_over } ,
2018-12-19 17:02:00 +01:00
{ { BAGL_RECTANGLE , 0x21 , 0 , 217 , 5 , 48 , 0 , 0 , BAGL_FILL , COLOR_BG_1 , COLOR_BG_1 , 0 , 0 } , NULL , 0 , 0x41CCB4 , 0 , NULL , NULL , NULL } ,
2018-07-27 21:02:24 +02:00
{ { BAGL_RECTANGLE , 0x32 , 30 , 265 , 260 , 1 , 1 , 0 , 0 , 0xEEEEEE , COLOR_BG_1 , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
2018-12-19 17:02:00 +01:00
2018-07-27 21:02:24 +02:00
{ { BAGL_LABELINE , 0x72 , 30 , 294 , 100 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } , // MAX FEES
// x-18 when ...
{ { BAGL_LABELINE , 0x12 , 130 , 294 , 160 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } , //maxFee
{ { BAGL_LABELINE , 0x22 , 284 , 294 , 6 , 16 , 0 , 0 , BAGL_FILL , 0x999999 , COLOR_BG_1 , BAGL_FONT_SYMBOLS_0 | BAGL_FONT_ALIGNMENT_RIGHT , 0 } , BAGL_FONT_SYMBOLS_0_MINIRIGHT , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_NONE | BAGL_FLAG_TOUCHABLE , 0x00 , 0 , 266 , 320 , 48 , 0 , 9 , BAGL_FILL , 0xFFFFFF , 0x000000 , 0 , 0 } , NULL , 0 , 0xEEEEEE , 0x000000 , ui_approval_blue_3_details , ui_menu_item_out_over , ui_menu_item_out_over } ,
{ { BAGL_RECTANGLE , 0x22 , 0 , 266 , 5 , 48 , 0 , 0 , BAGL_FILL , COLOR_BG_1 , COLOR_BG_1 , 0 , 0 } , NULL , 0 , 0x41CCB4 , 0 , NULL , NULL , NULL } ,
2018-08-28 09:12:20 +02:00
{ { BAGL_RECTANGLE , 0x90 , 30 , 314 , 260 , 1 , 1 , 0 , 0 , 0xEEEEEE , COLOR_BG_1 , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x90 , 30 , 343 , 120 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX , 0 } , " CONTRACT DATA " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x90 , 133 , 343 , 140 , 30 , 0 , 0 , BAGL_FILL , 0x666666 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT , 0 } , " Present " , 0 , 0 , 0 , NULL , NULL , NULL } ,
2018-12-19 17:02:00 +01:00
{ { BAGL_ICON , 0x90 , 278 , 333 , 12 , 12 , 0 , 0 , BAGL_FILL , 0 , COLOR_BG_1 , 0 , 0 } , & C_icon_warning , 0 , 0 , 0 , NULL , NULL , NULL } ,
2018-07-27 21:02:24 +02:00
{ { BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE , 0x00 , 40 , 414 , 115 , 36 , 0 , 18 , BAGL_FILL , 0xCCCCCC , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | BAGL_FONT_ALIGNMENT_MIDDLE , 0 } , " REJECT " , 0 , 0xB7B7B7 , COLOR_BG_1 , ui_approval_blue_cancel_callback , NULL , NULL } ,
{ { BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE , 0x00 , 165 , 414 , 115 , 36 , 0 , 18 , BAGL_FILL , 0x41ccb4 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | BAGL_FONT_ALIGNMENT_MIDDLE , 0 } , " CONFIRM " , 0 , 0x3ab7a2 , COLOR_BG_1 , ui_approval_blue_ok_callback , NULL , NULL } ,
2017-05-31 21:51:11 +02:00
} ;
2018-07-27 21:02:24 +02:00
const bagl_element_t * ui_approval_blue_prepro ( const bagl_element_t * element ) {
copy_element_and_map_coin_colors ( element ) ;
2017-05-31 21:51:11 +02:00
if ( element - > component . userid = = 0 ) {
2018-07-27 21:02:24 +02:00
return & tmp_element ;
2017-05-31 21:51:11 +02:00
}
// none elements are skipped
2018-07-27 21:02:24 +02:00
if ( ( element - > component . type & ( ~ BAGL_FLAG_TOUCHABLE ) ) = = BAGL_NONE ) {
return 0 ;
}
else {
switch ( element - > component . userid & 0xF0 ) {
2017-05-31 21:51:11 +02:00
// icon
case 0x40 :
2018-12-19 17:02:00 +01:00
return & tmp_element ;
2018-07-27 21:02:24 +02:00
break ;
2018-12-19 17:02:00 +01:00
2017-05-31 21:51:11 +02:00
// TITLE
2018-12-19 17:02:00 +01:00
case 0x60 :
2018-07-27 21:02:24 +02:00
tmp_element . text = ui_approval_blue_details_name [ G_ui_approval_blue_state ] [ 3 ] ;
return & tmp_element ;
break ;
2018-12-19 17:02:00 +01:00
2017-05-31 21:51:11 +02:00
// SUBLINE
2018-12-19 17:02:00 +01:00
case 0x50 :
2018-07-27 21:02:24 +02:00
tmp_element . text = ui_approval_blue_details_name [ G_ui_approval_blue_state ] [ 4 ] ;
return & tmp_element ;
2017-05-31 21:51:11 +02:00
// details label
case 0x70 :
2018-07-27 21:02:24 +02:00
if ( ! ui_approval_blue_details_name [ G_ui_approval_blue_state ] [ element - > component . userid & 0xF ] ) {
return NULL ;
}
tmp_element . text = ui_approval_blue_details_name [ G_ui_approval_blue_state ] [ element - > component . userid & 0xF ] ;
return & tmp_element ;
2017-05-31 21:51:11 +02:00
// detail value
case 0x10 :
2018-07-27 21:02:24 +02:00
// won't display
if ( ! ui_approval_blue_details_name [ G_ui_approval_blue_state ] [ element - > component . userid & 0xF ] ) {
return NULL ;
}
// always display the value
tmp_element . text = ui_approval_blue_values [ ( element - > component . userid & 0xF ) ] ;
// x -= 18 when overflow is detected
if ( strlen ( ui_approval_blue_values [ ( element - > component . userid & 0xF ) ] ) * BAGL_FONT_OPEN_SANS_LIGHT_16_22PX_AVG_WIDTH > = 160 ) {
tmp_element . component . x - = 18 ;
}
return & tmp_element ;
break ;
2017-05-31 21:51:11 +02:00
// right arrow and left selection rectangle
case 0x20 :
2018-07-27 21:02:24 +02:00
if ( ! ui_approval_blue_details_name [ G_ui_approval_blue_state ] [ element - > component . userid & 0xF ] ) {
return NULL ;
}
if ( strlen ( ui_approval_blue_values [ ( element - > component . userid & 0xF ) ] ) * BAGL_FONT_OPEN_SANS_LIGHT_16_22PX_AVG_WIDTH < 160 ) {
return NULL ;
}
2017-05-31 21:51:11 +02:00
// horizontal delimiter
case 0x30 :
2018-07-27 21:02:24 +02:00
return ui_approval_blue_details_name [ G_ui_approval_blue_state ] [ element - > component . userid & 0xF ] ! = NULL ? & tmp_element : NULL ;
2018-08-28 09:12:20 +02:00
case 0x90 :
return ( dataPresent & & ! N_storage . contractDetails ) ;
2018-07-27 21:02:24 +02:00
}
2017-05-31 21:51:11 +02:00
}
2018-07-27 21:02:24 +02:00
return & tmp_element ;
2017-05-31 21:51:11 +02:00
}
2018-07-27 21:02:24 +02:00
unsigned int ui_approval_blue_button ( unsigned int button_mask , unsigned int button_mask_counter ) {
return 0 ;
2017-05-31 21:51:11 +02:00
}
# endif // #if defined(TARGET_BLUE)
# if defined(TARGET_BLUE)
const bagl_element_t ui_address_blue [ ] = {
2018-07-27 21:02:24 +02:00
{ { BAGL_RECTANGLE , 0x00 , 0 , 68 , 320 , 413 , 0 , 0 , BAGL_FILL , COLOR_BG_1 , 0x000000 , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
// erase screen (only under the status bar)
{ { BAGL_RECTANGLE , 0x00 , 0 , 20 , 320 , 48 , 0 , 0 , BAGL_FILL , COLOR_APP , COLOR_APP , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
/// TOP STATUS BAR
{ { BAGL_LABELINE , 0x00 , 0 , 45 , 320 , 30 , 0 , 0 , BAGL_FILL , 0xFFFFFF , COLOR_APP , BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " CONFIRM ACCOUNT " , 0 , 0 , 0 , NULL , NULL , NULL } ,
//{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 264, 19, 56, 44, 0, 0, BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT, BAGL_FONT_SYMBOLS_0|BAGL_FONT_ALIGNMENT_CENTER|BAGL_FONT_ALIGNMENT_MIDDLE, 0 }, " " /*BAGL_FONT_SYMBOLS_0_DASHBOARD*/, 0, COLOR_APP, 0xFFFFFF, io_seproxyhal_touch_exit, NULL, NULL},
{ { BAGL_LABELINE , 0x00 , 30 , 106 , 320 , 30 , 0 , 0 , BAGL_FILL , 0x999999 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX , 0 } , " ACCOUNT " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x10 , 30 , 136 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , addressSummary , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x11 , 30 , 159 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , addressSummary , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE , 0x00 , 40 , 414 , 115 , 36 , 0 , 18 , BAGL_FILL , 0xCCCCCC , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | BAGL_FONT_ALIGNMENT_MIDDLE , 0 } , " REJECT " , 0 , 0xB7B7B7 , COLOR_BG_1 , io_seproxyhal_touch_address_cancel , NULL , NULL } ,
{ { BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE , 0x00 , 165 , 414 , 115 , 36 , 0 , 18 , BAGL_FILL , 0x41ccb4 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | BAGL_FONT_ALIGNMENT_MIDDLE , 0 } , " CONFIRM " , 0 , 0x3ab7a2 , COLOR_BG_1 , io_seproxyhal_touch_address_ok , NULL , NULL } ,
2017-05-31 21:51:11 +02:00
} ;
2018-07-27 21:02:24 +02:00
unsigned int ui_address_blue_prepro ( const bagl_element_t * element ) {
copy_element_and_map_coin_colors ( element ) ;
if ( element - > component . userid > 0 ) {
2018-07-31 19:59:59 +02:00
unsigned int length = strlen ( strings . common . fullAddress ) ;
2018-07-27 21:02:24 +02:00
if ( length > = ( element - > component . userid & 0xF ) * MAX_CHAR_PER_LINE ) {
os_memset ( addressSummary , 0 , MAX_CHAR_PER_LINE + 1 ) ;
2018-07-31 19:59:59 +02:00
os_memmove ( addressSummary , strings . common . fullAddress + ( element - > component . userid & 0xF ) * MAX_CHAR_PER_LINE , MIN ( length - ( element - > component . userid & 0xF ) * MAX_CHAR_PER_LINE , MAX_CHAR_PER_LINE ) ) ;
2018-07-27 21:02:24 +02:00
return & tmp_element ;
2017-05-31 21:51:11 +02:00
}
2018-07-27 21:02:24 +02:00
// nothing to draw for this line
return 0 ;
}
return & tmp_element ;
2017-05-31 21:51:11 +02:00
}
2018-07-27 21:02:24 +02:00
unsigned int ui_address_blue_button ( unsigned int button_mask , unsigned int button_mask_counter ) {
return 0 ;
2017-05-31 21:51:11 +02:00
}
# endif // #if defined(TARGET_BLUE)
2020-01-18 12:47:53 +01:00
# if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW)
2017-05-31 21:51:11 +02:00
const bagl_element_t ui_address_nanos [ ] = {
2018-07-27 21:02:24 +02:00
// 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 } ,
{ { BAGL_ICON , 0x00 , 3 , 12 , 7 , 7 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , 0 , BAGL_GLYPH_ICON_CROSS } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_ICON , 0x00 , 117 , 13 , 8 , 6 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , 0 , BAGL_GLYPH_ICON_CHECK } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
2018-12-19 17:02:00 +01:00
//{{BAGL_ICON , 0x01, 31, 9, 14, 14, 0, 0, 0 , 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_EYE_BADGE }, NULL, 0, 0, 0, NULL, NULL, NULL },
2018-07-27 21:02:24 +02:00
{ { BAGL_LABELINE , 0x01 , 0 , 12 , 128 , 12 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " Confirm " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x01 , 0 , 26 , 128 , 12 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " address " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x02 , 0 , 12 , 128 , 12 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " Address " , 0 , 0 , 0 , NULL , NULL , NULL } ,
2018-07-31 19:59:59 +02:00
{ { BAGL_LABELINE , 0x02 , 23 , 26 , 82 , 12 , 0x80 | 10 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 26 } , ( char * ) strings . common . fullAddress , 0 , 0 , 0 , NULL , NULL , NULL } ,
2016-06-01 21:41:29 +02:00
} ;
2017-01-22 18:26:27 +01:00
2018-07-27 21:02:24 +02:00
unsigned int ui_address_prepro ( const bagl_element_t * element ) {
2017-05-31 21:51:11 +02:00
if ( element - > component . userid > 0 ) {
2018-07-27 21:02:24 +02:00
unsigned int display = ( ux_step = = element - > component . userid - 1 ) ;
if ( display ) {
switch ( element - > component . userid ) {
case 1 :
UX_CALLBACK_SET_INTERVAL ( 2000 ) ;
break ;
case 2 :
UX_CALLBACK_SET_INTERVAL ( MAX ( 3000 , 1000 + bagl_label_roundtrip_duration_ms ( element , 7 ) ) ) ;
break ;
}
2017-01-22 18:26:27 +01:00
}
2017-05-31 21:51:11 +02:00
return display ;
2017-01-22 18:26:27 +01:00
}
return 1 ;
}
2016-06-01 21:41:29 +02:00
2018-07-27 21:02:24 +02:00
unsigned int ui_address_nanos_button ( unsigned int button_mask , unsigned int button_mask_counter ) ;
2020-01-18 12:47:53 +01:00
# endif // #if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW)
2018-07-27 21:02:24 +02:00
2020-01-18 12:47:53 +01:00
# if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW)
2016-07-31 09:36:00 +02:00
const bagl_element_t ui_approval_nanos [ ] = {
2018-07-27 21:02:24 +02:00
// 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 } ,
{ { BAGL_ICON , 0x00 , 3 , 12 , 7 , 7 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , 0 , BAGL_GLYPH_ICON_CROSS } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_ICON , 0x00 , 117 , 13 , 8 , 6 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , 0 , BAGL_GLYPH_ICON_CHECK } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
2018-12-19 17:02:00 +01:00
//{{BAGL_ICON , 0x01, 21, 9, 14, 14, 0, 0, 0 , 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_TRANSACTION_BADGE }, NULL, 0, 0, 0, NULL, NULL, NULL },
2018-07-27 21:02:24 +02:00
{ { BAGL_LABELINE , 0x01 , 0 , 12 , 128 , 32 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " Confirm " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x01 , 0 , 26 , 128 , 32 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " transaction " , 0 , 0 , 0 , NULL , NULL , NULL } ,
2018-08-28 09:12:20 +02:00
{ { BAGL_LABELINE , 0x02 , 0 , 12 , 128 , 32 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " WARNING " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x02 , 23 , 26 , 82 , 12 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " Data present " , 0 , 0 , 0 , NULL , NULL , NULL } ,
2018-07-27 21:02:24 +02:00
2018-08-28 09:12:20 +02:00
{ { BAGL_LABELINE , 0x03 , 0 , 12 , 128 , 32 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " Amount " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x03 , 23 , 26 , 82 , 12 , 0x80 | 10 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 26 } , ( char * ) strings . common . fullAmount , 0 , 0 , 0 , NULL , NULL , NULL } ,
2018-07-27 21:02:24 +02:00
2018-08-28 09:12:20 +02:00
{ { BAGL_LABELINE , 0x04 , 0 , 12 , 128 , 32 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " Address " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x04 , 23 , 26 , 82 , 12 , 0x80 | 10 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 50 } , ( char * ) strings . common . fullAddress , 0 , 0 , 0 , NULL , NULL , NULL } ,
2018-07-27 21:02:24 +02:00
2018-08-28 09:12:20 +02:00
{ { BAGL_LABELINE , 0x05 , 0 , 12 , 128 , 32 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " Maximum fees " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x05 , 23 , 26 , 82 , 12 , 0x80 | 10 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 26 } , ( char * ) strings . common . maxFee , 0 , 0 , 0 , NULL , NULL , NULL } ,
2016-10-17 23:40:31 +02:00
2016-06-01 21:41:29 +02:00
} ;
2018-07-27 21:02:24 +02:00
unsigned int ui_approval_prepro ( const bagl_element_t * element ) {
2016-10-17 23:40:31 +02:00
unsigned int display = 1 ;
2016-07-31 09:36:00 +02:00
if ( element - > component . userid > 0 ) {
2018-07-27 21:02:24 +02:00
display = ( ux_step = = element - > component . userid - 1 ) ;
if ( display ) {
switch ( element - > component . userid ) {
case 1 :
UX_CALLBACK_SET_INTERVAL ( 2000 ) ;
break ;
case 2 :
2018-08-28 09:12:20 +02:00
if ( dataPresent & & ! N_storage . contractDetails ) {
UX_CALLBACK_SET_INTERVAL ( 3000 ) ;
}
else {
display = 0 ;
ux_step + + ; // display the next step
}
2018-07-27 21:02:24 +02:00
break ;
2018-07-31 19:59:59 +02:00
case 3 :
2018-07-27 21:02:24 +02:00
UX_CALLBACK_SET_INTERVAL ( MAX ( 3000 , 1000 + bagl_label_roundtrip_duration_ms ( element , 7 ) ) ) ;
break ;
2018-07-31 19:59:59 +02:00
case 4 :
2018-07-27 21:02:24 +02:00
UX_CALLBACK_SET_INTERVAL ( MAX ( 3000 , 1000 + bagl_label_roundtrip_duration_ms ( element , 7 ) ) ) ;
break ;
2018-08-28 09:12:20 +02:00
case 5 :
UX_CALLBACK_SET_INTERVAL ( MAX ( 3000 , 1000 + bagl_label_roundtrip_duration_ms ( element , 7 ) ) ) ;
break ;
2018-07-27 21:02:24 +02:00
}
2016-07-31 09:36:00 +02:00
}
}
2016-10-17 23:40:31 +02:00
return display ;
2016-07-31 09:36:00 +02:00
}
2018-07-27 21:02:24 +02:00
unsigned int ui_approval_nanos_button ( unsigned int button_mask , unsigned int button_mask_counter ) ;
2017-03-03 13:49:39 +01:00
const bagl_element_t ui_approval_signMessage_nanos [ ] = {
2018-07-27 21:02:24 +02:00
// 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 } ,
2018-12-19 17:02:00 +01:00
2018-07-27 21:02:24 +02:00
{ { BAGL_ICON , 0x00 , 3 , 12 , 7 , 7 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , 0 , BAGL_GLYPH_ICON_CROSS } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_ICON , 0x00 , 117 , 13 , 8 , 6 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , 0 , BAGL_GLYPH_ICON_CHECK } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
//{{BAGL_ICON , 0x01, 28, 9, 14, 14, 0, 0, 0 , 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_TRANSACTION_BADGE }, NULL, 0, 0, 0, NULL, NULL, NULL },
{ { BAGL_LABELINE , 0x01 , 0 , 12 , 128 , 32 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " Sign the " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x01 , 0 , 26 , 128 , 32 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " message " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x02 , 0 , 12 , 128 , 32 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " Message hash " , 0 , 0 , 0 , NULL , NULL , NULL } ,
2018-07-31 19:59:59 +02:00
{ { BAGL_LABELINE , 0x02 , 0 , 26 , 128 , 32 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , strings . common . fullAddress , 0 , 0 , 0 , NULL , NULL , NULL } ,
2017-03-03 13:49:39 +01:00
} ;
unsigned int
2018-07-27 21:02:24 +02:00
ui_approval_signMessage_nanos_button ( unsigned int button_mask , unsigned int button_mask_counter ) ;
2017-03-03 13:49:39 +01:00
unsigned int ui_approval_signMessage_prepro ( const bagl_element_t * element ) {
if ( element - > component . userid > 0 ) {
switch ( element - > component . userid ) {
case 1 :
UX_CALLBACK_SET_INTERVAL ( 2000 ) ;
break ;
case 2 :
UX_CALLBACK_SET_INTERVAL ( 3000 ) ;
break ;
}
return ( ux_step = = element - > component . userid - 1 ) ;
}
return 1 ;
}
2020-01-18 12:47:53 +01:00
# endif // #if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW)
2016-07-31 09:36:00 +02:00
2018-07-31 19:59:59 +02:00
# if defined(TARGET_BLUE)
const bagl_element_t ui_data_selector_blue [ ] = {
{ { BAGL_RECTANGLE , 0x00 , 0 , 68 , 320 , 413 , 0 , 0 , BAGL_FILL , COLOR_BG_1 , 0x000000 , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
// erase screen (only under the status bar)
{ { BAGL_RECTANGLE , 0x00 , 0 , 20 , 320 , 48 , 0 , 0 , BAGL_FILL , COLOR_APP , COLOR_APP , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
/// TOP STATUS BAR
{ { BAGL_LABELINE , 0x00 , 0 , 45 , 320 , 30 , 0 , 0 , BAGL_FILL , 0xFFFFFF , COLOR_APP , BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " CONFIRM SELECTOR " , 0 , 0 , 0 , NULL , NULL , NULL } ,
//{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 264, 19, 56, 44, 0, 0, BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT, BAGL_FONT_SYMBOLS_0|BAGL_FONT_ALIGNMENT_CENTER|BAGL_FONT_ALIGNMENT_MIDDLE, 0 }, " " /*BAGL_FONT_SYMBOLS_0_DASHBOARD*/, 0, COLOR_APP, 0xFFFFFF, io_seproxyhal_touch_exit, NULL, NULL},
{ { BAGL_LABELINE , 0x00 , 30 , 106 , 320 , 30 , 0 , 0 , BAGL_FILL , 0x999999 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX , 0 } , " SELECTOR " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x10 , 30 , 136 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , strings . tmp . tmp , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE , 0x00 , 40 , 414 , 115 , 36 , 0 , 18 , BAGL_FILL , 0xCCCCCC , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | BAGL_FONT_ALIGNMENT_MIDDLE , 0 } , " REJECT " , 0 , 0xB7B7B7 , COLOR_BG_1 , io_seproxyhal_touch_data_cancel , NULL , NULL } ,
{ { BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE , 0x00 , 165 , 414 , 115 , 36 , 0 , 18 , BAGL_FILL , 0x41ccb4 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | BAGL_FONT_ALIGNMENT_MIDDLE , 0 } , " CONFIRM " , 0 , 0x3ab7a2 , COLOR_BG_1 , io_seproxyhal_touch_data_ok , NULL , NULL } ,
} ;
unsigned int ui_data_selector_blue_prepro ( const bagl_element_t * element ) {
copy_element_and_map_coin_colors ( element ) ;
if ( element - > component . userid > 0 ) {
unsigned int length = strlen ( strings . tmp . tmp ) ;
unsigned int offset = ( element - > component . userid & 0xF ) * 24 ;
if ( length > = offset ) {
unsigned int copyLength = ( ( offset + 24 ) > length ? length - offset : 24 ) ;
os_memset ( addressSummary , 0 , 25 ) ;
os_memmove ( addressSummary , strings . tmp . tmp + offset , copyLength ) ;
return & tmp_element ;
}
// nothing to draw for this line
return 0 ;
}
return & tmp_element ;
}
unsigned int ui_data_selector_blue_button ( unsigned int button_mask , unsigned int button_mask_counter ) {
return 0 ;
}
# endif // #if defined(TARGET_BLUE)
2020-01-18 12:47:53 +01:00
# if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW)
2018-07-31 19:59:59 +02:00
const bagl_element_t ui_data_selector_nanos [ ] = {
// type userid x y w h str rad
// fill fg bg fid iid txt touchparams... ]
2018-08-28 09:12:20 +02:00
{ { BAGL_RECTANGLE , 0x00 , 0 , 0 , 128 , 32 , 0 , 0 , BAGL_FILL , 0x000000 , 0xFFFFFF , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_ICON , 0x00 , 3 , 12 , 7 , 7 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , 0 , BAGL_GLYPH_ICON_CROSS } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_ICON , 0x00 , 117 , 13 , 8 , 6 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , 0 , BAGL_GLYPH_ICON_CHECK } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x01 , 0 , 12 , 128 , 12 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " Confirm " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x01 , 0 , 26 , 128 , 12 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " selector " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x02 , 0 , 12 , 128 , 12 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " Selector " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x02 , 23 , 26 , 82 , 12 , 0x80 | 10 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 26 } , ( char * ) strings . tmp . tmp , 0 , 0 , 0 , NULL , NULL , NULL } ,
2018-07-31 19:59:59 +02:00
} ;
2018-08-03 19:09:06 +02:00
unsigned int ui_data_selector_prepro ( const bagl_element_t * element ) {
if ( element - > component . userid > 0 ) {
unsigned int display = ( ux_step = = element - > component . userid - 1 ) ;
if ( display ) {
switch ( element - > component . userid ) {
case 1 :
UX_CALLBACK_SET_INTERVAL ( 2000 ) ;
break ;
case 2 :
UX_CALLBACK_SET_INTERVAL ( MAX (
3000 , 1000 + bagl_label_roundtrip_duration_ms ( element , 7 ) ) ) ;
break ;
}
}
return display ;
}
return 1 ;
2018-07-31 19:59:59 +02:00
}
unsigned int ui_data_selector_nanos_button ( unsigned int button_mask ,
unsigned int button_mask_counter ) ;
2020-01-18 12:47:53 +01:00
# endif // #if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW)
2018-07-31 19:59:59 +02:00
# if defined(TARGET_BLUE)
const bagl_element_t ui_data_parameter_blue [ ] = {
{ { BAGL_RECTANGLE , 0x00 , 0 , 68 , 320 , 413 , 0 , 0 , BAGL_FILL , COLOR_BG_1 , 0x000000 , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
// erase screen (only under the status bar)
{ { BAGL_RECTANGLE , 0x00 , 0 , 20 , 320 , 48 , 0 , 0 , BAGL_FILL , COLOR_APP , COLOR_APP , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
/// TOP STATUS BAR
{ { BAGL_LABELINE , 0x00 , 0 , 45 , 320 , 30 , 0 , 0 , BAGL_FILL , 0xFFFFFF , COLOR_APP , BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " CONFIRM PARAMETER " , 0 , 0 , 0 , NULL , NULL , NULL } ,
//{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 264, 19, 56, 44, 0, 0, BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT, BAGL_FONT_SYMBOLS_0|BAGL_FONT_ALIGNMENT_CENTER|BAGL_FONT_ALIGNMENT_MIDDLE, 0 }, " " /*BAGL_FONT_SYMBOLS_0_DASHBOARD*/, 0, COLOR_APP, 0xFFFFFF, io_seproxyhal_touch_exit, NULL, NULL},
{ { BAGL_LABELINE , 0x00 , 30 , 106 , 320 , 30 , 0 , 0 , BAGL_FILL , 0x999999 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX , 0 } , " PARAMETER " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x00 , 30 , 136 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , strings . tmp . tmp2 , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x10 , 30 , 159 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , addressSummary , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x11 , 30 , 182 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , addressSummary , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x12 , 30 , 205 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , addressSummary , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x13 , 30 , 228 , 260 , 30 , 0 , 0 , BAGL_FILL , 0x000000 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_10_13PX , 0 } , addressSummary , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE , 0x00 , 40 , 414 , 115 , 36 , 0 , 18 , BAGL_FILL , 0xCCCCCC , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | BAGL_FONT_ALIGNMENT_MIDDLE , 0 } , " REJECT " , 0 , 0xB7B7B7 , COLOR_BG_1 , io_seproxyhal_touch_data_cancel , NULL , NULL } ,
{ { BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE , 0x00 , 165 , 414 , 115 , 36 , 0 , 18 , BAGL_FILL , 0x41ccb4 , COLOR_BG_1 , BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | BAGL_FONT_ALIGNMENT_MIDDLE , 0 } , " CONFIRM " , 0 , 0x3ab7a2 , COLOR_BG_1 , io_seproxyhal_touch_data_ok , NULL , NULL } ,
} ;
unsigned int ui_data_parameter_blue_prepro ( const bagl_element_t * element ) {
copy_element_and_map_coin_colors ( element ) ;
if ( element - > component . userid > 0 ) {
unsigned int pos = ( element - > component . userid & 0xF ) ;
unsigned int i ;
unsigned int offset = 0 ;
unsigned int copyLength ;
for ( i = 0 ; i < pos ; i + + ) {
offset + = local_strchr ( strings . tmp . tmp + offset , ' : ' ) ;
if ( offset < 0 ) {
THROW ( EXCEPTION ) ;
}
offset = offset + 1 ;
}
if ( pos = = 3 ) {
copyLength = strlen ( strings . tmp . tmp ) - offset ;
}
else {
unsigned int endOffset ;
endOffset = offset + local_strchr ( strings . tmp . tmp + offset , ' : ' ) ;
copyLength = endOffset - offset ;
}
os_memmove ( addressSummary , strings . tmp . tmp + offset , copyLength ) ;
addressSummary [ copyLength ] = ' \0 ' ;
}
return & tmp_element ;
}
unsigned int ui_data_parameter_blue_button ( unsigned int button_mask , unsigned int button_mask_counter ) {
return 0 ;
}
# endif // #if defined(TARGET_BLUE)
2020-01-18 12:47:53 +01:00
# if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW)
2018-07-31 19:59:59 +02:00
const bagl_element_t ui_data_parameter_nanos [ ] = {
// type userid x y w h str rad
// fill fg bg fid iid txt touchparams... ]
2018-08-28 09:12:20 +02:00
{ { BAGL_RECTANGLE , 0x00 , 0 , 0 , 128 , 32 , 0 , 0 , BAGL_FILL , 0x000000 , 0xFFFFFF , 0 , 0 } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_ICON , 0x00 , 3 , 12 , 7 , 7 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , 0 , BAGL_GLYPH_ICON_CROSS } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_ICON , 0x00 , 117 , 13 , 8 , 6 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , 0 , BAGL_GLYPH_ICON_CHECK } , NULL , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x01 , 0 , 12 , 128 , 12 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " Confirm " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x01 , 0 , 26 , 128 , 12 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , " parameter " , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x02 , 0 , 12 , 128 , 12 , 0 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER , 0 } , ( char * ) strings . tmp . tmp2 , 0 , 0 , 0 , NULL , NULL , NULL } ,
{ { BAGL_LABELINE , 0x02 , 23 , 26 , 82 , 12 , 0x80 | 10 , 0 , 0 , 0xFFFFFF , 0x000000 , BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER , 26 } , ( char * ) strings . tmp . tmp , 0 , 0 , 0 , NULL , NULL , NULL } ,
2018-07-31 19:59:59 +02:00
} ;
unsigned int ui_data_parameter_prepro ( const bagl_element_t * element ) {
if ( element - > component . userid > 0 ) {
unsigned int display = ( ux_step = = element - > component . userid - 1 ) ;
if ( display ) {
switch ( element - > component . userid ) {
case 1 :
UX_CALLBACK_SET_INTERVAL ( 2000 ) ;
break ;
case 2 :
UX_CALLBACK_SET_INTERVAL ( MAX (
3000 , 1000 + bagl_label_roundtrip_duration_ms ( element , 7 ) ) ) ;
break ;
}
}
return display ;
}
return 1 ;
}
unsigned int ui_data_parameter_nanos_button ( unsigned int button_mask ,
unsigned int button_mask_counter ) ;
2020-01-18 12:47:53 +01:00
# endif // #if defined(TARGET_NANOS) && !defined(HAVE_UX_FLOW)
2018-07-31 19:59:59 +02:00
2020-01-18 12:47:53 +01:00
# if defined(HAVE_UX_FLOW)
2019-02-12 20:41:19 +01:00
void display_settings ( void ) ;
void switch_settings_contract_data ( void ) ;
void switch_settings_display_data ( void ) ;
//////////////////////////////////////////////////////////////////////
UX_FLOW_DEF_NOCB (
2019-03-18 14:03:54 +01:00
ux_idle_flow_1_step ,
2020-01-18 12:47:53 +01:00
nn , //pnn,
2019-02-12 20:41:19 +01:00
{
2020-01-18 12:47:53 +01:00
//"", //&C_icon_dashboard,
2019-02-12 20:41:19 +01:00
" Application " ,
" is ready " ,
} ) ;
UX_FLOW_DEF_NOCB (
2019-03-18 14:03:54 +01:00
ux_idle_flow_2_step ,
bn ,
2019-02-12 20:41:19 +01:00
{
" Version " ,
APPVERSION ,
} ) ;
UX_FLOW_DEF_VALID (
ux_idle_flow_3_step ,
pb ,
display_settings ( ) ,
{
& C_icon_eye ,
" Settings " ,
} ) ;
UX_FLOW_DEF_VALID (
ux_idle_flow_4_step ,
pb ,
os_sched_exit ( - 1 ) ,
{
2020-01-18 12:47:53 +01:00
& C_icon_dashboard_x ,
2019-02-12 20:41:19 +01:00
" Quit " ,
} ) ;
const ux_flow_step_t * const ux_idle_flow [ ] = {
& ux_idle_flow_1_step ,
& ux_idle_flow_2_step ,
& ux_idle_flow_3_step ,
& ux_idle_flow_4_step ,
FLOW_END_STEP ,
} ;
2020-01-18 12:47:53 +01:00
# 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
2019-02-12 20:41:19 +01:00
UX_FLOW_DEF_VALID (
2019-03-18 14:03:54 +01:00
ux_settings_flow_1_step ,
bnnn ,
2019-02-12 20:41:19 +01:00
switch_settings_contract_data ( ) ,
{
" Contract data " ,
" Allow contract data " ,
" in transactions " ,
strings . common . fullAddress ,
} ) ;
UX_FLOW_DEF_VALID (
2019-03-18 14:03:54 +01:00
ux_settings_flow_2_step ,
bnnn ,
2019-02-12 20:41:19 +01:00
switch_settings_display_data ( ) ,
{
2020-01-18 12:47:53 +01:00
" Debug data " ,
2019-02-12 20:41:19 +01:00
" Display contract data " ,
" details " ,
strings . common . fullAddress + 20
} ) ;
2020-01-18 12:47:53 +01:00
# endif
2019-02-12 20:41:19 +01:00
UX_FLOW_DEF_VALID (
ux_settings_flow_3_step ,
pb ,
ui_idle ( ) ,
{
2020-01-18 12:47:53 +01:00
& C_icon_back_x ,
2019-02-12 20:41:19 +01:00
" Back " ,
} ) ;
const ux_flow_step_t * const ux_settings_flow [ ] = {
& ux_settings_flow_1_step ,
& ux_settings_flow_2_step ,
& ux_settings_flow_3_step ,
FLOW_END_STEP ,
} ;
void display_settings ( ) {
strcpy ( strings . common . fullAddress , ( N_storage . dataAllowed ? " Allowed " : " NOT Allowed " ) ) ;
strcpy ( strings . common . fullAddress + 20 , ( N_storage . contractDetails ? " Displayed " : " NOT Displayed " ) ) ;
2019-03-18 14:03:54 +01:00
ux_flow_init ( 0 , ux_settings_flow , NULL ) ;
2019-02-12 20:41:19 +01:00
}
void switch_settings_contract_data ( ) {
uint8_t value = ( N_storage . dataAllowed ? 0 : 1 ) ;
nvm_write ( & N_storage . dataAllowed , ( void * ) & value , sizeof ( uint8_t ) ) ;
display_settings ( ) ;
}
void switch_settings_display_data ( ) {
uint8_t value = ( N_storage . contractDetails ? 0 : 1 ) ;
nvm_write ( & N_storage . contractDetails , ( void * ) & value , sizeof ( uint8_t ) ) ;
display_settings ( ) ;
}
//////////////////////////////////////////////////////////////////////
UX_FLOW_DEF_NOCB (
2019-03-18 14:03:54 +01:00
ux_display_public_flow_1_step ,
pnn ,
2019-02-12 20:41:19 +01:00
{
& C_icon_eye ,
" Verify " ,
" address " ,
} ) ;
UX_FLOW_DEF_NOCB (
2019-03-18 14:03:54 +01:00
ux_display_public_flow_2_step ,
bnnn_paging ,
2019-02-12 20:41:19 +01:00
{
. title = " Address " ,
. text = strings . common . fullAddress ,
} ) ;
UX_FLOW_DEF_VALID (
2019-03-18 14:03:54 +01:00
ux_display_public_flow_3_step ,
pb ,
2019-02-12 20:41:19 +01:00
io_seproxyhal_touch_address_ok ( NULL ) ,
{
& C_icon_validate_14 ,
" Approve " ,
} ) ;
UX_FLOW_DEF_VALID (
2019-03-18 14:03:54 +01:00
ux_display_public_flow_4_step ,
pb ,
2019-02-12 20:41:19 +01:00
io_seproxyhal_touch_address_cancel ( NULL ) ,
{
& C_icon_crossmark ,
" Reject " ,
} ) ;
const ux_flow_step_t * const ux_display_public_flow [ ] = {
& ux_display_public_flow_1_step ,
& ux_display_public_flow_2_step ,
& ux_display_public_flow_3_step ,
& ux_display_public_flow_4_step ,
FLOW_END_STEP ,
} ;
//////////////////////////////////////////////////////////////////////
UX_FLOW_DEF_NOCB (
2019-03-18 14:03:54 +01:00
ux_confirm_selector_flow_1_step ,
pnn ,
2019-02-12 20:41:19 +01:00
{
& C_icon_eye ,
" Verify " ,
" selector " ,
} ) ;
UX_FLOW_DEF_NOCB (
2019-03-18 14:03:54 +01:00
ux_confirm_selector_flow_2_step ,
bn ,
2019-02-12 20:41:19 +01:00
{
" Selector " ,
strings . tmp . tmp
} ) ;
UX_FLOW_DEF_VALID (
2019-03-18 14:03:54 +01:00
ux_confirm_selector_flow_3_step ,
pb ,
2019-02-12 20:41:19 +01:00
io_seproxyhal_touch_data_ok ( NULL ) ,
{
& C_icon_validate_14 ,
" Approve " ,
} ) ;
UX_FLOW_DEF_VALID (
2019-03-18 14:03:54 +01:00
ux_confirm_selector_flow_4_step ,
pb ,
2019-02-12 20:41:19 +01:00
io_seproxyhal_touch_data_cancel ( NULL ) ,
{
& C_icon_crossmark ,
" Reject " ,
} ) ;
const ux_flow_step_t * const ux_confirm_selector_flow [ ] = {
& ux_confirm_selector_flow_1_step ,
& ux_confirm_selector_flow_2_step ,
& ux_confirm_selector_flow_3_step ,
& ux_confirm_selector_flow_4_step ,
FLOW_END_STEP ,
} ;
//////////////////////////////////////////////////////////////////////
UX_FLOW_DEF_NOCB (
2019-03-18 14:03:54 +01:00
ux_confirm_parameter_flow_1_step ,
pnn ,
2019-02-12 20:41:19 +01:00
{
& C_icon_eye ,
" Verify " ,
strings . tmp . tmp2
} ) ;
UX_FLOW_DEF_NOCB (
2019-03-18 14:03:54 +01:00
ux_confirm_parameter_flow_2_step ,
bnnn_paging ,
2019-02-12 20:41:19 +01:00
{
. title = " Parameter " ,
. text = strings . tmp . tmp ,
} ) ;
UX_FLOW_DEF_VALID (
2019-03-18 14:03:54 +01:00
ux_confirm_parameter_flow_3_step ,
pb ,
2019-02-12 20:41:19 +01:00
io_seproxyhal_touch_data_ok ( NULL ) ,
{
& C_icon_validate_14 ,
" Approve " ,
} ) ;
UX_FLOW_DEF_VALID (
2019-03-18 14:03:54 +01:00
ux_confirm_parameter_flow_4_step ,
pb ,
2019-02-12 20:41:19 +01:00
io_seproxyhal_touch_data_cancel ( NULL ) ,
{
& C_icon_crossmark ,
" Reject " ,
} ) ;
const ux_flow_step_t * const ux_confirm_parameter_flow [ ] = {
& ux_confirm_parameter_flow_1_step ,
& ux_confirm_parameter_flow_2_step ,
& ux_confirm_parameter_flow_3_step ,
& ux_confirm_parameter_flow_4_step ,
FLOW_END_STEP ,
} ;
//////////////////////////////////////////////////////////////////////
2019-03-18 14:03:54 +01:00
UX_FLOW_DEF_NOCB ( ux_approval_tx_1_step ,
pnn ,
2019-02-12 20:41:19 +01:00
{
& C_icon_eye ,
" Review " ,
" transaction " ,
} ) ;
UX_FLOW_DEF_NOCB (
2019-03-18 14:03:54 +01:00
ux_approval_tx_2_step ,
bnnn_paging ,
2019-02-12 20:41:19 +01:00
{
. title = " Amount " ,
. text = strings . common . fullAmount
} ) ;
UX_FLOW_DEF_NOCB (
2019-03-18 14:03:54 +01:00
ux_approval_tx_3_step ,
bnnn_paging ,
2019-02-12 20:41:19 +01:00
{
. title = " Address " ,
. text = strings . common . fullAddress ,
} ) ;
UX_FLOW_DEF_NOCB (
2019-03-18 14:03:54 +01:00
ux_approval_tx_4_step ,
bnnn_paging ,
2019-02-12 20:41:19 +01:00
{
. title = " Max Fees " ,
. text = strings . common . maxFee ,
} ) ;
UX_FLOW_DEF_VALID (
2019-03-18 14:03:54 +01:00
ux_approval_tx_5_step ,
pbb ,
2019-02-12 20:41:19 +01:00
io_seproxyhal_touch_tx_ok ( NULL ) ,
{
& C_icon_validate_14 ,
" Accept " ,
" and send " ,
} ) ;
UX_FLOW_DEF_VALID (
2019-03-18 14:03:54 +01:00
ux_approval_tx_6_step ,
pb ,
2019-02-12 20:41:19 +01:00
io_seproxyhal_touch_tx_cancel ( NULL ) ,
{
& C_icon_crossmark ,
" Reject " ,
} ) ;
2019-03-18 14:03:54 +01:00
UX_FLOW_DEF_NOCB ( ux_approval_tx_data_warning_step ,
pbb ,
2019-02-12 20:41:19 +01:00
{
& C_icon_warning ,
" Data " ,
" Present " ,
} ) ;
const ux_flow_step_t * const ux_approval_tx_flow [ ] = {
& ux_approval_tx_1_step ,
& ux_approval_tx_2_step ,
& ux_approval_tx_3_step ,
& ux_approval_tx_4_step ,
& ux_approval_tx_5_step ,
& ux_approval_tx_6_step ,
FLOW_END_STEP ,
} ;
const ux_flow_step_t * const ux_approval_tx_data_warning_flow [ ] = {
& ux_approval_tx_1_step ,
& ux_approval_tx_data_warning_step ,
& ux_approval_tx_2_step ,
& ux_approval_tx_3_step ,
& ux_approval_tx_4_step ,
& ux_approval_tx_5_step ,
& ux_approval_tx_6_step ,
FLOW_END_STEP ,
} ;
//////////////////////////////////////////////////////////////////////
UX_FLOW_DEF_NOCB (
2019-03-18 14:03:54 +01:00
ux_sign_flow_1_step ,
pnn ,
2019-02-12 20:41:19 +01:00
{
& C_icon_certificate ,
" Sign " ,
" message " ,
} ) ;
UX_FLOW_DEF_NOCB (
2019-03-18 14:03:54 +01:00
ux_sign_flow_2_step ,
bnnn_paging ,
2019-02-12 20:41:19 +01:00
{
. title = " Message hash " ,
. text = strings . common . fullAddress ,
} ) ;
UX_FLOW_DEF_VALID (
ux_sign_flow_3_step ,
pbb ,
io_seproxyhal_touch_signMessage_ok ( NULL ) ,
{
& C_icon_validate_14 ,
" Sign " ,
" message " ,
} ) ;
UX_FLOW_DEF_VALID (
ux_sign_flow_4_step ,
pbb ,
io_seproxyhal_touch_signMessage_cancel ( NULL ) ,
{
& C_icon_crossmark ,
" Cancel " ,
" signature " ,
} ) ;
const ux_flow_step_t * const ux_sign_flow [ ] = {
& ux_sign_flow_1_step ,
& ux_sign_flow_2_step ,
& ux_sign_flow_3_step ,
& ux_sign_flow_4_step ,
FLOW_END_STEP ,
} ;
2020-01-18 12:47:53 +01:00
# endif // #if defined(HAVE_UX_FLOW)
2019-02-12 20:41:19 +01:00
2018-07-31 19:59:59 +02:00
2016-07-31 09:36:00 +02:00
void ui_idle ( void ) {
2017-05-31 21:51:11 +02:00
# if defined(TARGET_BLUE)
2018-07-27 21:02:24 +02:00
UX_DISPLAY ( ui_idle_blue , ui_idle_blue_prepro ) ;
2020-01-18 12:47:53 +01:00
# elif defined(HAVE_UX_FLOW)
2019-02-12 20:41:19 +01:00
// reserve a display stack slot if none yet
if ( G_ux . stack_count = = 0 ) {
ux_stack_push ( ) ;
}
2019-03-18 14:03:54 +01:00
ux_flow_init ( 0 , ux_idle_flow , NULL ) ;
2020-01-18 12:47:53 +01:00
# elif defined(TARGET_NANOS)
UX_MENU_DISPLAY ( 0 , menu_main , NULL ) ;
2017-01-22 18:26:27 +01:00
# endif // #if TARGET_ID
}
2017-05-31 21:51:11 +02:00
# if defined(TARGET_BLUE)
2017-01-22 18:26:27 +01:00
unsigned int io_seproxyhal_touch_settings ( const bagl_element_t * e ) {
2018-07-27 21:02:24 +02:00
UX_DISPLAY ( ui_settings_blue , ui_settings_blue_prepro ) ;
return 0 ; // do not redraw button, screen has switched
2016-06-02 02:04:57 +02:00
}
2017-05-31 21:51:11 +02:00
# endif // #if defined(TARGET_BLUE)
2016-06-02 02:04:57 +02:00
2016-07-31 09:36:00 +02:00
unsigned int io_seproxyhal_touch_exit ( const bagl_element_t * e ) {
2016-06-01 21:41:29 +02:00
// Go back to the dashboard
os_sched_exit ( 0 ) ;
return 0 ; // do not redraw the widget
}
2016-07-31 09:36:00 +02:00
unsigned int io_seproxyhal_touch_address_ok ( const bagl_element_t * e ) {
2016-06-01 21:41:29 +02:00
uint32_t tx = set_result_get_publicKey ( ) ;
G_io_apdu_buffer [ tx + + ] = 0x90 ;
G_io_apdu_buffer [ tx + + ] = 0x00 ;
2020-01-18 12:47:53 +01:00
reset_app_context ( ) ;
2016-06-01 21:41:29 +02:00
// Send back the response, do not restart the event loop
io_exchange ( CHANNEL_APDU | IO_RETURN_AFTER_TX , tx ) ;
// Display back the original UX
2016-07-31 09:36:00 +02:00
ui_idle ( ) ;
2016-06-01 21:41:29 +02:00
return 0 ; // do not redraw the widget
}
2016-07-31 09:36:00 +02:00
unsigned int io_seproxyhal_touch_address_cancel ( const bagl_element_t * e ) {
2016-06-01 21:41:29 +02:00
G_io_apdu_buffer [ 0 ] = 0x69 ;
G_io_apdu_buffer [ 1 ] = 0x85 ;
2020-01-18 12:47:53 +01:00
reset_app_context ( ) ;
2016-06-01 21:41:29 +02:00
// Send back the response, do not restart the event loop
io_exchange ( CHANNEL_APDU | IO_RETURN_AFTER_TX , 2 ) ;
// Display back the original UX
2016-07-31 09:36:00 +02:00
ui_idle ( ) ;
2016-06-01 21:41:29 +02:00
return 0 ; // do not redraw the widget
}
2017-05-31 21:51:11 +02:00
# if defined(TARGET_NANOS)
2018-07-27 21:02:24 +02:00
unsigned int ui_address_nanos_button ( unsigned int button_mask , unsigned int button_mask_counter ) {
switch ( button_mask ) {
case BUTTON_EVT_RELEASED | BUTTON_LEFT : // CANCEL
io_seproxyhal_touch_address_cancel ( NULL ) ;
break ;
2016-07-31 09:36:00 +02:00
2018-07-27 21:02:24 +02:00
case BUTTON_EVT_RELEASED | BUTTON_RIGHT : { // OK
io_seproxyhal_touch_address_ok ( NULL ) ;
break ;
}
2016-07-31 09:36:00 +02:00
}
return 0 ;
}
2017-05-31 21:51:11 +02:00
# endif // #if defined(TARGET_NANOS)
2016-07-31 09:36:00 +02:00
2018-07-31 19:59:59 +02:00
void io_seproxyhal_send_status ( uint32_t sw ) {
G_io_apdu_buffer [ 0 ] = ( ( sw > > 8 ) & 0xff ) ;
G_io_apdu_buffer [ 1 ] = ( sw & 0xff ) ;
io_exchange ( CHANNEL_APDU | IO_RETURN_AFTER_TX , 2 ) ;
}
2020-01-18 12:47:53 +01:00
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 ) ;
}
2016-07-31 09:36:00 +02:00
unsigned int io_seproxyhal_touch_tx_ok ( const bagl_element_t * e ) {
2016-06-01 21:41:29 +02:00
uint8_t privateKeyData [ 32 ] ;
uint8_t signature [ 100 ] ;
uint8_t signatureLength ;
cx_ecfp_private_key_t privateKey ;
uint32_t tx = 0 ;
2018-07-28 17:36:12 +02:00
uint32_t v = getV ( & tmpContent . txContent ) ;
2020-01-18 12:47:53 +01:00
io_seproxyhal_io_heartbeat ( ) ;
2018-07-27 21:02:24 +02:00
os_perso_derive_node_bip32 ( CX_CURVE_256K1 , tmpCtx . transactionContext . bip32Path ,
tmpCtx . transactionContext . pathLength ,
privateKeyData , NULL ) ;
cx_ecfp_init_private_key ( CX_CURVE_256K1 , privateKeyData , 32 ,
& privateKey ) ;
2016-06-01 21:41:29 +02:00
os_memset ( privateKeyData , 0 , sizeof ( privateKeyData ) ) ;
2018-12-19 17:02:00 +01:00
unsigned int info = 0 ;
2020-01-18 12:47:53 +01:00
io_seproxyhal_io_heartbeat ( ) ;
2018-03-12 11:04:02 +01:00
signatureLength =
cx_ecdsa_sign ( & privateKey , CX_RND_RFC6979 | CX_LAST , CX_SHA256 ,
tmpCtx . transactionContext . hash ,
2020-01-18 12:47:53 +01:00
sizeof ( tmpCtx . transactionContext . hash ) , signature , sizeof ( signature ) , & info ) ;
2018-12-19 17:02:00 +01:00
os_memset ( & privateKey , 0 , sizeof ( privateKey ) ) ;
2016-06-01 21:41:29 +02:00
// Parity is present in the sequence tag in the legacy API
2017-03-03 13:49:39 +01:00
if ( tmpContent . txContent . vLength = = 0 ) {
2018-07-27 21:02:24 +02:00
// Legacy API
G_io_apdu_buffer [ 0 ] = 27 ;
}
else {
// New API
// Note that this is wrong for a large v, but the client can always recover
2018-12-19 17:02:00 +01:00
G_io_apdu_buffer [ 0 ] = ( v * 2 ) + 35 ;
2018-07-27 21:02:24 +02:00
}
if ( info & CX_ECCINFO_PARITY_ODD ) {
G_io_apdu_buffer [ 0 ] + + ;
}
if ( info & CX_ECCINFO_xGTn ) {
G_io_apdu_buffer [ 0 ] + = 2 ;
2016-11-25 09:10:04 +01:00
}
2020-01-18 12:47:53 +01:00
format_signature_out ( signature ) ;
2016-06-01 21:41:29 +02:00
tx = 65 ;
G_io_apdu_buffer [ tx + + ] = 0x90 ;
G_io_apdu_buffer [ tx + + ] = 0x00 ;
2020-01-18 12:47:53 +01:00
reset_app_context ( ) ;
2016-06-01 21:41:29 +02:00
// Send back the response, do not restart the event loop
io_exchange ( CHANNEL_APDU | IO_RETURN_AFTER_TX , tx ) ;
// Display back the original UX
2016-07-31 09:36:00 +02:00
ui_idle ( ) ;
2016-06-01 21:41:29 +02:00
return 0 ; // do not redraw the widget
}
2016-07-31 09:36:00 +02:00
unsigned int io_seproxyhal_touch_tx_cancel ( const bagl_element_t * e ) {
2020-01-18 12:47:53 +01:00
reset_app_context ( ) ;
2016-06-01 21:41:29 +02:00
G_io_apdu_buffer [ 0 ] = 0x69 ;
G_io_apdu_buffer [ 1 ] = 0x85 ;
// Send back the response, do not restart the event loop
io_exchange ( CHANNEL_APDU | IO_RETURN_AFTER_TX , 2 ) ;
// Display back the original UX
2016-07-31 09:36:00 +02:00
ui_idle ( ) ;
2016-06-01 21:41:29 +02:00
return 0 ; // do not redraw the widget
}
2018-07-27 21:02:24 +02:00
2017-03-03 13:49:39 +01:00
unsigned int io_seproxyhal_touch_signMessage_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 ;
2020-01-18 12:47:53 +01:00
io_seproxyhal_io_heartbeat ( ) ;
2017-03-03 13:49:39 +01:00
os_perso_derive_node_bip32 (
CX_CURVE_256K1 , tmpCtx . messageSigningContext . bip32Path ,
tmpCtx . messageSigningContext . pathLength , privateKeyData , NULL ) ;
2020-01-18 12:47:53 +01:00
io_seproxyhal_io_heartbeat ( ) ;
2017-03-03 13:49:39 +01:00
cx_ecfp_init_private_key ( CX_CURVE_256K1 , privateKeyData , 32 , & privateKey ) ;
os_memset ( privateKeyData , 0 , sizeof ( privateKeyData ) ) ;
2018-12-19 17:02:00 +01:00
unsigned int info = 0 ;
2020-01-18 12:47:53 +01:00
io_seproxyhal_io_heartbeat ( ) ;
2017-03-03 13:49:39 +01:00
signatureLength =
cx_ecdsa_sign ( & privateKey , CX_RND_RFC6979 | CX_LAST , CX_SHA256 ,
tmpCtx . messageSigningContext . hash ,
2020-01-18 12:47:53 +01:00
sizeof ( tmpCtx . messageSigningContext . hash ) , signature , sizeof ( signature ) , & info ) ;
2017-03-03 13:49:39 +01:00
os_memset ( & privateKey , 0 , sizeof ( privateKey ) ) ;
2018-07-27 21:02:24 +02:00
G_io_apdu_buffer [ 0 ] = 27 ;
if ( info & CX_ECCINFO_PARITY_ODD ) {
G_io_apdu_buffer [ 0 ] + + ;
}
if ( info & CX_ECCINFO_xGTn ) {
G_io_apdu_buffer [ 0 ] + = 2 ;
2018-12-19 17:02:00 +01:00
}
2020-01-18 12:47:53 +01:00
format_signature_out ( signature ) ;
2017-03-03 13:49:39 +01:00
tx = 65 ;
G_io_apdu_buffer [ tx + + ] = 0x90 ;
G_io_apdu_buffer [ tx + + ] = 0x00 ;
2020-01-18 12:47:53 +01:00
reset_app_context ( ) ;
2017-03-03 13:49:39 +01:00
// 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
}
unsigned int io_seproxyhal_touch_signMessage_cancel ( const bagl_element_t * e ) {
2020-01-18 12:47:53 +01:00
reset_app_context ( ) ;
2017-03-03 13:49:39 +01:00
G_io_apdu_buffer [ 0 ] = 0x69 ;
G_io_apdu_buffer [ 1 ] = 0x85 ;
// Send back the response, do not restart the event loop
io_exchange ( CHANNEL_APDU | IO_RETURN_AFTER_TX , 2 ) ;
// Display back the original UX
ui_idle ( ) ;
return 0 ; // do not redraw the widget
}
2018-07-31 19:59:59 +02:00
unsigned int io_seproxyhal_touch_data_ok ( const bagl_element_t * e ) {
parserStatus_e txResult = USTREAM_FINISHED ;
txResult = continueTx ( & txContext ) ;
switch ( txResult ) {
case USTREAM_SUSPENDED :
break ;
case USTREAM_FINISHED :
break ;
case USTREAM_PROCESSING :
io_seproxyhal_send_status ( 0x9000 ) ;
ui_idle ( ) ;
break ;
case USTREAM_FAULT :
2020-01-18 12:47:53 +01:00
reset_app_context ( ) ;
2018-07-31 19:59:59 +02:00
io_seproxyhal_send_status ( 0x6A80 ) ;
ui_idle ( ) ;
break ;
default :
PRINTF ( " Unexpected parser status \n " ) ;
2020-01-18 12:47:53 +01:00
reset_app_context ( ) ;
2018-07-31 19:59:59 +02:00
io_seproxyhal_send_status ( 0x6A80 ) ;
ui_idle ( ) ;
}
if ( txResult = = USTREAM_FINISHED ) {
finalizeParsing ( false ) ;
}
return 0 ;
}
unsigned int io_seproxyhal_touch_data_cancel ( const bagl_element_t * e ) {
2020-01-18 12:47:53 +01:00
reset_app_context ( ) ;
2018-07-31 19:59:59 +02:00
io_seproxyhal_send_status ( 0x6985 ) ;
// Display back the original UX
ui_idle ( ) ;
2018-12-19 17:02:00 +01:00
return 0 ; // do not redraw the widget
2018-07-31 19:59:59 +02:00
}
2017-05-31 21:51:11 +02:00
# if defined(TARGET_BLUE)
void ui_approval_blue_init ( void ) {
2018-07-27 21:02:24 +02:00
UX_DISPLAY ( ui_approval_blue , ui_approval_blue_prepro ) ;
2017-05-31 21:51:11 +02:00
}
void ui_approval_transaction_blue_init ( void ) {
2018-07-27 21:02:24 +02:00
ui_approval_blue_ok = ( bagl_element_callback_t ) io_seproxyhal_touch_tx_ok ;
ui_approval_blue_cancel = ( bagl_element_callback_t ) io_seproxyhal_touch_tx_cancel ;
G_ui_approval_blue_state = APPROVAL_TRANSACTION ;
2018-07-31 19:59:59 +02:00
ui_approval_blue_values [ 0 ] = strings . common . fullAmount ;
ui_approval_blue_values [ 1 ] = strings . common . fullAddress ;
ui_approval_blue_values [ 2 ] = strings . common . maxFee ;
2018-07-27 21:02:24 +02:00
ui_approval_blue_init ( ) ;
2017-05-31 21:51:11 +02:00
}
void ui_approval_message_sign_blue_init ( void ) {
2018-07-27 21:02:24 +02:00
ui_approval_blue_ok = ( bagl_element_callback_t ) io_seproxyhal_touch_signMessage_ok ;
ui_approval_blue_cancel = ( bagl_element_callback_t ) io_seproxyhal_touch_signMessage_cancel ;
G_ui_approval_blue_state = APPROVAL_MESSAGE ;
2018-07-31 19:59:59 +02:00
ui_approval_blue_values [ 0 ] = strings . common . fullAmount ;
2018-07-27 21:02:24 +02:00
ui_approval_blue_values [ 1 ] = NULL ;
ui_approval_blue_values [ 2 ] = NULL ;
ui_approval_blue_init ( ) ;
2017-05-31 21:51:11 +02:00
}
# elif defined(TARGET_NANOS)
2018-07-27 21:02:24 +02:00
unsigned int ui_approval_nanos_button ( unsigned int button_mask , unsigned int button_mask_counter ) {
switch ( button_mask ) {
case BUTTON_EVT_RELEASED | BUTTON_LEFT :
io_seproxyhal_touch_tx_cancel ( NULL ) ;
break ;
2016-07-31 09:36:00 +02:00
2018-07-27 21:02:24 +02:00
case BUTTON_EVT_RELEASED | BUTTON_RIGHT : {
io_seproxyhal_touch_tx_ok ( NULL ) ;
break ;
}
2018-12-19 17:02:00 +01:00
}
2016-07-31 09:36:00 +02:00
return 0 ;
2016-06-01 21:41:29 +02:00
}
2017-03-03 13:49:39 +01:00
2018-07-27 21:02:24 +02:00
unsigned int ui_approval_signMessage_nanos_button ( unsigned int button_mask , unsigned int button_mask_counter ) {
2017-03-03 13:49:39 +01:00
switch ( button_mask ) {
case BUTTON_EVT_RELEASED | BUTTON_LEFT :
io_seproxyhal_touch_signMessage_cancel ( NULL ) ;
break ;
case BUTTON_EVT_RELEASED | BUTTON_RIGHT : {
io_seproxyhal_touch_signMessage_ok ( NULL ) ;
break ;
}
}
return 0 ;
}
2018-07-31 19:59:59 +02:00
unsigned int ui_data_selector_nanos_button ( unsigned int button_mask ,
unsigned int button_mask_counter ) {
switch ( button_mask ) {
case BUTTON_EVT_RELEASED | BUTTON_LEFT :
io_seproxyhal_touch_data_cancel ( NULL ) ;
break ;
case BUTTON_EVT_RELEASED | BUTTON_RIGHT : {
io_seproxyhal_touch_data_ok ( NULL ) ;
break ;
}
}
return 0 ;
}
unsigned int ui_data_parameter_nanos_button ( unsigned int button_mask ,
unsigned int button_mask_counter ) {
switch ( button_mask ) {
case BUTTON_EVT_RELEASED | BUTTON_LEFT :
io_seproxyhal_touch_data_cancel ( NULL ) ;
break ;
case BUTTON_EVT_RELEASED | BUTTON_RIGHT : {
io_seproxyhal_touch_data_ok ( NULL ) ;
break ;
}
}
return 0 ;
}
2017-05-31 21:51:11 +02:00
# endif // #if defined(TARGET_NANOS)
2016-06-01 21:41:29 +02:00
unsigned short io_exchange_al ( unsigned char channel , unsigned short tx_len ) {
switch ( channel & ~ ( IO_FLAGS ) ) {
case CHANNEL_KEYBOARD :
break ;
// multiplexed io exchange over a SPI channel and TLV encapsulated protocol
case CHANNEL_SPI :
if ( tx_len ) {
io_seproxyhal_spi_send ( G_io_apdu_buffer , tx_len ) ;
if ( channel & IO_RESET_AFTER_REPLIED ) {
reset ( ) ;
}
return 0 ; // nothing received from the master so far (it's a tx
// transaction)
} else {
return io_seproxyhal_spi_recv ( G_io_apdu_buffer ,
sizeof ( G_io_apdu_buffer ) , 0 ) ;
}
default :
THROW ( INVALID_PARAMETER ) ;
}
return 0 ;
}
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 ) ;
tx + = 65 ;
G_io_apdu_buffer [ tx + + ] = 40 ;
os_memmove ( G_io_apdu_buffer + tx , tmpCtx . publicKeyContext . address , 40 ) ;
tx + = 40 ;
2016-10-17 23:40:31 +02:00
if ( tmpCtx . publicKeyContext . getChaincode ) {
2018-07-27 21:02:24 +02:00
os_memmove ( G_io_apdu_buffer + tx , tmpCtx . publicKeyContext . chainCode , 32 ) ;
tx + = 32 ;
2016-10-17 23:40:31 +02:00
}
2016-06-01 21:41:29 +02:00
return tx ;
}
2018-07-31 19:59:59 +02:00
uint32_t splitBinaryParameterPart ( char * result , uint8_t * parameter ) {
uint32_t i ;
for ( i = 0 ; i < 8 ; i + + ) {
if ( parameter [ i ] ! = 0x00 ) {
break ;
}
}
if ( i = = 8 ) {
result [ 0 ] = ' 0 ' ;
result [ 1 ] = ' 0 ' ;
result [ 2 ] = ' \0 ' ;
return 2 ;
}
else {
array_hexstr ( result , parameter + i , 8 - i ) ;
return ( ( 8 - i ) * 2 ) ;
}
}
tokenDefinition_t * getKnownToken ( ) {
tokenDefinition_t * currentToken = NULL ;
2019-03-18 14:03:54 +01:00
# ifdef HAVE_TOKENS_LIST
2018-07-31 19:59:59 +02:00
uint32_t numTokens = 0 ;
uint32_t i ;
switch ( chainConfig - > kind ) {
case CHAIN_KIND_AKROMA :
numTokens = NUM_TOKENS_AKROMA ;
break ;
case CHAIN_KIND_ETHEREUM :
numTokens = NUM_TOKENS_ETHEREUM ;
break ;
case CHAIN_KIND_ETHEREUM_CLASSIC :
numTokens = NUM_TOKENS_ETHEREUM_CLASSIC ;
2018-12-19 17:02:00 +01:00
break ;
2018-07-31 19:59:59 +02:00
case CHAIN_KIND_PIRL :
numTokens = NUM_TOKENS_PIRL ;
break ;
case CHAIN_KIND_POA :
numTokens = NUM_TOKENS_POA ;
break ;
2020-01-18 12:47:53 +01:00
case CHAIN_KIND_ARTIS_SIGMA1 :
numTokens = NUM_TOKENS_ARTIS_SIGMA1 ;
break ;
case CHAIN_KIND_ARTIS_TAU1 :
numTokens = NUM_TOKENS_ARTIS_TAU1 ;
break ;
2018-07-31 19:59:59 +02:00
case CHAIN_KIND_RSK :
numTokens = NUM_TOKENS_RSK ;
2018-12-19 17:02:00 +01:00
break ;
2018-07-31 19:59:59 +02:00
case CHAIN_KIND_EXPANSE :
numTokens = NUM_TOKENS_EXPANSE ;
break ;
case CHAIN_KIND_UBIQ :
numTokens = NUM_TOKENS_UBIQ ;
break ;
case CHAIN_KIND_WANCHAIN :
numTokens = NUM_TOKENS_WANCHAIN ;
2018-12-19 17:02:00 +01:00
break ;
2018-07-31 19:59:59 +02:00
case CHAIN_KIND_KUSD :
numTokens = NUM_TOKENS_KUSD ;
2018-12-19 17:02:00 +01:00
break ;
2018-08-02 10:11:56 +02:00
case CHAIN_KIND_MUSICOIN :
numTokens = NUM_TOKENS_MUSICOIN ;
break ;
case CHAIN_KIND_CALLISTO :
numTokens = NUM_TOKENS_CALLISTO ;
2018-12-19 17:02:00 +01:00
break ;
2018-08-02 10:19:36 +02:00
case CHAIN_KIND_ETHERSOCIAL :
numTokens = NUM_TOKENS_ETHERSOCIAL ;
break ;
2018-08-02 10:23:20 +02:00
case CHAIN_KIND_ELLAISM :
numTokens = NUM_TOKENS_ELLAISM ;
break ;
2018-08-05 02:19:44 -04:00
case CHAIN_KIND_ETHER1 :
numTokens = NUM_TOKENS_ETHER1 ;
break ;
2018-08-10 14:54:56 -04:00
case CHAIN_KIND_ETHERGEM :
numTokens = NUM_TOKENS_ETHERGEM ;
break ;
2018-08-23 11:06:12 -04:00
case CHAIN_KIND_ATHEIOS :
numTokens = NUM_TOKENS_ATHEIOS ;
break ;
2018-09-08 07:27:12 -04:00
case CHAIN_KIND_GOCHAIN :
numTokens = NUM_TOKENS_GOCHAIN ;
break ;
2018-10-07 10:14:12 -04:00
case CHAIN_KIND_MIX :
numTokens = NUM_TOKENS_MIX ;
break ;
2018-12-10 08:46:32 -05:00
case CHAIN_KIND_REOSC :
numTokens = NUM_TOKENS_REOSC ;
break ;
2018-11-09 00:25:04 +01:00
case CHAIN_KIND_HPB :
numTokens = NUM_TOKENS_HPB ;
break ;
2019-02-06 08:03:49 +00:00
case CHAIN_KIND_TOMOCHAIN :
numTokens = NUM_TOKENS_TOMOCHAIN ;
break ;
2019-01-31 17:38:12 +01:00
case CHAIN_KIND_TOBALABA :
numTokens = NUM_TOKENS_TOBALABA ;
break ;
2020-01-18 12:47:53 +01:00
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 ;
2018-07-31 19:59:59 +02:00
}
2018-12-19 17:02:00 +01:00
for ( i = 0 ; i < numTokens ; i + + ) {
2018-07-31 19:59:59 +02:00
switch ( chainConfig - > kind ) {
case CHAIN_KIND_AKROMA :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_AKROMA [ i ] ) ;
2018-07-31 19:59:59 +02:00
break ;
case CHAIN_KIND_ETHEREUM :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_ETHEREUM [ i ] ) ;
2018-07-31 19:59:59 +02:00
break ;
case CHAIN_KIND_ETHEREUM_CLASSIC :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_ETHEREUM_CLASSIC [ i ] ) ;
2018-12-19 17:02:00 +01:00
break ;
2018-07-31 19:59:59 +02:00
case CHAIN_KIND_PIRL :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_PIRL [ i ] ) ;
2018-07-31 19:59:59 +02:00
break ;
case CHAIN_KIND_POA :
2020-01-18 12:47:53 +01:00
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 ;
2018-07-31 19:59:59 +02:00
case CHAIN_KIND_RSK :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_RSK [ i ] ) ;
2018-12-19 17:02:00 +01:00
break ;
2018-07-31 19:59:59 +02:00
case CHAIN_KIND_EXPANSE :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_EXPANSE [ i ] ) ;
2018-12-19 17:02:00 +01:00
break ;
2018-07-31 19:59:59 +02:00
case CHAIN_KIND_UBIQ :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_UBIQ [ i ] ) ;
2018-12-19 17:02:00 +01:00
break ;
2018-07-31 19:59:59 +02:00
case CHAIN_KIND_WANCHAIN :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_WANCHAIN [ i ] ) ;
2018-12-19 17:02:00 +01:00
break ;
2018-07-31 19:59:59 +02:00
case CHAIN_KIND_KUSD :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_KUSD [ i ] ) ;
2018-07-31 19:59:59 +02:00
break ;
2018-08-02 10:11:56 +02:00
case CHAIN_KIND_MUSICOIN :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_MUSICOIN [ i ] ) ;
2018-08-02 10:11:56 +02:00
break ;
case CHAIN_KIND_CALLISTO :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_CALLISTO [ i ] ) ;
2018-08-02 10:11:56 +02:00
break ;
2018-08-02 10:19:36 +02:00
case CHAIN_KIND_ETHERSOCIAL :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_ETHERSOCIAL [ i ] ) ;
2018-08-02 10:19:36 +02:00
break ;
2018-08-02 10:23:20 +02:00
case CHAIN_KIND_ELLAISM :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_ELLAISM [ i ] ) ;
2018-08-02 10:23:20 +02:00
break ;
2018-08-05 02:19:44 -04:00
case CHAIN_KIND_ETHER1 :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_ETHER1 [ i ] ) ;
2018-08-05 02:19:44 -04:00
break ;
2018-08-10 14:54:56 -04:00
case CHAIN_KIND_ETHERGEM :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_ETHERGEM [ i ] ) ;
2018-08-10 14:54:56 -04:00
break ;
2018-08-23 11:06:12 -04:00
case CHAIN_KIND_ATHEIOS :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_ATHEIOS [ i ] ) ;
2018-08-23 11:06:12 -04:00
break ;
2018-09-08 07:27:12 -04:00
case CHAIN_KIND_GOCHAIN :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_GOCHAIN [ i ] ) ;
2018-09-08 07:27:12 -04:00
break ;
2018-10-07 10:14:12 -04:00
case CHAIN_KIND_MIX :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_MIX [ i ] ) ;
2018-10-07 10:14:12 -04:00
break ;
2018-12-10 08:46:32 -05:00
case CHAIN_KIND_REOSC :
2018-12-19 17:02:02 +01:00
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_REOSC [ i ] ) ;
2018-12-10 08:46:32 -05:00
break ;
2018-11-09 00:25:04 +01:00
case CHAIN_KIND_HPB :
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_HPB [ i ] ) ;
break ;
2019-02-06 08:03:49 +00:00
case CHAIN_KIND_TOMOCHAIN :
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_TOMOCHAIN [ i ] ) ;
break ;
2019-01-31 17:38:12 +01:00
case CHAIN_KIND_TOBALABA :
currentToken = ( tokenDefinition_t * ) PIC ( & TOKENS_TOBALABA [ i ] ) ;
break ;
2020-01-18 12:47:53 +01:00
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
2019-03-18 14:03:54 +01:00
}
2018-07-31 19:59:59 +02:00
if ( os_memcmp ( currentToken - > address , tmpContent . txContent . destination , 20 ) = = 0 ) {
return currentToken ;
}
}
2019-02-05 14:50:36 +01:00
# endif
2019-03-18 14:03:54 +01:00
if ( ( currentTokenSet | | tokenProvisioned ) & & ( os_memcmp ( tmpCtx . transactionContext . currentToken . address , tmpContent . txContent . destination , 20 ) = = 0 ) ) {
2019-03-08 11:12:50 +01:00
currentTokenSet = false ;
2019-02-05 14:50:36 +01:00
return & tmpCtx . transactionContext . currentToken ;
}
2018-07-31 19:59:59 +02:00
return NULL ;
}
customStatus_e customProcessor ( txContext_t * context ) {
2016-06-01 21:41:29 +02:00
if ( ( context - > currentField = = TX_RLP_DATA ) & &
( context - > currentFieldLength ! = 0 ) ) {
2018-07-31 19:59:59 +02:00
dataPresent = true ;
// If handling a new contract rather than a function call, abort immediately
if ( tmpContent . txContent . destinationLength = = 0 ) {
2018-08-27 17:04:15 +02:00
return CUSTOM_NOT_HANDLED ;
2018-07-31 19:59:59 +02:00
}
2018-12-19 17:02:00 +01:00
if ( context - > currentFieldPos = = 0 ) {
2018-07-31 19:59:59 +02:00
// If handling the beginning of the data field, assume that the function selector is present
if ( context - > commandLength < 4 ) {
PRINTF ( " Missing function selector \n " ) ;
return CUSTOM_FAULT ;
}
// Initial check to see if the token content can be processed
2018-12-19 17:02:00 +01:00
tokenProvisioned =
2018-07-31 19:59:59 +02:00
( context - > currentFieldLength = = sizeof ( dataContext . tokenContext . data ) ) & &
2018-12-19 17:02:00 +01:00
( os_memcmp ( context - > workBuffer , TOKEN_TRANSFER_ID , 4 ) = = 0 ) & &
2018-07-31 19:59:59 +02:00
( getKnownToken ( ) ! = NULL ) ;
}
if ( tokenProvisioned ) {
if ( context - > currentFieldPos < context - > currentFieldLength ) {
uint32_t copySize = ( context - > commandLength <
( ( context - > currentFieldLength -
context - > currentFieldPos ) )
? context - > commandLength
: context - > currentFieldLength -
context - > currentFieldPos ) ;
copyTxData ( context ,
dataContext . tokenContext . data + context - > currentFieldPos ,
copySize ) ;
}
if ( context - > currentFieldPos = = context - > currentFieldLength ) {
context - > currentField + + ;
context - > processingField = false ;
}
return CUSTOM_HANDLED ;
}
else {
uint32_t blockSize ;
uint32_t copySize ;
uint32_t fieldPos = context - > currentFieldPos ;
if ( fieldPos = = 0 ) {
if ( ! N_storage . dataAllowed ) {
PRINTF ( " Data field forbidden \n " ) ;
return CUSTOM_FAULT ;
}
2018-08-28 09:12:20 +02:00
if ( ! N_storage . contractDetails ) {
return CUSTOM_NOT_HANDLED ;
}
2018-07-31 19:59:59 +02:00
dataContext . rawDataContext . fieldIndex = 0 ;
dataContext . rawDataContext . fieldOffset = 0 ;
blockSize = 4 ;
}
else {
2018-10-03 18:22:38 +02:00
if ( ! N_storage . contractDetails ) {
return CUSTOM_NOT_HANDLED ;
2018-12-19 17:02:00 +01:00
}
2018-10-03 18:22:38 +02:00
blockSize = 32 - ( dataContext . rawDataContext . fieldOffset % 32 ) ;
2018-07-31 19:59:59 +02:00
}
// Sanity check
if ( ( context - > currentFieldLength - fieldPos ) < blockSize ) {
PRINTF ( " Unconsistent data \n " ) ;
return CUSTOM_FAULT ;
}
copySize = ( context - > commandLength < blockSize ? context - > commandLength : blockSize ) ;
copyTxData ( context ,
dataContext . rawDataContext . data + dataContext . rawDataContext . fieldOffset ,
2018-07-27 21:02:24 +02:00
copySize ) ;
2018-07-31 19:59:59 +02:00
if ( context - > currentFieldPos = = context - > currentFieldLength ) {
context - > currentField + + ;
context - > processingField = false ;
}
dataContext . rawDataContext . fieldOffset + = copySize ;
if ( copySize = = blockSize ) {
// Can display
if ( fieldPos ! = 0 ) {
dataContext . rawDataContext . fieldIndex + + ;
}
2018-12-19 17:02:00 +01:00
dataContext . rawDataContext . fieldOffset = 0 ;
2018-07-31 19:59:59 +02:00
if ( fieldPos = = 0 ) {
array_hexstr ( strings . tmp . tmp , dataContext . rawDataContext . data , 4 ) ;
# if defined(TARGET_BLUE)
UX_DISPLAY ( ui_data_selector_blue , ui_data_selector_blue_prepro ) ;
2020-01-18 12:47:53 +01:00
# elif defined(HAVE_UX_FLOW)
ux_flow_init ( 0 , ux_confirm_selector_flow , NULL ) ;
2018-07-31 19:59:59 +02:00
# elif defined(TARGET_NANOS)
ux_step = 0 ;
ux_step_count = 2 ;
UX_DISPLAY ( ui_data_selector_nanos , ui_data_selector_prepro ) ;
# endif // #if TARGET_ID
}
else {
uint32_t offset = 0 ;
uint32_t i ;
snprintf ( strings . tmp . tmp2 , sizeof ( strings . tmp . tmp2 ) , " Field %d " , dataContext . rawDataContext . fieldIndex ) ;
for ( i = 0 ; i < 4 ; i + + ) {
offset + = splitBinaryParameterPart ( strings . tmp . tmp + offset , dataContext . rawDataContext . data + 8 * i ) ;
if ( i ! = 3 ) {
strings . tmp . tmp [ offset + + ] = ' : ' ;
}
}
# if defined(TARGET_BLUE)
UX_DISPLAY ( ui_data_parameter_blue , ui_data_parameter_blue_prepro ) ;
2020-01-18 12:47:53 +01:00
# elif defined(HAVE_UX_FLOW)
ux_flow_init ( 0 , ux_confirm_parameter_flow , NULL ) ;
2018-07-31 19:59:59 +02:00
# elif defined(TARGET_NANOS)
ux_step = 0 ;
ux_step_count = 2 ;
UX_DISPLAY ( ui_data_parameter_nanos , ui_data_parameter_prepro ) ;
2018-12-19 17:02:00 +01:00
# endif // #if TARGET_ID
2018-07-31 19:59:59 +02:00
}
}
else {
return CUSTOM_HANDLED ;
}
2018-12-19 17:02:00 +01:00
return CUSTOM_SUSPENDED ;
2018-07-31 19:59:59 +02:00
}
}
return CUSTOM_NOT_HANDLED ;
2016-06-01 21:41:29 +02:00
}
2020-01-18 12:47:53 +01:00
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
2016-10-17 23:40:31 +02:00
2018-07-27 21:02:24 +02:00
void handleGetPublicKey ( uint8_t p1 , uint8_t p2 , uint8_t * dataBuffer , uint16_t dataLength , volatile unsigned int * flags , volatile unsigned int * tx ) {
2018-12-19 17:02:00 +01:00
UNUSED ( dataLength ) ;
2018-07-27 21:02:24 +02:00
uint8_t privateKeyData [ 32 ] ;
uint32_t bip32Path [ MAX_BIP32_PATH ] ;
uint32_t i ;
uint8_t bip32PathLength = * ( dataBuffer + + ) ;
2019-03-18 14:03:54 +01:00
cx_ecfp_private_key_t privateKey ;
2020-01-18 12:47:53 +01:00
reset_app_context ( ) ;
2018-07-27 21:02:24 +02:00
if ( ( bip32PathLength < 0x01 ) | |
( bip32PathLength > MAX_BIP32_PATH ) ) {
PRINTF ( " Invalid path \n " ) ;
THROW ( 0x6a80 ) ;
}
if ( ( p1 ! = P1_CONFIRM ) & & ( p1 ! = P1_NON_CONFIRM ) ) {
THROW ( 0x6B00 ) ;
}
if ( ( p2 ! = P2_CHAINCODE ) & & ( p2 ! = P2_NO_CHAINCODE ) ) {
THROW ( 0x6B00 ) ;
}
for ( i = 0 ; i < bip32PathLength ; i + + ) {
2019-02-05 14:50:36 +01:00
bip32Path [ i ] = U4BE ( dataBuffer , 0 ) ;
2018-07-27 21:02:24 +02:00
dataBuffer + = 4 ;
}
tmpCtx . publicKeyContext . getChaincode = ( p2 = = P2_CHAINCODE ) ;
2020-01-18 12:47:53 +01:00
io_seproxyhal_io_heartbeat ( ) ;
2018-07-27 21:02:24 +02:00
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 ) ;
2020-01-18 12:47:53 +01:00
io_seproxyhal_io_heartbeat ( ) ;
2018-07-27 21:02:24 +02:00
cx_ecfp_generate_pair ( CX_CURVE_256K1 , & tmpCtx . publicKeyContext . publicKey , & privateKey , 1 ) ;
os_memset ( & privateKey , 0 , sizeof ( privateKey ) ) ;
os_memset ( privateKeyData , 0 , sizeof ( privateKeyData ) ) ;
2020-01-18 12:47:53 +01:00
io_seproxyhal_io_heartbeat ( ) ;
2018-07-27 21:02:24 +02:00
getEthAddressStringFromKey ( & tmpCtx . publicKeyContext . publicKey , tmpCtx . publicKeyContext . address , & sha3 ) ;
2019-02-12 20:41:19 +01:00
# ifndef NO_CONSENT
if ( p1 = = P1_NON_CONFIRM )
# endif // NO_CONSENT
{
2018-07-27 21:02:24 +02:00
* tx = set_result_get_publicKey ( ) ;
THROW ( 0x9000 ) ;
2018-12-19 17:02:00 +01:00
}
2019-02-12 20:41:19 +01:00
# ifndef NO_CONSENT
2018-12-19 17:02:00 +01:00
else
2018-07-27 21:02:24 +02:00
{
/*
addressSummary [ 0 ] = ' 0 ' ;
addressSummary [ 1 ] = ' x ' ;
os_memmove ( ( unsigned char * ) ( addressSummary + 2 ) , tmpCtx . publicKeyContext . address , 4 ) ;
os_memmove ( ( unsigned char * ) ( addressSummary + 6 ) , " ... " , 3 ) ;
os_memmove ( ( unsigned char * ) ( addressSummary + 9 ) , tmpCtx . publicKeyContext . address + 40 - 4 , 4 ) ;
addressSummary [ 13 ] = ' \0 ' ;
*/
// prepare for a UI based reply
2017-05-31 21:51:11 +02:00
# if defined(TARGET_BLUE)
2018-07-31 19:59:59 +02:00
snprintf ( strings . common . fullAddress , sizeof ( strings . common . fullAddress ) , " 0x%.*s " , 40 , tmpCtx . publicKeyContext . address ) ;
2018-07-27 21:02:24 +02:00
UX_DISPLAY ( ui_address_blue , ui_address_blue_prepro ) ;
2020-01-18 12:47:53 +01:00
# 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 ) ;
2017-05-31 21:51:11 +02:00
# elif defined(TARGET_NANOS)
2018-07-31 19:59:59 +02:00
snprintf ( strings . common . fullAddress , sizeof ( strings . common . fullAddress ) , " 0x%.*s " , 40 , tmpCtx . publicKeyContext . address ) ;
2018-07-27 21:02:24 +02:00
ux_step = 0 ;
ux_step_count = 2 ;
2018-12-19 17:02:00 +01:00
UX_DISPLAY ( ui_address_nanos , ui_address_prepro ) ;
2017-01-22 18:26:27 +01:00
# endif // #if TARGET_ID
2018-12-19 17:02:00 +01:00
2018-07-27 21:02:24 +02:00
* flags | = IO_ASYNCH_REPLY ;
}
2019-02-12 20:41:19 +01:00
# endif // NO_CONSENT
2016-10-17 23:40:31 +02:00
}
2018-07-31 19:59:59 +02:00
void finalizeParsing ( bool direct ) {
2018-07-27 21:02:24 +02:00
uint256_t gasPrice , startGas , uint256 ;
uint32_t i ;
uint8_t address [ 41 ] ;
uint8_t decimals = WEI_TO_ETHER ;
2018-12-19 17:02:03 +01:00
uint8_t * ticker = ( uint8_t * ) PIC ( chainConfig - > coinName ) ;
uint8_t * feeTicker = ( uint8_t * ) PIC ( chainConfig - > coinName ) ;
2018-07-27 21:02:24 +02:00
uint8_t tickerOffset = 0 ;
2018-07-31 19:59:59 +02:00
2018-07-27 21:02:24 +02:00
// Verify the chain
if ( chainConfig - > chainId ! = 0 ) {
2018-07-28 17:36:12 +02:00
uint32_t v = getV ( & tmpContent . txContent ) ;
2018-07-27 21:02:24 +02:00
if ( chainConfig - > chainId ! = v ) {
2020-01-18 12:47:53 +01:00
reset_app_context ( ) ;
2018-07-27 21:02:24 +02:00
PRINTF ( " Invalid chainId %d expected %d \n " , v , chainConfig - > chainId ) ;
2018-07-31 19:59:59 +02:00
if ( direct ) {
THROW ( 0x6A80 ) ;
}
else {
io_seproxyhal_send_status ( 0x6A80 ) ;
ui_idle ( ) ;
return ;
}
2016-10-17 23:40:31 +02:00
}
2018-07-27 21:02:24 +02:00
}
// Store the hash
2020-01-18 12:47:53 +01:00
cx_hash ( ( cx_hash_t * ) & sha3 , CX_LAST , tmpCtx . transactionContext . hash , 0 , tmpCtx . transactionContext . hash , 32 ) ;
2017-02-04 13:09:46 +01:00
// If there is a token to process, check if it is well known
2018-07-31 19:59:59 +02:00
if ( tokenProvisioned ) {
tokenDefinition_t * currentToken = getKnownToken ( ) ;
if ( currentToken ! = NULL ) {
dataPresent = false ;
decimals = currentToken - > decimals ;
ticker = currentToken - > ticker ;
tmpContent . txContent . destinationLength = 20 ;
os_memmove ( tmpContent . txContent . destination , dataContext . tokenContext . data + 4 + 12 , 20 ) ;
os_memmove ( tmpContent . txContent . value . value , dataContext . tokenContext . data + 4 + 32 , 32 ) ;
tmpContent . txContent . value . length = 32 ;
2017-02-04 13:09:46 +01:00
}
2018-12-19 17:02:00 +01:00
}
2018-07-27 21:02:24 +02:00
else {
if ( dataPresent & & ! N_storage . dataAllowed ) {
2020-01-18 12:47:53 +01:00
reset_app_context ( ) ;
2018-07-27 21:02:24 +02:00
PRINTF ( " Data field forbidden \n " ) ;
2018-07-31 19:59:59 +02:00
if ( direct ) {
THROW ( 0x6A80 ) ;
}
else {
io_seproxyhal_send_status ( 0x6A80 ) ;
ui_idle ( ) ;
return ;
}
2018-12-19 17:02:00 +01:00
}
2017-02-04 13:09:46 +01:00
}
2018-07-27 21:02:24 +02:00
// Add address
if ( tmpContent . txContent . destinationLength ! = 0 ) {
getEthAddressStringFromBinary ( tmpContent . txContent . destination , address , & sha3 ) ;
/*
addressSummary [ 0 ] = ' 0 ' ;
addressSummary [ 1 ] = ' x ' ;
os_memmove ( ( unsigned char * ) ( addressSummary + 2 ) , address , 4 ) ;
os_memmove ( ( unsigned char * ) ( addressSummary + 6 ) , " ... " , 3 ) ;
os_memmove ( ( unsigned char * ) ( addressSummary + 9 ) , address + 40 - 4 , 4 ) ;
addressSummary [ 13 ] = ' \0 ' ;
*/
2018-07-31 19:59:59 +02:00
strings . common . fullAddress [ 0 ] = ' 0 ' ;
strings . common . fullAddress [ 1 ] = ' x ' ;
os_memmove ( ( unsigned char * ) strings . common . fullAddress + 2 , address , 40 ) ;
strings . common . fullAddress [ 42 ] = ' \0 ' ;
2018-07-27 21:02:24 +02:00
}
2018-12-19 17:02:00 +01:00
else
2018-07-27 21:02:24 +02:00
{
os_memmove ( ( void * ) addressSummary , CONTRACT_ADDRESS , sizeof ( CONTRACT_ADDRESS ) ) ;
2018-07-31 19:59:59 +02:00
strcpy ( strings . common . fullAddress , " Contract " ) ;
2018-07-27 21:02:24 +02:00
}
// Add amount in ethers or tokens
convertUint256BE ( tmpContent . txContent . value . value , tmpContent . txContent . value . length , & uint256 ) ;
tostring256 ( & uint256 , 10 , ( char * ) ( G_io_apdu_buffer + 100 ) , 100 ) ;
i = 0 ;
while ( G_io_apdu_buffer [ 100 + i ] ) {
i + + ;
}
adjustDecimals ( ( char * ) ( G_io_apdu_buffer + 100 ) , i , ( char * ) G_io_apdu_buffer , 100 , decimals ) ;
i = 0 ;
2017-02-04 13:09:46 +01:00
tickerOffset = 0 ;
while ( ticker [ tickerOffset ] ) {
2018-07-31 19:59:59 +02:00
strings . common . fullAmount [ tickerOffset ] = ticker [ tickerOffset ] ;
2017-02-04 13:09:46 +01:00
tickerOffset + + ;
}
2016-10-17 23:40:31 +02:00
while ( G_io_apdu_buffer [ i ] ) {
2018-07-31 19:59:59 +02:00
strings . common . fullAmount [ tickerOffset + i ] = G_io_apdu_buffer [ i ] ;
2016-10-17 23:40:31 +02:00
i + + ;
2018-12-19 17:02:00 +01:00
}
2018-07-31 19:59:59 +02:00
strings . common . fullAmount [ tickerOffset + i ] = ' \0 ' ;
2018-07-27 21:02:24 +02:00
// Compute maximum fee
convertUint256BE ( tmpContent . txContent . gasprice . value , tmpContent . txContent . gasprice . length , & gasPrice ) ;
convertUint256BE ( tmpContent . txContent . startgas . value , tmpContent . txContent . startgas . length , & startGas ) ;
mul256 ( & gasPrice , & startGas , & uint256 ) ;
tostring256 ( & uint256 , 10 , ( char * ) ( G_io_apdu_buffer + 100 ) , 100 ) ;
i = 0 ;
while ( G_io_apdu_buffer [ 100 + i ] ) {
i + + ;
}
adjustDecimals ( ( char * ) ( G_io_apdu_buffer + 100 ) , i , ( char * ) G_io_apdu_buffer , 100 , WEI_TO_ETHER ) ;
i = 0 ;
tickerOffset = 0 ;
2018-07-31 20:13:12 +02:00
while ( feeTicker [ tickerOffset ] ) {
strings . common . maxFee [ tickerOffset ] = feeTicker [ tickerOffset ] ;
2018-07-27 21:02:24 +02:00
tickerOffset + + ;
}
tickerOffset + + ;
while ( G_io_apdu_buffer [ i ] ) {
2018-07-31 19:59:59 +02:00
strings . common . maxFee [ tickerOffset + i ] = G_io_apdu_buffer [ i ] ;
2018-07-27 21:02:24 +02:00
i + + ;
}
2018-07-31 19:59:59 +02:00
strings . common . maxFee [ tickerOffset + i ] = ' \0 ' ;
2016-10-17 23:40:31 +02:00
2019-02-12 20:41:19 +01:00
# ifdef NO_CONSENT
io_seproxyhal_touch_tx_ok ( NULL ) ;
# else // NO_CONSENT
2017-05-31 21:51:11 +02:00
# if defined(TARGET_BLUE)
2018-07-27 21:02:24 +02:00
ui_approval_transaction_blue_init ( ) ;
2020-01-18 12:47:53 +01:00
# elif defined(HAVE_UX_FLOW)
ux_flow_init ( 0 ,
( ( dataPresent & & ! N_storage . contractDetails ) ? ux_approval_tx_data_warning_flow : ux_approval_tx_flow ) ,
NULL ) ;
2017-05-31 21:51:11 +02:00
# elif defined(TARGET_NANOS)
2018-07-27 21:02:24 +02:00
ux_step = 0 ;
2018-08-28 09:12:20 +02:00
ux_step_count = 5 ;
2018-12-19 17:02:00 +01:00
UX_DISPLAY ( ui_approval_nanos , ui_approval_prepro ) ;
2017-01-22 18:26:27 +01:00
# endif // #if TARGET_ID
2019-02-12 20:41:19 +01:00
# endif // NO_CONSENT
2018-07-31 19:59:59 +02:00
}
2019-02-05 14:50:36 +01:00
void handleProvideErc20TokenInformation ( uint8_t p1 , uint8_t p2 , uint8_t * workBuffer , uint16_t dataLength , volatile unsigned int * flags , volatile unsigned int * tx ) {
UNUSED ( p1 ) ;
UNUSED ( p2 ) ;
UNUSED ( flags ) ;
uint32_t offset = 0 ;
uint8_t tickerLength ;
uint32_t chainId ;
uint8_t hash [ 32 ] ;
cx_ecfp_public_key_t tokenKey ;
if ( dataLength < 1 ) {
THROW ( 0x6A80 ) ;
}
tickerLength = workBuffer [ offset + + ] ;
dataLength - - ;
2019-03-24 21:56:30 +01:00
if ( ( tickerLength + 1 ) > = sizeof ( tmpCtx . transactionContext . currentToken . ticker ) ) {
2019-02-05 14:50:36 +01:00
THROW ( 0x6A80 ) ;
}
if ( dataLength < tickerLength + 20 + 4 + 4 ) {
THROW ( 0x6A80 ) ;
}
2020-01-18 12:47:53 +01:00
cx_hash_sha256 ( workBuffer + offset , tickerLength + 20 + 4 + 4 , hash , 32 ) ;
2019-02-05 14:50:36 +01:00
os_memmove ( tmpCtx . transactionContext . currentToken . ticker , workBuffer + offset , tickerLength ) ;
2019-03-24 21:56:30 +01:00
tmpCtx . transactionContext . currentToken . ticker [ tickerLength ] = ' ' ;
2020-01-18 12:47:53 +01:00
tmpCtx . transactionContext . currentToken . ticker [ tickerLength + 1 ] = ' \0 ' ;
2019-02-05 14:50:36 +01:00
offset + = tickerLength ;
2019-03-18 14:03:54 +01:00
dataLength - = tickerLength ;
2019-02-05 14:50:36 +01:00
os_memmove ( tmpCtx . transactionContext . currentToken . address , workBuffer + offset , 20 ) ;
offset + = 20 ;
dataLength - = 20 ;
tmpCtx . transactionContext . currentToken . decimals = U4BE ( workBuffer , offset ) ;
offset + = 4 ;
dataLength - = 4 ;
chainId = U4BE ( workBuffer , offset ) ;
if ( ( chainConfig - > chainId ! = 0 ) & & ( chainConfig - > chainId ! = chainId ) ) {
PRINTF ( " ChainId token mismatch \n " ) ;
THROW ( 0x6A80 ) ;
}
offset + = 4 ;
dataLength - = 4 ;
cx_ecfp_init_public_key ( CX_CURVE_256K1 , TOKEN_SIGNATURE_PUBLIC_KEY , sizeof ( TOKEN_SIGNATURE_PUBLIC_KEY ) , & tokenKey ) ;
if ( ! cx_ecdsa_verify ( & tokenKey , CX_LAST , CX_SHA256 , hash , 32 , workBuffer + offset , dataLength ) ) {
PRINTF ( " Invalid token signature \n " ) ;
THROW ( 0x6A80 ) ;
2019-03-18 14:03:54 +01:00
}
currentTokenSet = true ;
2019-02-05 14:50:36 +01:00
THROW ( 0x9000 ) ;
}
2018-07-31 19:59:59 +02:00
void handleSign ( uint8_t p1 , uint8_t p2 , uint8_t * workBuffer , uint16_t dataLength , volatile unsigned int * flags , volatile unsigned int * tx ) {
UNUSED ( tx ) ;
2018-12-19 17:02:00 +01:00
parserStatus_e txResult ;
2018-07-31 19:59:59 +02:00
uint32_t i ;
if ( p1 = = P1_FIRST ) {
2020-01-18 12:47:53 +01:00
if ( dataLength < 1 ) {
PRINTF ( " Invalid data \n " ) ;
THROW ( 0x6a80 ) ;
}
if ( appState ! = APP_STATE_IDLE ) {
reset_app_context ( ) ;
}
appState = APP_STATE_SIGNING_TX ;
2018-07-31 19:59:59 +02:00
tmpCtx . transactionContext . pathLength = workBuffer [ 0 ] ;
if ( ( tmpCtx . transactionContext . pathLength < 0x01 ) | |
( tmpCtx . transactionContext . pathLength > MAX_BIP32_PATH ) ) {
PRINTF ( " Invalid path \n " ) ;
THROW ( 0x6a80 ) ;
}
workBuffer + + ;
dataLength - - ;
for ( i = 0 ; i < tmpCtx . transactionContext . pathLength ; i + + ) {
2020-01-18 12:47:53 +01:00
if ( dataLength < 4 ) {
PRINTF ( " Invalid data \n " ) ;
THROW ( 0x6a80 ) ;
}
2019-02-05 14:50:36 +01:00
tmpCtx . transactionContext . bip32Path [ i ] = U4BE ( workBuffer , 0 ) ;
2018-07-31 19:59:59 +02:00
workBuffer + = 4 ;
dataLength - = 4 ;
}
dataPresent = false ;
2019-03-18 14:03:54 +01:00
tokenProvisioned = false ;
2018-07-31 19:59:59 +02:00
initTx ( & txContext , & sha3 , & tmpContent . txContent , customProcessor , NULL ) ;
2018-12-19 17:02:00 +01:00
}
else
2018-07-31 19:59:59 +02:00
if ( p1 ! = P1_MORE ) {
THROW ( 0x6B00 ) ;
}
if ( p2 ! = 0 ) {
THROW ( 0x6B00 ) ;
}
2020-01-18 12:47:53 +01:00
if ( ( p1 = = P1_MORE ) & & ( appState ! = APP_STATE_SIGNING_TX ) ) {
PRINTF ( " Signature not initialized \n " ) ;
THROW ( 0x6985 ) ;
}
2018-07-31 19:59:59 +02:00
if ( txContext . currentField = = TX_RLP_NONE ) {
PRINTF ( " Parser not initialized \n " ) ;
THROW ( 0x6985 ) ;
}
txResult = processTx ( & txContext , workBuffer , dataLength , ( chainConfig - > kind = = CHAIN_KIND_WANCHAIN ? TX_FLAG_TYPE : 0 ) ) ;
switch ( txResult ) {
case USTREAM_SUSPENDED :
break ;
case USTREAM_FINISHED :
break ;
case USTREAM_PROCESSING :
THROW ( 0x9000 ) ;
case USTREAM_FAULT :
THROW ( 0x6A80 ) ;
default :
PRINTF ( " Unexpected parser status \n " ) ;
THROW ( 0x6A80 ) ;
}
2016-10-17 23:40:31 +02:00
2018-07-27 21:02:24 +02:00
* flags | = IO_ASYNCH_REPLY ;
2018-07-31 19:59:59 +02:00
if ( txResult = = USTREAM_FINISHED ) {
finalizeParsing ( true ) ;
2018-12-19 17:02:00 +01:00
}
2016-10-17 23:40:31 +02:00
}
2018-07-27 21:02:24 +02:00
void handleGetAppConfiguration ( uint8_t p1 , uint8_t p2 , uint8_t * workBuffer , uint16_t dataLength , volatile unsigned int * flags , volatile unsigned int * tx ) {
UNUSED ( p1 ) ;
UNUSED ( p2 ) ;
UNUSED ( workBuffer ) ;
UNUSED ( dataLength ) ;
UNUSED ( flags ) ;
2019-02-05 14:50:36 +01:00
G_io_apdu_buffer [ 0 ] = ( N_storage . dataAllowed ? APP_FLAG_DATA_ALLOWED : 0x00 ) ;
# ifndef HAVE_TOKENS_LIST
G_io_apdu_buffer [ 0 ] | = APP_FLAG_EXTERNAL_TOKEN_NEEDED ;
2019-03-18 14:03:54 +01:00
# endif
2018-07-27 21:02:24 +02:00
G_io_apdu_buffer [ 1 ] = LEDGER_MAJOR_VERSION ;
G_io_apdu_buffer [ 2 ] = LEDGER_MINOR_VERSION ;
G_io_apdu_buffer [ 3 ] = LEDGER_PATCH_VERSION ;
* tx = 4 ;
THROW ( 0x9000 ) ;
2016-10-17 23:40:31 +02:00
}
2018-07-27 21:02:24 +02:00
void handleSignPersonalMessage ( uint8_t p1 , uint8_t p2 , uint8_t * workBuffer , uint16_t dataLength , volatile unsigned int * flags , volatile unsigned int * tx ) {
UNUSED ( tx ) ;
uint8_t hashMessage [ 32 ] ;
if ( p1 = = P1_FIRST ) {
char tmp [ 11 ] ;
uint32_t index ;
uint32_t base = 10 ;
uint8_t pos = 0 ;
uint32_t i ;
2020-01-18 12:47:53 +01:00
if ( dataLength < 1 ) {
PRINTF ( " Invalid data \n " ) ;
THROW ( 0x6a80 ) ;
}
if ( appState ! = APP_STATE_IDLE ) {
reset_app_context ( ) ;
}
appState = APP_STATE_SIGNING_MESSAGE ;
2018-07-27 21:02:24 +02:00
tmpCtx . messageSigningContext . pathLength = workBuffer [ 0 ] ;
if ( ( tmpCtx . messageSigningContext . pathLength < 0x01 ) | |
( tmpCtx . messageSigningContext . pathLength > MAX_BIP32_PATH ) ) {
PRINTF ( " Invalid path \n " ) ;
THROW ( 0x6a80 ) ;
}
workBuffer + + ;
dataLength - - ;
for ( i = 0 ; i < tmpCtx . messageSigningContext . pathLength ; i + + ) {
2020-01-18 12:47:53 +01:00
if ( dataLength < 4 ) {
PRINTF ( " Invalid data \n " ) ;
THROW ( 0x6a80 ) ;
}
2019-02-05 14:50:36 +01:00
tmpCtx . messageSigningContext . bip32Path [ i ] = U4BE ( workBuffer , 0 ) ;
2017-03-03 13:49:39 +01:00
workBuffer + = 4 ;
dataLength - = 4 ;
}
2020-01-18 12:47:53 +01:00
if ( dataLength < 4 ) {
PRINTF ( " Invalid data \n " ) ;
THROW ( 0x6a80 ) ;
}
2019-02-05 14:50:36 +01:00
tmpCtx . messageSigningContext . remainingLength = U4BE ( workBuffer , 0 ) ;
2018-07-27 21:02:24 +02:00
workBuffer + = 4 ;
dataLength - = 4 ;
// Initialize message header + length
cx_keccak_init ( & sha3 , 256 ) ;
2020-01-18 12:47:53 +01:00
cx_hash ( ( cx_hash_t * ) & sha3 , 0 , ( uint8_t * ) SIGN_MAGIC , sizeof ( SIGN_MAGIC ) - 1 , NULL , 0 ) ;
2018-07-27 21:02:24 +02:00
for ( index = 1 ; ( ( ( index * base ) < = tmpCtx . messageSigningContext . remainingLength ) & &
( ( ( index * base ) / base ) = = index ) ) ;
index * = base ) ;
for ( ; index ; index / = base ) {
tmp [ pos + + ] = ' 0 ' + ( ( tmpCtx . messageSigningContext . remainingLength / index ) % base ) ;
2017-03-03 13:49:39 +01:00
}
2018-07-27 21:02:24 +02:00
tmp [ pos ] = ' \0 ' ;
2020-01-18 12:47:53 +01:00
cx_hash ( ( cx_hash_t * ) & sha3 , 0 , ( uint8_t * ) tmp , pos , NULL , 0 ) ;
2018-07-27 21:02:24 +02:00
cx_sha256_init ( & tmpContent . sha2 ) ;
2018-12-19 17:02:00 +01:00
}
2018-07-27 21:02:24 +02:00
else if ( p1 ! = P1_MORE ) {
THROW ( 0x6B00 ) ;
}
if ( p2 ! = 0 ) {
THROW ( 0x6B00 ) ;
}
2020-01-18 12:47:53 +01:00
if ( ( p1 = = P1_MORE ) & & ( appState ! = APP_STATE_SIGNING_MESSAGE ) ) {
PRINTF ( " Signature not initialized \n " ) ;
THROW ( 0x6985 ) ;
}
2018-07-27 21:02:24 +02:00
if ( dataLength > tmpCtx . messageSigningContext . remainingLength ) {
THROW ( 0x6A80 ) ;
}
2020-01-18 12:47:53 +01:00
cx_hash ( ( cx_hash_t * ) & sha3 , 0 , workBuffer , dataLength , NULL , 0 ) ;
cx_hash ( ( cx_hash_t * ) & tmpContent . sha2 , 0 , workBuffer , dataLength , NULL , 0 ) ;
2018-07-27 21:02:24 +02:00
tmpCtx . messageSigningContext . remainingLength - = dataLength ;
if ( tmpCtx . messageSigningContext . remainingLength = = 0 ) {
2020-01-18 12:47:53 +01:00
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 ) ;
2017-03-03 13:49:39 +01:00
# define HASH_LENGTH 4
2018-07-31 19:59:59 +02:00
array_hexstr ( strings . common . fullAddress , hashMessage , HASH_LENGTH / 2 ) ;
strings . common . fullAddress [ HASH_LENGTH / 2 * 2 ] = ' . ' ;
strings . common . fullAddress [ HASH_LENGTH / 2 * 2 + 1 ] = ' . ' ;
strings . common . fullAddress [ HASH_LENGTH / 2 * 2 + 2 ] = ' . ' ;
array_hexstr ( strings . common . fullAddress + HASH_LENGTH / 2 * 2 + 3 , hashMessage + 32 - HASH_LENGTH / 2 , HASH_LENGTH / 2 ) ;
2017-03-03 13:49:39 +01:00
2019-02-12 20:41:19 +01:00
# ifdef NO_CONSENT
io_seproxyhal_touch_signMessage_ok ( NULL ) ;
# else NO_CONSENT
2017-05-31 21:51:11 +02:00
# if defined(TARGET_BLUE)
2018-07-27 21:02:24 +02:00
ui_approval_message_sign_blue_init ( ) ;
2020-01-18 12:47:53 +01:00
# elif defined(HAVE_UX_FLOW)
ux_flow_init ( 0 , ux_sign_flow , NULL ) ;
2017-05-31 21:51:11 +02:00
# elif defined(TARGET_NANOS)
2018-07-27 21:02:24 +02:00
ux_step = 0 ;
ux_step_count = 2 ;
UX_DISPLAY ( ui_approval_signMessage_nanos ,
2017-03-03 13:49:39 +01:00
ui_approval_signMessage_prepro ) ;
# endif // #if TARGET_ID
2019-02-12 20:41:19 +01:00
# endif // NO_CONSENT
2017-03-03 13:49:39 +01:00
2018-07-27 21:02:24 +02:00
* flags | = IO_ASYNCH_REPLY ;
2017-03-03 13:49:39 +01:00
2018-07-27 21:02:24 +02:00
} else {
THROW ( 0x9000 ) ;
}
2017-03-03 13:49:39 +01:00
}
2016-10-17 23:40:31 +02:00
void handleApdu ( volatile unsigned int * flags , volatile unsigned int * tx ) {
2018-07-27 21:02:24 +02:00
unsigned short sw = 0 ;
BEGIN_TRY {
TRY {
2020-01-18 12:47:53 +01:00
# 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
2018-07-27 21:02:24 +02:00
if ( G_io_apdu_buffer [ OFFSET_CLA ] ! = CLA ) {
THROW ( 0x6E00 ) ;
}
switch ( G_io_apdu_buffer [ OFFSET_INS ] ) {
2018-12-19 17:02:00 +01:00
case INS_GET_PUBLIC_KEY :
2019-02-05 14:50:36 +01:00
currentTokenSet = false ;
2018-07-27 21:02:24 +02:00
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 ;
2019-02-05 14:50:36 +01:00
case INS_PROVIDE_ERC20_TOKEN_INFORMATION :
currentTokenSet = false ;
2019-03-18 14:03:54 +01:00
handleProvideErc20TokenInformation ( 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 ) ;
2019-02-05 14:50:36 +01:00
break ;
2019-03-18 14:03:54 +01:00
case INS_SIGN :
2018-07-27 21:02:24 +02:00
handleSign ( 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 ;
2018-12-19 17:02:00 +01:00
case INS_GET_APP_CONFIGURATION :
2018-07-27 21:02:24 +02:00
handleGetAppConfiguration ( 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 ;
2018-12-19 17:02:00 +01:00
case INS_SIGN_PERSONAL_MESSAGE :
2019-02-05 14:50:36 +01:00
currentTokenSet = false ;
2018-07-27 21:02:24 +02:00
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 ;
#if 0
case 0xFF : // return to dashboard
goto return_to_dashboard ;
2018-12-19 17:02:00 +01:00
# endif
2018-07-27 21:02:24 +02:00
default :
THROW ( 0x6D00 ) ;
break ;
}
2016-10-17 23:40:31 +02:00
}
2018-07-27 21:02:24 +02:00
CATCH ( EXCEPTION_IO_RESET ) {
THROW ( EXCEPTION_IO_RESET ) ;
}
CATCH_OTHER ( e ) {
switch ( e & 0xF000 ) {
case 0x6000 :
// Wipe the transaction context and report the exception
sw = e ;
2020-01-18 12:47:53 +01:00
reset_app_context ( ) ;
2018-07-27 21:02:24 +02:00
break ;
case 0x9000 :
// All is well
sw = e ;
break ;
default :
// Internal error
sw = 0x6800 | ( e & 0x7FF ) ;
2020-01-18 12:47:53 +01:00
reset_app_context ( ) ;
2018-07-27 21:02:24 +02:00
break ;
}
// Unexpected exception => report
G_io_apdu_buffer [ * tx ] = sw > > 8 ;
G_io_apdu_buffer [ * tx + 1 ] = sw ;
* tx + = 2 ;
}
FINALLY {
}
}
END_TRY ;
2016-10-17 23:40:31 +02:00
}
2016-06-01 21:41:29 +02:00
void sample_main ( void ) {
volatile unsigned int rx = 0 ;
volatile unsigned int tx = 0 ;
volatile unsigned int flags = 0 ;
// DESIGN NOTE: the bootloader ignores the way APDU are fetched. The only
// goal is to retrieve APDU.
// When APDU are to be fetched from multiple IOs, like NFC+USB+BLE, make
// sure the io_event is called with a
// switch event, before the apdu is replied to the bootloader. This avoid
// APDU injection faults.
for ( ; ; ) {
volatile unsigned short sw = 0 ;
BEGIN_TRY {
TRY {
rx = tx ;
tx = 0 ; // ensure no race in catch_other if io_exchange throws
// an error
rx = io_exchange ( CHANNEL_APDU | flags , rx ) ;
2016-07-31 09:36:00 +02:00
flags = 0 ;
2016-06-01 21:41:29 +02:00
// no apdu received, well, reset the session, and reset the
// bootloader configuration
if ( rx = = 0 ) {
THROW ( 0x6982 ) ;
}
2020-01-18 12:47:53 +01:00
PRINTF ( " New APDU received: \n %.*H \n " , rx , G_io_apdu_buffer ) ;
2016-10-17 23:40:31 +02:00
handleApdu ( & flags , & tx ) ;
2016-06-01 21:41:29 +02:00
}
2017-06-02 16:12:08 +02:00
CATCH ( EXCEPTION_IO_RESET ) {
2018-07-27 21:02:24 +02:00
THROW ( EXCEPTION_IO_RESET ) ;
2017-06-02 16:12:08 +02:00
}
2016-06-01 21:41:29 +02:00
CATCH_OTHER ( e ) {
switch ( e & 0xF000 ) {
case 0x6000 :
// Wipe the transaction context and report the exception
sw = e ;
2020-01-18 12:47:53 +01:00
reset_app_context ( ) ;
2016-06-01 21:41:29 +02:00
break ;
case 0x9000 :
// All is well
sw = e ;
break ;
default :
// Internal error
sw = 0x6800 | ( e & 0x7FF ) ;
2020-01-18 12:47:53 +01:00
reset_app_context ( ) ;
2016-06-01 21:41:29 +02:00
break ;
}
2018-07-31 19:59:59 +02:00
if ( e ! = 0x9000 ) {
flags & = ~ IO_ASYNCH_REPLY ;
}
2016-06-01 21:41:29 +02:00
// Unexpected exception => report
G_io_apdu_buffer [ tx ] = sw > > 8 ;
G_io_apdu_buffer [ tx + 1 ] = sw ;
tx + = 2 ;
}
FINALLY {
}
}
END_TRY ;
}
2018-07-27 21:02:24 +02:00
//return_to_dashboard:
2016-06-01 21:41:29 +02:00
return ;
}
2017-01-22 18:26:27 +01:00
// override point, but nothing more to do
2016-06-01 21:41:29 +02:00
void io_seproxyhal_display ( const bagl_element_t * element ) {
2018-07-27 21:02:24 +02:00
io_seproxyhal_display_default ( ( bagl_element_t * ) element ) ;
2016-06-01 21:41:29 +02:00
}
unsigned char io_event ( unsigned char channel ) {
// nothing done with the event, throw an error on the transport layer if
// needed
// can't have more than one tag in the reply, not supported yet.
switch ( G_io_seproxyhal_spi_buffer [ 0 ] ) {
2016-07-31 09:36:00 +02:00
case SEPROXYHAL_TAG_FINGER_EVENT :
2018-07-27 21:02:24 +02:00
UX_FINGER_EVENT ( G_io_seproxyhal_spi_buffer ) ;
break ;
2018-12-19 17:02:00 +01:00
2016-07-31 09:36:00 +02:00
case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT :
UX_BUTTON_PUSH_EVENT ( G_io_seproxyhal_spi_buffer ) ;
break ;
2016-06-01 21:41:29 +02:00
2017-01-22 18:26:27 +01:00
case SEPROXYHAL_TAG_STATUS_EVENT :
2018-07-27 21:02:24 +02:00
if ( G_io_apdu_media = = IO_APDU_MEDIA_USB_HID & & ! ( U4BE ( G_io_seproxyhal_spi_buffer , 3 ) & SEPROXYHAL_TAG_STATUS_EVENT_FLAG_USB_POWERED ) ) {
THROW ( EXCEPTION_IO_RESET ) ;
2016-06-01 21:41:29 +02:00
}
2018-07-27 21:02:24 +02:00
// no break is intentional
2017-01-22 18:26:27 +01:00
default :
UX_DEFAULT_EVENT ( ) ;
2016-07-31 09:36:00 +02:00
break ;
2017-01-22 18:26:27 +01:00
case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT :
UX_DISPLAYED_EVENT ( { } ) ;
2016-07-31 09:36:00 +02:00
break ;
2016-06-01 21:41:29 +02:00
2017-01-22 18:26:27 +01:00
case SEPROXYHAL_TAG_TICKER_EVENT :
2018-12-19 17:02:00 +01:00
UX_TICKER_EVENT ( G_io_seproxyhal_spi_buffer ,
2018-07-27 21:02:24 +02:00
{
2020-01-18 12:47:53 +01:00
# ifndef HAVE_UX_FLOW
2018-07-27 21:02:24 +02:00
if ( UX_ALLOWED ) {
if ( ux_step_count ) {
// prepare next screen
ux_step = ( ux_step + 1 ) % ux_step_count ;
// redisplay screen
2018-12-19 17:02:00 +01:00
UX_REDISPLAY ( ) ;
2017-01-22 18:26:27 +01:00
}
2018-07-27 21:02:24 +02:00
}
2020-01-18 12:47:53 +01:00
# endif // HAVE_UX_FLOW
2017-01-22 18:26:27 +01:00
} ) ;
2016-06-01 21:41:29 +02:00
break ;
}
2016-07-31 09:36:00 +02:00
// close the event if not done previously (by a display or whatever)
if ( ! io_seproxyhal_spi_is_status_sent ( ) ) {
io_seproxyhal_general_status ( ) ;
}
2016-06-01 21:41:29 +02:00
// command has been processed, DO NOT reset the current APDU transport
return 1 ;
}
2016-07-31 09:36:00 +02:00
void app_exit ( void ) {
2018-07-27 21:02:24 +02:00
2016-07-31 09:36:00 +02:00
BEGIN_TRY_L ( exit ) {
TRY_L ( exit ) {
os_sched_exit ( - 1 ) ;
}
FINALLY_L ( exit ) {
2018-07-27 21:02:24 +02:00
2016-07-31 09:36:00 +02:00
}
}
END_TRY_L ( exit ) ;
}
2018-07-27 21:02:24 +02:00
chain_config_t const C_chain_config = {
. coinName = CHAINID_COINNAME " " ,
. chainId = CHAIN_ID ,
. kind = CHAIN_KIND ,
# ifdef TARGET_BLUE
. color_header = COLOR_APP ,
. color_dashboard = COLOR_APP_LIGHT ,
. header_text = CHAINID_UPCASE ,
# endif // TARGET_BLUE
} ;
__attribute__ ( ( section ( " .boot " ) ) ) int main ( int arg0 ) {
# ifdef USE_LIB_ETHEREUM
chain_config_t local_chainConfig ;
os_memmove ( & local_chainConfig , & C_chain_config , sizeof ( chain_config_t ) ) ;
unsigned int libcall_params [ 3 ] ;
unsigned char coinName [ sizeof ( CHAINID_COINNAME ) ] ;
strcpy ( coinName , CHAINID_COINNAME ) ;
# ifdef TARGET_BLUE
unsigned char coinNameUP [ sizeof ( CHAINID_UPCASE ) ] ;
strcpy ( coinNameUP , CHAINID_UPCASE ) ;
local_chainConfig . header_text = coinNameUP ;
# endif // TARGET_BLUE
local_chainConfig . coinName = coinName ;
BEGIN_TRY {
TRY {
// ensure syscall will accept us
check_api_level ( CX_COMPAT_APILEVEL ) ;
// delegate to Ethereum app/lib
libcall_params [ 0 ] = " Ethereum " ;
libcall_params [ 1 ] = 0x100 ; // use the Init call, as we won't exit
libcall_params [ 2 ] = & local_chainConfig ;
os_lib_call ( & libcall_params ) ;
}
FINALLY {
app_exit ( ) ;
}
}
2018-12-19 17:02:00 +01:00
END_TRY ;
# else
2016-06-01 21:41:29 +02:00
// exit critical section
__asm volatile ( " cpsie i " ) ;
2018-07-27 21:02:24 +02:00
if ( arg0 ) {
if ( ( ( unsigned int * ) arg0 ) [ 0 ] ! = 0x100 ) {
os_lib_throw ( INVALID_PARAMETER ) ;
2018-12-19 17:02:00 +01:00
}
2018-07-27 21:02:24 +02:00
chainConfig = ( chain_config_t * ) ( ( unsigned int * ) arg0 ) [ 1 ] ;
}
else {
chainConfig = ( chain_config_t * ) PIC ( & C_chain_config ) ;
}
2020-01-18 12:47:53 +01:00
reset_app_context ( ) ;
2016-06-01 21:41:29 +02:00
2018-07-27 21:02:24 +02:00
// ensure exception will work as planned
os_boot ( ) ;
2017-05-31 21:51:11 +02:00
for ( ; ; ) {
UX_INIT ( ) ;
2016-07-31 09:36:00 +02:00
2017-05-31 21:51:11 +02:00
BEGIN_TRY {
TRY {
io_seproxyhal_init ( ) ;
2019-02-12 20:41:19 +01:00
# ifdef TARGET_NANOX
// grab the current plane mode setting
G_io_app . plane_mode = os_setting_get ( OS_SETTING_PLANEMODE , NULL , 0 ) ;
2019-03-18 14:03:54 +01:00
# endif // TARGET_NANOX
2019-02-12 20:41:19 +01:00
2017-05-31 21:51:11 +02:00
if ( N_storage . initialized ! = 0x01 ) {
2018-07-27 21:02:24 +02:00
internalStorage_t storage ;
storage . dataAllowed = 0x00 ;
2018-08-28 09:12:20 +02:00
storage . contractDetails = 0x00 ;
2018-07-27 21:02:24 +02:00
storage . initialized = 0x01 ;
nvm_write ( & N_storage , ( void * ) & storage , sizeof ( internalStorage_t ) ) ;
2017-05-31 21:51:11 +02:00
}
2018-07-27 21:02:24 +02:00
dataAllowed = N_storage . dataAllowed ;
2018-08-28 09:12:20 +02:00
contractDetails = N_storage . contractDetails ;
2016-10-17 23:40:31 +02:00
2018-07-27 21:02:24 +02:00
USB_power ( 0 ) ;
USB_power ( 1 ) ;
2016-06-01 21:41:29 +02:00
2019-03-18 14:03:54 +01:00
ui_idle ( ) ;
2019-02-12 20:41:19 +01:00
# ifdef HAVE_BLE
BLE_power ( 0 , NULL ) ;
BLE_power ( 1 , " Nano X " ) ;
2019-03-18 14:03:54 +01:00
# endif // HAVE_BLE
2017-01-22 18:26:27 +01:00
2018-07-27 21:02:24 +02:00
# if defined(TARGET_BLUE)
// setup the status bar colors (remembered after wards, even more if another app does not resetup after app switch)
UX_SET_STATUS_BAR_COLOR ( 0xFFFFFF , chainConfig - > color_header ) ;
# endif // #if defined(TARGET_BLUE)
2018-12-19 17:02:00 +01:00
2017-05-31 21:51:11 +02:00
sample_main ( ) ;
}
CATCH ( EXCEPTION_IO_RESET ) {
2018-07-27 21:02:24 +02:00
// reset IO and UX before continuing
continue ;
2017-05-31 21:51:11 +02:00
}
CATCH_ALL {
2018-07-27 21:02:24 +02:00
break ;
2017-05-31 21:51:11 +02:00
}
FINALLY {
}
2016-06-01 21:41:29 +02:00
}
2017-05-31 21:51:11 +02:00
END_TRY ;
2016-06-01 21:41:29 +02:00
}
2018-07-27 21:02:24 +02:00
app_exit ( ) ;
# endif
2016-07-31 09:36:00 +02:00
return 0 ;
2016-06-01 21:41:29 +02:00
}