diff --git a/Makefile b/Makefile index f2add04..5240eb1 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ #******************************************************************************* -# Ledger Nano S -# (c) 2016-2019 Ledger -# +# Ledger App Monero +# (c) 2023 Ledger SAS. +# # 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 @@ -15,188 +15,83 @@ # limitations under the License. #******************************************************************************* -TARGET_NAME := TARGET_NANOX - --include Makefile.env ifeq ($(BOLOS_SDK),) $(error Environment variable BOLOS_SDK is not set) endif include $(BOLOS_SDK)/Makefile.defines -#Monero /44'/128' -APP_LOAD_PARAMS= --path "2147483692/2147483776" --curve secp256k1 $(COMMON_LOAD_PARAMS) --appFlags 0x240 +######################################## +# Mandatory configuration # +######################################## +# Application name APPNAME = "Monero" -ifeq ($(TARGET_NAME),TARGET_NANOS) -ICONNAME = images/icon_monero.gif -else ifeq ($(TARGET_NAME),TARGET_STAX) -ICONNAME = images/icon_monero_stax.gif -else -ICONNAME = images/icon_monero_nanox.gif -endif +# Application version +APPVERSION_M = 1 +APPVERSION_N = 9 +APPVERSION_P = 0 +APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)" -#DEFINES += MONERO_ALPHA -#DEFINES += MONERO_BETA +SPECVERSION = "1.0" + +# Application source files +APP_SOURCE_PATH += src + +# Application icons following guidelines: +# https://developers.ledger.com/docs/embedded-app/design-requirements/#device-icon +ICON_NANOS = icons/app_monero_16px.gif +ICON_NANOX = icons/app_monero_14px.gif +ICON_NANOSP = icons/app_monero_14px.gif +ICON_STAX = icons/app_monero_32px.gif -APPVERSION_M=1 -APPVERSION_N=8 -APPVERSION_P=2 +# Application allowed derivation curves. +CURVE_APP_LOAD_PARAMS = secp256k1 -APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) -SPECVERSION="1.0" +# Application allowed derivation paths. +PATH_APP_LOAD_PARAMS = "44'/128'" + +VARIANT_PARAM = COIN +VARIANT_VALUES = monero + +ENABLE_BLUETOOTH = 1 +ENABLE_NBGL_QRCODE = 1 DEFINES += $(MONERO_CONFIG) DEFINES += MONERO_VERSION_MAJOR=$(APPVERSION_M) MONERO_VERSION_MINOR=$(APPVERSION_N) MONERO_VERSION_MICRO=$(APPVERSION_P) DEFINES += MONERO_VERSION=$(APPVERSION) DEFINES += MONERO_NAME=$(APPNAME) -DEFINES += SPEC_VERSION=$(SPECVERSION) -ifeq ($(TARGET_NAME),TARGET_NANOS) -DEFINES += UI_NANO_S -else ifeq ($(TARGET_NAME),TARGET_STAX) -DEFINES += UI_STAX -DEFINES += NBGL_QRCODE -SDK_SOURCE_PATH += qrcode -else -DEFINES += UI_NANO_X -TARGET_UI := FLOW -endif +DEFINES += SPEC_VERSION=$(SPECVERSION) -#DEFINES += IOCRYPT +# Enable StageNet by default +#DEFINES += MONERO_ALPHA // This will also disable mainnet +#DEFINES += MONERO_BETA -################ -# Default rule # -################ -all: default +#DEFINES += IOCRYPT ############ # Platform # ############ -ifneq ($(NO_CONSENT),) -DEFINES += NO_CONSENT -endif - -DEFINES += OS_IO_SEPROXYHAL -DEFINES += HAVE_SPRINTF -DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=4 IO_HID_EP_LENGTH=64 HAVE_USB_APDU DEFINES += CUSTOM_IO_APDU_BUFFER_SIZE=\(255+5+64\) DEFINES += HAVE_LEGACY_PID -DEFINES += USB_SEGMENT_SIZE=64 DEFINES += U2F_PROXY_MAGIC=\"MOON\" DEFINES += HAVE_IO_U2F HAVE_U2F -DEFINES += UNUSED\(x\)=\(void\)x -DEFINES += APPVERSION=\"$(APPVERSION)\" - -ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_NANOX TARGET_STAX)) -DEFINES += HAVE_BLE BLE_COMMAND_TIMEOUT_MS=2000 -DEFINES += HAVE_BLE_APDU # basic ledger apdu transport over BLE -endif - -ifeq ($(TARGET_NAME),TARGET_NANOS) -DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128 -DEFINES += HAVE_BAGL -else -DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300 -ifneq ($(TARGET_NAME),TARGET_STAX) -DEFINES += HAVE_BAGL BAGL_WIDTH=128 BAGL_HEIGHT=64 -DEFINES += HAVE_GLO096 -DEFINES += HAVE_BAGL_ELLIPSIS # long label truncation feature -DEFINES += HAVE_BAGL_FONT_OPEN_SANS_REGULAR_11PX -DEFINES += HAVE_BAGL_FONT_OPEN_SANS_EXTRABOLD_11PX -DEFINES += HAVE_BAGL_FONT_OPEN_SANS_LIGHT_16PX -endif -endif - -ifeq ($(TARGET_UI),FLOW) -DEFINES += HAVE_UX_FLOW -endif - # Enabling debug PRINTF -DEBUG = 0 ifneq ($(DEBUG),0) - - ifeq ($(TARGET_NAME),TARGET_NANOS) - DEFINES += HAVE_PRINTF PRINTF=screen_printf - else - DEFINES += HAVE_PRINTF PRINTF=mcu_usb_printf - endif - DEFINES += PLINE="PRINTF(\"FILE:%s..LINE:%d\n\",__FILE__,__LINE__)" # Debug options DEFINES += DEBUG_HWDEVICE DEFINES += BYPASS_COMMITMENT_FOR_TESTS DEFINES += IODUMMYCRYPT # or IONOCRYPT # Stagenet network by default DEFINES += MONERO_BETA -else - - DEFINES += PRINTF\(...\)= - DEFINES += PLINE\(...\)= - endif -############## -# Compiler # -############## -ifneq ($(BOLOS_ENV),) -$(info BOLOS_ENV=$(BOLOS_ENV)) -CLANGPATH := $(BOLOS_ENV)/clang-arm-fropi/bin/ -GCCPATH := $(BOLOS_ENV)/gcc-arm-none-eabi-5_3-2016q1/bin/ -else -$(info BOLOS_ENV is not set: falling back to CLANGPATH and GCCPATH) -endif -ifeq ($(CLANGPATH),) -$(info CLANGPATH is not set: clang will be used from PATH) -endif -ifeq ($(GCCPATH),) -$(info GCCPATH is not set: arm-none-eabi-* will be used from PATH) -endif -CC := $(CLANGPATH)clang - -#CFLAGS += -O0 -gdwarf-2 -gstrict-dwarf -CFLAGS += -O3 -Os -#CFLAGS += -fno-jump-tables -fno-lookup-tables -fsave-optimization-record -#$(info $(CFLAGS)) - -AS := $(GCCPATH)arm-none-eabi-gcc - -LD := $(GCCPATH)arm-none-eabi-gcc - -#LDFLAGS += -O0 -gdwarf-2 -gstrict-dwarf -LDFLAGS += -O3 -Os -LDLIBS += -lm -lgcc -lc - -# import rules to compile glyphs(/pone) -include $(BOLOS_SDK)/Makefile.glyphs - ### variables processed by the common makefile.rules of the SDK to grab source files and include dirs -APP_SOURCE_PATH += src -SDK_SOURCE_PATH += lib_stusb lib_stusb_impl lib_u2f - -ifeq ($(TARGET_UI),FLOW) -SDK_SOURCE_PATH += lib_ux -endif - -ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_NANOX TARGET_STAX)) -SDK_SOURCE_PATH += lib_blewbxx lib_blewbxx_impl -endif - -load: all - python -m ledgerblue.loadApp $(APP_LOAD_PARAMS) - -delete: - python -m ledgerblue.deleteApp $(COMMON_DELETE_PARAMS) - -# import generic rules from the user and SDK --include Makefile.rules -include $(BOLOS_SDK)/Makefile.rules - -#add dependency on custom makefile filename -dep/%.d: %.c Makefile +SDK_SOURCE_PATH += lib_u2f -listvariants: - @echo VARIANTS COIN monero +include $(BOLOS_SDK)/Makefile.standard_app diff --git a/icons/app_monero_14px.gif b/icons/app_monero_14px.gif new file mode 100644 index 0000000..fe64cd2 Binary files /dev/null and b/icons/app_monero_14px.gif differ diff --git a/icons/app_monero_16px.gif b/icons/app_monero_16px.gif new file mode 100644 index 0000000..760ccfe Binary files /dev/null and b/icons/app_monero_16px.gif differ diff --git a/icons/app_monero_32px.gif b/icons/app_monero_32px.gif new file mode 100644 index 0000000..0b9408b Binary files /dev/null and b/icons/app_monero_32px.gif differ diff --git a/src/monero_api.h b/src/monero_api.h index 4a174c5..e2584c4 100644 --- a/src/monero_api.h +++ b/src/monero_api.h @@ -21,16 +21,14 @@ #include "monero_vars.h" +void __attribute__((noreturn)) send_error_and_kill_app(int sw); int monero_apdu_reset(void); -int monero_apdu_lock(void); -void monero_lock_and_throw(int sw) __attribute__((noreturn)); void monero_install(unsigned char netId); -void monero_init(void); -void monero_init_private_key(void); -void monero_wipe_private_key(void); +unsigned int monero_init(void); +int monero_init_private_key(void); -void monero_init_ux(void); +int monero_init_ux(void); int monero_dispatch(void); int monero_apdu_put_key(void); @@ -59,7 +57,7 @@ int monero_apdu_get_tx_proof(void); int monero_apdu_open_tx(void); int monero_apdu_open_tx_cont(void); -void monero_reset_tx(int reset_tx_cnt); +int monero_reset_tx(int reset_tx_cnt); int monero_apdu_open_subtx(void); int monero_apdu_set_signature_mode(void); int monero_apdu_stealth(void); @@ -91,9 +89,9 @@ void ui_menu_main_display(void); void ui_menu_show_security_error(void); void ui_menu_show_tx_aborted(void); void ui_export_viewkey_display(unsigned int value); -void ui_menu_any_pubaddr_display(unsigned int value, unsigned char *pub_view, - unsigned char *pub_spend, unsigned char is_subbadress, - unsigned char *paymanetID); +int ui_menu_any_pubaddr_display(unsigned int value, unsigned char *pub_view, + unsigned char *pub_spend, unsigned char is_subbadress, + unsigned char *paymanetID); void ui_menu_pubaddr_display(unsigned int value); unsigned int ui_menu_transaction_start(void); @@ -109,20 +107,20 @@ int monero_base58_public_key(char *str_b58, unsigned char *view, unsigned char * /** unsigned varint amount to uint64 */ uint64_t monero_vamount2uint64(unsigned char *binary); /** binary little endian unsigned int amount to uint64 */ -uint64_t monero_bamount2uint64(unsigned char *binary); +uint64_t monero_bamount2uint64(unsigned char *binary, size_t binary_len); /** unsigned varint amount to str */ int monero_vamount2str(unsigned char *binary, char *str, unsigned int str_len); /** binary little endian unsigned int amount to str */ -int monero_bamount2str(unsigned char *binary, char *str, unsigned int str_len); +int monero_bamount2str(unsigned char *binary, char *str, size_t binary_len, unsigned int str_len); /** uint64 amount to str */ int monero_amount2str(uint64_t xmr, char *str, unsigned int str_len); /** uint64 amount to str */ -void monero_uint642str(uint64_t val, char *str, unsigned int str_len); +unsigned int monero_uint642str(uint64_t val, char *str, unsigned int str_len); int monero_abort_tx(void); int monero_unblind(unsigned char *v, unsigned char *k, unsigned char *AKout, - unsigned int short_amount); + unsigned int short_amount, size_t v_len, size_t k_len, size_t AKout_len); void ui_menu_validation_display(unsigned int value); void ui_menu_validation_display_last(unsigned int value); void ui_menu_fee_validation_display(unsigned int value); @@ -142,11 +140,14 @@ extern const unsigned char C_FAKE_SEC_SPEND_KEY[32]; int is_fake_view_key(unsigned char *s); int is_fake_spend_key(unsigned char *s); -void monero_ge_fromfe_frombytes(unsigned char *ge, unsigned char *bytes); +int monero_ge_fromfe_frombytes(unsigned char *ge, unsigned char *bytes, size_t ge_len, + size_t bytes_len); void monero_sc_add(unsigned char *r, unsigned char *s1, unsigned char *s2); -void monero_hash_to_scalar(unsigned char *scalar, unsigned char *raw, unsigned int len); -void monero_hash_to_ec(unsigned char *ec, unsigned char *ec_pub); -void monero_generate_keypair(unsigned char *ec_pub, unsigned char *ec_priv); +int monero_hash_to_scalar(unsigned char *scalar, unsigned char *raw, size_t scalar_len, + unsigned int len); +int monero_hash_to_ec(unsigned char *ec, unsigned char *ec_pub, size_t ec_len); +int monero_generate_keypair(unsigned char *ec_pub, unsigned char *ec_priv, size_t ec_pub_len, + size_t ec_priv_len); /* * compute s = 8 * (k*P) * @@ -154,10 +155,10 @@ void monero_generate_keypair(unsigned char *ec_pub, unsigned char *ec_priv); * P [in] point in 02 y or 04 x y format * k [in] 32 bytes scalar */ -void monero_generate_key_derivation(unsigned char *drv_data, unsigned char *P, - unsigned char *scalar); -void monero_derivation_to_scalar(unsigned char *scalar, unsigned char *drv_data, - unsigned int out_idx); +int monero_generate_key_derivation(unsigned char *drv_data, unsigned char *P, unsigned char *scalar, + size_t drv_data_len, size_t P_len, size_t scalar_len); +int monero_derivation_to_scalar(unsigned char *scalar, unsigned char *drv_data, + unsigned int out_idx, size_t scalar_len, size_t drv_data_len); /* * compute x = Hps(drv_data,out_idx) + ec_pv * @@ -165,8 +166,9 @@ void monero_derivation_to_scalar(unsigned char *scalar, unsigned char *drv_data, * drv_data [in] 32 bytes derivation data (point) * ec_pv [in] 32 bytes private key */ -void monero_derive_secret_key(unsigned char *x, unsigned char *drv_data, unsigned int out_idx, - unsigned char *ec_priv); +int monero_derive_secret_key(unsigned char *x, unsigned char *drv_data, unsigned int out_idx, + unsigned char *ec_priv, size_t x_len, size_t drv_data_len, + size_t ec_priv_len); /* * compute x = Hps(drv_data,out_idx)*G + ec_pub * @@ -174,18 +176,25 @@ void monero_derive_secret_key(unsigned char *x, unsigned char *drv_data, unsigne * drv_data [in] 32 bytes derivation data (point) * ec_pub [in] 32 bytes public key */ -void monero_derive_public_key(unsigned char *x, unsigned char *drv_data, unsigned int out_idx, - unsigned char *ec_pub); -void monero_secret_key_to_public_key(unsigned char *ec_pub, unsigned char *ec_priv); -void monero_generate_key_image(unsigned char *img, unsigned char *P, unsigned char *x); -void monero_derive_view_tag(unsigned char *view_tag, const unsigned char drv_data[static 32], - unsigned int out_idx); - -void monero_derive_subaddress_public_key(unsigned char *x, unsigned char *pub, - unsigned char *drv_data, unsigned int index); -void monero_get_subaddress_spend_public_key(unsigned char *x, unsigned char *index); -void monero_get_subaddress(unsigned char *C, unsigned char *D, unsigned char *index); -void monero_get_subaddress_secret_key(unsigned char *sub_s, unsigned char *s, unsigned char *index); +int monero_derive_public_key(unsigned char *x, unsigned char *drv_data, unsigned int out_idx, + unsigned char *ec_pub, size_t x_len, size_t drv_data_len, + size_t ec_pub_len); +int monero_secret_key_to_public_key(unsigned char *ec_pub, unsigned char *ec_priv, + size_t ec_pub_len, size_t ec_priv_len); +int monero_generate_key_image(unsigned char *img, unsigned char *P, unsigned char *x, + size_t img_len, size_t x_len); +int monero_derive_view_tag(unsigned char *view_tag, const unsigned char drv_data[static 32], + unsigned int out_idx); + +int monero_derive_subaddress_public_key(unsigned char *x, unsigned char *pub, + unsigned char *drv_data, unsigned int index, size_t x_len, + size_t pub_len, size_t drv_data_len); +int monero_get_subaddress_spend_public_key(unsigned char *x, unsigned char *index, size_t x_len, + size_t index_len); +int monero_get_subaddress(unsigned char *C, unsigned char *D, unsigned char *index, size_t C_len, + size_t D_len, size_t index_len); +int monero_get_subaddress_secret_key(unsigned char *sub_s, unsigned char *s, unsigned char *index, + size_t sub_s_len, size_t s_len, size_t index_len); void monero_clear_words(void); /* ----------------------------------------------------------------------- */ @@ -193,39 +202,27 @@ void monero_clear_words(void); /* ----------------------------------------------------------------------- */ extern const unsigned char C_ED25519_ORDER[]; -void monero_aes_derive(cx_aes_key_t *sk, unsigned char *seed32, unsigned char *a, unsigned char *b); +int monero_aes_derive(cx_aes_key_t *sk, unsigned char *seed32, unsigned char *a, unsigned char *b); void monero_aes_generate(cx_aes_key_t *sk); /* Compute Monero-Hash of data*/ -void monero_hash_init_keccak(cx_hash_t *hasher); +int monero_hash_init_keccak(cx_hash_t *hasher); void monero_hash_init_sha256(cx_hash_t *hasher); -void monero_hash_update(cx_hash_t *hasher, const unsigned char *buf, unsigned int len); +int monero_hash_update(cx_hash_t *hasher, const unsigned char *buf, unsigned int len); int monero_hash_final(cx_hash_t *hasher, unsigned char *out); int monero_hash(unsigned int algo, cx_hash_t *hasher, const unsigned char *buf, unsigned int len, unsigned char *out); -static inline void monero_keccak_init_F(void) { - monero_hash_init_keccak((cx_hash_t *)&G_monero_vstate.keccakF); -} - -static inline void monero_keccak_update_F(const unsigned char *buf, size_t len) { - monero_hash_update((cx_hash_t *)&G_monero_vstate.keccakF, buf, len); -} - -static inline int monero_keccak_final_F(unsigned char *out) { - return monero_hash_final((cx_hash_t *)&G_monero_vstate.keccakF, out); -} - static inline int monero_keccak_F(unsigned char *buf, size_t len, unsigned char *out) { return monero_hash(CX_KECCAK, (cx_hash_t *)&G_monero_vstate.keccakF, buf, len, out); } -static inline void monero_keccak_init_H(void) { - monero_hash_init_keccak((cx_hash_t *)&G_monero_vstate.keccakH); +static inline int monero_keccak_init_H(void) { + return monero_hash_init_keccak((cx_hash_t *)&G_monero_vstate.keccakH); } -static inline void monero_keccak_update_H(const unsigned char *buf, size_t len) { - monero_hash_update((cx_hash_t *)&G_monero_vstate.keccakH, buf, len); +static inline int monero_keccak_update_H(const unsigned char *buf, size_t len) { + return monero_hash_update((cx_hash_t *)&G_monero_vstate.keccakH, buf, len); } static inline int monero_keccak_final_H(unsigned char *out) { @@ -240,8 +237,8 @@ static inline void monero_sha256_commitment_init(void) { monero_hash_init_sha256((cx_hash_t *)&G_monero_vstate.sha256_commitment); } -static inline void monero_sha256_commitment_update(const unsigned char *buf, size_t len) { - monero_hash_update((cx_hash_t *)&G_monero_vstate.sha256_commitment, buf, len); +static inline int monero_sha256_commitment_update(const unsigned char *buf, size_t len) { + return monero_hash_update((cx_hash_t *)&G_monero_vstate.sha256_commitment, buf, len); } static inline int monero_sha256_commitment_final(unsigned char *out) { @@ -253,8 +250,8 @@ static inline void monero_sha256_outkeys_init(void) { monero_hash_init_sha256((cx_hash_t *)&G_monero_vstate.sha256_out_keys); } -static inline void monero_sha256_outkeys_update(const unsigned char *buf, size_t len) { - monero_hash_update((cx_hash_t *)&G_monero_vstate.sha256_out_keys, buf, len); +static inline int monero_sha256_outkeys_update(const unsigned char *buf, size_t len) { + return monero_hash_update((cx_hash_t *)&G_monero_vstate.sha256_out_keys, buf, len); } static inline int monero_sha256_outkeys_final(unsigned char *out) { @@ -264,108 +261,115 @@ static inline int monero_sha256_outkeys_final(unsigned char *out) { /* * check 10 --- */ /* ----------------------------------------------------------------------- */ -unsigned int monero_encode_varint(unsigned char *varint, unsigned int max_len, uint64_t value) { - unsigned int len; - len = 0; +unsigned int monero_encode_varint(unsigned char *varint, unsigned int max_len, uint64_t value, + unsigned int *out_len) { + if (!varint || !out_len) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA; + } + + *out_len = 0; while (value >= 0x80) { - if (len == (max_len - 1)) { - THROW(SW_WRONG_DATA_RANGE); + if (*out_len == (max_len - 1)) { + return SW_WRONG_DATA_RANGE; } - varint[len] = (value & 0x7F) | 0x80; + varint[*out_len] = (value & 0x7F) | 0x80; value = value >> 7; - len++; + *out_len = *out_len + 1; } - varint[len] = value; - return len + 1; + varint[*out_len] = value; + *out_len = *out_len + 1; + return 0; } /* ----------------------------------------------------------------------- */ /* --- assert: max_len>0 --- */ /* ----------------------------------------------------------------------- */ -unsigned int monero_decode_varint(const unsigned char *varint, size_t max_len, uint64_t *value) { +unsigned int monero_decode_varint(const unsigned char *varint, size_t max_len, uint64_t *value, + unsigned int *out_len) { uint64_t v; size_t len; v = 0; len = 0; + if (!varint || !out_len) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA; + } while ((varint[len]) & 0x80) { if (len == (max_len - 1)) { - THROW(SW_WRONG_DATA_RANGE); + return SW_WRONG_DATA_RANGE; } v = v + ((uint64_t)((varint[len]) & 0x7f) << (len * 7)); len++; @@ -116,20 +146,30 @@ unsigned int monero_decode_varint(const unsigned char *varint, size_t max_len, u v = v + ((uint64_t)((varint[len]) & 0x7f) << (len * 7)); *value = v; - return len + 1; + *out_len = len + 1; + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_reverse32(unsigned char *rscal, unsigned char *scal) { +int monero_reverse32(unsigned char *rscal, unsigned char *scal, size_t rscal_len, size_t scal_len) { unsigned char x; unsigned int i; + if (!rscal || !scal) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA; + } + if (rscal_len < 32 || scal_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } for (i = 0; i < 16; i++) { x = scal[i]; rscal[i] = scal[31 - i]; rscal[31 - i] = x; } + return 0; } /* ----------------------------------------------------------------------- */ @@ -139,22 +179,34 @@ void monero_hash_init_sha256(cx_hash_t *hasher) { cx_sha256_init((cx_sha256_t *)hasher); } -void monero_hash_init_keccak(cx_hash_t *hasher) { - cx_keccak_init((cx_sha3_t *)hasher, 256); +int monero_hash_init_keccak(cx_hash_t *hasher) { + int error = cx_keccak_init_no_throw((cx_sha3_t *)hasher, 256); + if (error) { + return SW_SECURITY_INTERNAL; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_hash_update(cx_hash_t *hasher, const unsigned char *buf, unsigned int len) { - cx_hash(hasher, 0, buf, len, NULL, 0); +int monero_hash_update(cx_hash_t *hasher, const unsigned char *buf, unsigned int len) { + int error = cx_hash_no_throw(hasher, 0, buf, len, NULL, 0); + if (error) { + return SW_SECURITY_INTERNAL; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ int monero_hash_final(cx_hash_t *hasher, unsigned char *out) { - return cx_hash(hasher, CX_LAST, NULL, 0, out, 32); + int error = cx_hash_no_throw(hasher, CX_LAST, NULL, 0, out, 32); + if (error) { + return SW_SECURITY_INTERNAL; + } + return 0; } /* ----------------------------------------------------------------------- */ @@ -162,12 +214,20 @@ int monero_hash_final(cx_hash_t *hasher, unsigned char *out) { /* ----------------------------------------------------------------------- */ int monero_hash(unsigned int algo, cx_hash_t *hasher, const unsigned char *buf, unsigned int len, unsigned char *out) { + int err = 0; if (algo == CX_SHA256) { cx_sha256_init((cx_sha256_t *)hasher); } else { - cx_keccak_init((cx_sha3_t *)hasher, 256); + err = cx_keccak_init_no_throw((cx_sha3_t *)hasher, 256); + if (err) { + return SW_SECURITY_INTERNAL; + } + } + err = cx_hash_no_throw(hasher, CX_LAST, buf, len, out, 32); + if (err) { + return SW_SECURITY_INTERNAL; } - return cx_hash(hasher, CX_LAST, buf, len, out, 32); + return 0; } /* ----------------------------------------------------------------------- */ @@ -278,7 +338,9 @@ const unsigned char C_fe_qm5div8[] = { 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd}; -void monero_ge_fromfe_frombytes(unsigned char *ge, unsigned char *bytes) { +int monero_ge_fromfe_frombytes(unsigned char *ge, unsigned char *bytes, size_t ge_len, + size_t bytes_len) { + int error = 0; #define MOD (unsigned char *)C_ED25519_FIELD, 32 #define fe_isnegative(f) (f[31] & 1) #if 0 @@ -309,7 +371,7 @@ void monero_ge_fromfe_frombytes(unsigned char *ge, unsigned char *bytes) { #define rZ (G_monero_vstate.io_buffer + 8 * 32) union { - unsigned char _Pxy[65]; + unsigned char _Pxy[PXY_SIZE]; struct { unsigned char _uv7[32]; unsigned char _v3[32]; @@ -328,65 +390,74 @@ void monero_ge_fromfe_frombytes(unsigned char *ge, unsigned char *bytes) { #endif unsigned char sign; + if (!ge) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA; + } + if (ge_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } // cx works in BE - monero_reverse32(u, bytes); - cx_math_modm(u, 32, (unsigned char *)C_ED25519_FIELD, 32); + error |= monero_reverse32(u, bytes, 32, bytes_len); + error |= cx_math_modm_no_throw(u, 32, (unsigned char *)C_ED25519_FIELD, 32); // go on - cx_math_multm(v, u, u, MOD); /* 2 * u^2 */ - cx_math_addm(v, v, v, MOD); + error |= cx_math_multm_no_throw(v, u, u, MOD); /* 2 * u^2 */ + error |= cx_math_addm_no_throw(v, v, v, MOD); memset(w, 0, 32); - w[31] = 1; /* w = 1 */ - cx_math_addm(w, v, w, MOD); /* w = 2 * u^2 + 1 */ - cx_math_multm(x, w, w, MOD); /* w^2 */ - cx_math_multm(y, (unsigned char *)C_fe_ma2, v, MOD); /* -2 * A^2 * u^2 */ - cx_math_addm(x, x, y, MOD); /* x = w^2 - 2 * A^2 * u^2 */ + w[31] = 1; /* w = 1 */ + error |= cx_math_addm_no_throw(w, v, w, MOD); /* w = 2 * u^2 + 1 */ + error |= cx_math_multm_no_throw(x, w, w, MOD); /* w^2 */ + error |= cx_math_multm_no_throw(y, (unsigned char *)C_fe_ma2, v, MOD); /* -2 * A^2 * u^2 */ + error |= cx_math_addm_no_throw(x, x, y, MOD); /* x = w^2 - 2 * A^2 * u^2 */ // inline fe_divpowm1(r->X, w, x); // (w / x)^(m + 1) => fe_divpowm1(r,u,v) #define _u w #define _v x - cx_math_multm(v3, _v, _v, MOD); - cx_math_multm(v3, v3, _v, MOD); /* v3 = v^3 */ - cx_math_multm(uv7, v3, v3, MOD); - cx_math_multm(uv7, uv7, _v, MOD); - cx_math_multm(uv7, uv7, _u, MOD); /* uv7 = uv^7 */ - cx_math_powm(uv7, uv7, (unsigned char *)C_fe_qm5div8, 32, MOD); /* (uv^7)^((q-5)/8)*/ - cx_math_multm(uv7, uv7, v3, MOD); - cx_math_multm(rX, uv7, w, MOD); /* u^(m+1)v^(-(m+1)) */ + error |= cx_math_multm_no_throw(v3, _v, _v, MOD); + error |= cx_math_multm_no_throw(v3, v3, _v, MOD); /* v3 = v^3 */ + error |= cx_math_multm_no_throw(uv7, v3, v3, MOD); + error |= cx_math_multm_no_throw(uv7, uv7, _v, MOD); + error |= cx_math_multm_no_throw(uv7, uv7, _u, MOD); /* uv7 = uv^7 */ + error |= cx_math_powm_no_throw(uv7, uv7, (unsigned char *)C_fe_qm5div8, 32, + MOD); /* (uv^7)^((q-5)/8)*/ + error |= cx_math_multm_no_throw(uv7, uv7, v3, MOD); + error |= cx_math_multm_no_throw(rX, uv7, w, MOD); /* u^(m+1)v^(-(m+1)) */ #undef _u #undef _v - cx_math_multm(y, rX, rX, MOD); - cx_math_multm(x, y, x, MOD); - cx_math_subm(y, w, x, MOD); + error |= cx_math_multm_no_throw(y, rX, rX, MOD); + error |= cx_math_multm_no_throw(x, y, x, MOD); + error |= cx_math_subm_no_throw(y, w, x, MOD); memcpy(z, C_fe_ma, 32); if (!cx_math_is_zero(y, 32)) { - cx_math_addm(y, w, x, MOD); + error |= cx_math_addm_no_throw(y, w, x, MOD); if (!cx_math_is_zero(y, 32)) { goto negative; } else { - cx_math_multm(rX, rX, (unsigned char *)C_fe_fffb1, MOD); + error |= cx_math_multm_no_throw(rX, rX, (unsigned char *)C_fe_fffb1, MOD); } } else { - cx_math_multm(rX, rX, (unsigned char *)C_fe_fffb2, MOD); + error |= cx_math_multm_no_throw(rX, rX, (unsigned char *)C_fe_fffb2, MOD); } - cx_math_multm(rX, rX, u, MOD); // u * sqrt(2 * A * (A + 2) * w / x) - cx_math_multm(z, z, v, MOD); // -2 * A * u^2 + error |= cx_math_multm_no_throw(rX, rX, u, MOD); // u * sqrt(2 * A * (A + 2) * w / x) + error |= cx_math_multm_no_throw(z, z, v, MOD); // -2 * A * u^2 sign = 0; goto setsign; negative: - cx_math_multm(x, x, (unsigned char *)C_fe_sqrtm1, MOD); - cx_math_subm(y, w, x, MOD); + error |= cx_math_multm_no_throw(x, x, (unsigned char *)C_fe_sqrtm1, MOD); + error |= cx_math_subm_no_throw(y, w, x, MOD); if (!cx_math_is_zero(y, 32)) { - cx_math_addm(y, w, x, MOD); - cx_math_multm(rX, rX, (unsigned char *)C_fe_fffb3, MOD); + error |= cx_math_addm_no_throw(y, w, x, MOD); + error |= cx_math_multm_no_throw(rX, rX, (unsigned char *)C_fe_fffb3, MOD); } else { - cx_math_multm(rX, rX, (unsigned char *)C_fe_fffb4, MOD); + error |= cx_math_multm_no_throw(rX, rX, (unsigned char *)C_fe_fffb4, MOD); } // r->X = sqrt(A * (A + 2) * w / x) // z = -A @@ -394,20 +465,25 @@ void monero_ge_fromfe_frombytes(unsigned char *ge, unsigned char *bytes) { setsign: if (fe_isnegative(rX) != sign) { - cx_math_sub(rX, (unsigned char *)C_ED25519_FIELD, rX, 32); + error |= cx_math_sub(rX, (unsigned char *)C_ED25519_FIELD, rX, 32); } - cx_math_addm(rZ, z, w, MOD); - cx_math_subm(rY, z, w, MOD); - cx_math_multm(rX, rX, rZ, MOD); + error |= cx_math_addm_no_throw(rZ, z, w, MOD); + error |= cx_math_subm_no_throw(rY, z, w, MOD); + error |= cx_math_multm_no_throw(rX, rX, rZ, MOD); // back to monero y-affine - cx_math_invprimem(u, rZ, MOD); + error |= cx_math_invprimem_no_throw(u, rZ, MOD); Pxy[0] = 0x04; - cx_math_multm(&Pxy[1], rX, u, MOD); - cx_math_multm(&Pxy[1 + 32], rY, u, MOD); - cx_edwards_compress_point(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_math_multm_no_throw(&Pxy[1], rX, u, MOD); + error |= cx_math_multm_no_throw(&Pxy[1 + 32], rY, u, MOD); + error |= cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); memcpy(ge, &Pxy[1], 32); + if (error) { + return SW_SECURITY_INTERNAL; + } + return 0; + #undef u #undef v #undef w @@ -431,109 +507,203 @@ void monero_ge_fromfe_frombytes(unsigned char *ge, unsigned char *bytes) { /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_hash_to_scalar(unsigned char *scalar, unsigned char *raw, unsigned int raw_len) { - monero_keccak_F(raw, raw_len, scalar); - monero_reduce(scalar, scalar); +int monero_hash_to_scalar(unsigned char *scalar, unsigned char *raw, size_t scalar_len, + unsigned int raw_len) { + int error; + + error = monero_keccak_F(raw, raw_len, scalar); + if (error) { + return error; + } + + error = monero_reduce(scalar, scalar, scalar_len, scalar_len); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_hash_to_ec(unsigned char *ec, unsigned char *ec_pub) { - monero_keccak_F(ec_pub, 32, ec); - monero_ge_fromfe_frombytes(ec, ec); - monero_ecmul_8(ec, ec); +int monero_hash_to_ec(unsigned char *ec, unsigned char *ec_pub, size_t ec_len) { + int error; + error = monero_keccak_F(ec_pub, 32, ec); + if (error) { + return error; + } + + error = monero_ge_fromfe_frombytes(ec, ec, ec_len, ec_len); + if (error) { + return error; + } + + error = monero_ecmul_8(ec, ec, ec_len, ec_len); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_generate_keypair(unsigned char *ec_pub, unsigned char *ec_priv) { - monero_rng_mod_order(ec_priv); - monero_ecmul_G(ec_pub, ec_priv); +int monero_generate_keypair(unsigned char *ec_pub, unsigned char *ec_priv, size_t ec_pub_len, + size_t ec_priv_len) { + int error; + error = monero_rng_mod_order(ec_priv, ec_priv_len); + if (error) { + return error; + } + + error = monero_ecmul_G(ec_pub, ec_priv, ec_pub_len, ec_priv_len); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- ok --- */ /* ----------------------------------------------------------------------- */ -void monero_generate_key_derivation(unsigned char *drv_data, unsigned char *P, - unsigned char *scalar) { - monero_ecmul_8k(drv_data, P, scalar); +int monero_generate_key_derivation(unsigned char *drv_data, unsigned char *P, unsigned char *scalar, + size_t drv_data_len, size_t P_len, size_t scalar_len) { + return monero_ecmul_8k(drv_data, P, scalar, drv_data_len, P_len, scalar_len); } /* ----------------------------------------------------------------------- */ /* --- ok --- */ /* ----------------------------------------------------------------------- */ -void monero_derivation_to_scalar(unsigned char *scalar, unsigned char *drv_data, - unsigned int out_idx) { +int monero_derivation_to_scalar(unsigned char *scalar, unsigned char *drv_data, + unsigned int out_idx, size_t scalar_len, size_t drv_data_len) { unsigned char varint[32 + 8]; unsigned int len_varint; + int error = 0; + + if (drv_data_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } memcpy(varint, drv_data, 32); - len_varint = monero_encode_varint(varint + 32, 8, out_idx); + error = monero_encode_varint(varint + 32, 8, out_idx, &len_varint); + if (error) { + return error; + } len_varint += 32; - monero_keccak_F(varint, len_varint, varint); - monero_reduce(scalar, varint); + + error = monero_keccak_F(varint, len_varint, varint); + if (error) { + return error; + } + + error = monero_reduce(scalar, varint, scalar_len, sizeof(varint)); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_derive_secret_key(unsigned char *x, unsigned char *drv_data, unsigned int out_idx, - unsigned char *ec_priv) { +int monero_derive_secret_key(unsigned char *x, unsigned char *drv_data, unsigned int out_idx, + unsigned char *ec_priv, size_t x_len, size_t drv_data_len, + size_t ec_priv_len) { unsigned char tmp[32]; + int error; // derivation to scalar - monero_derivation_to_scalar(tmp, drv_data, out_idx); + error = monero_derivation_to_scalar(tmp, drv_data, out_idx, sizeof(tmp), drv_data_len); + if (error) { + return error; + } // generate - monero_addm(x, tmp, ec_priv); + error = monero_addm(x, tmp, ec_priv, x_len, sizeof(tmp), ec_priv_len); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_derive_public_key(unsigned char *x, unsigned char *drv_data, unsigned int out_idx, - unsigned char *ec_pub) { +int monero_derive_public_key(unsigned char *x, unsigned char *drv_data, unsigned int out_idx, + unsigned char *ec_pub, size_t x_len, size_t drv_data_len, + size_t ec_pub_len) { unsigned char tmp[32]; // derivation to scalar - monero_derivation_to_scalar(tmp, drv_data, out_idx); + int error = monero_derivation_to_scalar(tmp, drv_data, out_idx, sizeof(tmp), drv_data_len); + if (error) { + return error; + } // generate - monero_ecmul_G(tmp, tmp); - monero_ecadd(x, tmp, ec_pub); + error = monero_ecmul_G(tmp, tmp, sizeof(tmp), sizeof(tmp)); + if (error) { + return error; + } + + error = monero_ecadd(x, tmp, ec_pub, x_len, sizeof(tmp), ec_pub_len); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_secret_key_to_public_key(unsigned char *ec_pub, unsigned char *ec_priv) { - monero_ecmul_G(ec_pub, ec_priv); +int monero_secret_key_to_public_key(unsigned char *ec_pub, unsigned char *ec_priv, + size_t ec_pub_len, size_t ec_priv_len) { + return monero_ecmul_G(ec_pub, ec_priv, ec_pub_len, ec_priv_len); } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_generate_key_image(unsigned char *img, unsigned char *P, unsigned char *x) { +int monero_generate_key_image(unsigned char *img, unsigned char *P, unsigned char *x, + size_t img_len, size_t x_len) { unsigned char I[32]; - monero_hash_to_ec(I, P); - monero_ecmul_k(img, I, x); + int error; + error = monero_hash_to_ec(I, P, sizeof(I)); + if (error) { + return error; + } + + error = monero_ecmul_k(img, I, x, img_len, sizeof(I), x_len); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_derive_view_tag(unsigned char *view_tag, const unsigned char drv_data[static 32], - unsigned int out_idx) { +int monero_derive_view_tag(unsigned char *view_tag, const unsigned char drv_data[static 32], + unsigned int out_idx) { unsigned char varint[8 + 32 + 8]; unsigned int len_varint; + int error = 0; memcpy(varint, "view_tag", 8); memcpy(varint + 8, drv_data, 32); - len_varint = monero_encode_varint(varint + 8 + 32, 8, out_idx); + error = monero_encode_varint(varint + 8 + 32, 8, out_idx, &len_varint); + if (error) { + return error; + } len_varint += 8 + 32; - monero_keccak_F(varint, len_varint, varint); + + error = monero_keccak_F(varint, len_varint, varint); + if (error) { + return error; + } + *view_tag = varint[0]; + return 0; } /* ======================================================================= */ @@ -543,35 +713,70 @@ void monero_derive_view_tag(unsigned char *view_tag, const unsigned char drv_dat /* ----------------------------------------------------------------------- */ /* --- ok --- */ /* ----------------------------------------------------------------------- */ -void monero_derive_subaddress_public_key(unsigned char *x, unsigned char *pub, - unsigned char *drv_data, unsigned int index) { +int monero_derive_subaddress_public_key(unsigned char *x, unsigned char *pub, + unsigned char *drv_data, unsigned int index, size_t x_len, + size_t pub_len, size_t drv_data_len) { unsigned char scalarG[32]; + int error; - monero_derivation_to_scalar(scalarG, drv_data, index); - monero_ecmul_G(scalarG, scalarG); - monero_ecsub(x, pub, scalarG); + error = monero_derivation_to_scalar(scalarG, drv_data, index, sizeof(scalarG), drv_data_len); + if (error) { + return error; + } + error = monero_ecmul_G(scalarG, scalarG, sizeof(scalarG), sizeof(scalarG)); + if (error) { + return error; + } + error = monero_ecsub(x, pub, scalarG, x_len, pub_len, sizeof(scalarG)); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- ok --- */ /* ----------------------------------------------------------------------- */ -void monero_get_subaddress_spend_public_key(unsigned char *x, unsigned char *index) { +int monero_get_subaddress_spend_public_key(unsigned char *x, unsigned char *index, size_t x_len, + size_t index_len) { + int error; // m = Hs(a || index_major || index_minor) - monero_get_subaddress_secret_key(x, G_monero_vstate.a, index); + error = monero_get_subaddress_secret_key(x, G_monero_vstate.a, index, x_len, + sizeof(G_monero_vstate.a), index_len); + if (error) { + return error; + } + // M = m*G - monero_secret_key_to_public_key(x, x); + error = monero_secret_key_to_public_key(x, x, x_len, x_len); + if (error) { + return error; + } + // D = B + M - monero_ecadd(x, x, G_monero_vstate.B); + error = monero_ecadd(x, x, G_monero_vstate.B, x_len, x_len, sizeof(G_monero_vstate.B)); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_get_subaddress(unsigned char *C, unsigned char *D, unsigned char *index) { +int monero_get_subaddress(unsigned char *C, unsigned char *D, unsigned char *index, size_t C_len, + size_t D_len, size_t index_len) { // retrieve D - monero_get_subaddress_spend_public_key(D, index); + int error = monero_get_subaddress_spend_public_key(D, index, D_len, index_len); + if (error) { + return error; + } // C = a*D - monero_ecmul_k(C, D, G_monero_vstate.a); + error = monero_ecmul_k(C, D, G_monero_vstate.a, C_len, D_len, sizeof(G_monero_vstate.a)); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ @@ -579,16 +784,36 @@ void monero_get_subaddress(unsigned char *C, unsigned char *D, unsigned char *in /* ----------------------------------------------------------------------- */ static const char C_sub_address_prefix[] = {'S', 'u', 'b', 'A', 'd', 'd', 'r', 0}; -void monero_get_subaddress_secret_key(unsigned char *sub_s, unsigned char *s, - unsigned char *index) { +int monero_get_subaddress_secret_key(unsigned char *sub_s, unsigned char *s, unsigned char *index, + size_t sub_s_len, size_t s_len, size_t index_len) { unsigned char in[sizeof(C_sub_address_prefix) + 32 + 8]; + int error; + + if (!s || s_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } + + if (!index || index_len < 8) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } memcpy(in, C_sub_address_prefix, sizeof(C_sub_address_prefix)); memcpy(in + sizeof(C_sub_address_prefix), s, 32); memcpy(in + sizeof(C_sub_address_prefix) + 32, index, 8); // hash_to_scalar with more that 32bytes: - monero_keccak_F(in, sizeof(in), sub_s); - monero_reduce(sub_s, sub_s); + + error = monero_keccak_F(in, sizeof(in), sub_s); + if (error) { + return error; + } + + error = monero_reduce(sub_s, sub_s, sub_s_len, sub_s_len); + if (error) { + return error; + } + return 0; } /* ======================================================================= */ @@ -598,139 +823,267 @@ void monero_get_subaddress_secret_key(unsigned char *sub_s, unsigned char *s, /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_check_scalar_range_1N(unsigned char *s) { +unsigned int monero_check_scalar_range_1N(unsigned char *s, size_t s_len) { unsigned char x[32]; - monero_reverse32(x, s); - if (cx_math_is_zero(x, 32) || cx_math_cmp(x, C_ED25519_ORDER, 32) >= 0) { - THROW(SW_WRONG_DATA_RANGE); + int diff; + int error = monero_reverse32(x, s, sizeof(x), s_len); + if (error) { + return error; + } + if (cx_math_cmp_no_throw(x, C_ED25519_ORDER, 32, &diff)) { + return SW_SECURITY_INTERNAL; + } + if (cx_math_is_zero(x, 32) || diff >= 0) { + return SW_WRONG_DATA_RANGE; } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_check_scalar_not_null(unsigned char *s) { +unsigned int monero_check_scalar_not_null(unsigned char *s) { if (cx_math_is_zero(s, 32)) { - THROW(SW_WRONG_DATA_RANGE); + return SW_WRONG_DATA_RANGE; } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_ecmul_G(unsigned char *W, unsigned char *scalar32) { - unsigned char Pxy[65]; +int monero_ecmul_G(unsigned char *W, unsigned char *scalar32, size_t W_len, size_t scalar32_len) { + unsigned char Pxy[PXY_SIZE]; unsigned char s[32]; - monero_reverse32(s, scalar32); - memcpy(Pxy, C_ED25519_G, 65); - cx_ecfp_scalar_mult(CX_CURVE_Ed25519, Pxy, sizeof(Pxy), s, 32); - cx_edwards_compress_point(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + int error; + + if (!W || W_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } + + error = monero_reverse32(s, scalar32, sizeof(s), scalar32_len); + if (error) { + return error; + } + memcpy(Pxy, C_ED25519_G, PXY_SIZE); + error = cx_ecfp_scalar_mult_no_throw(CX_CURVE_Ed25519, Pxy, s, 32); + if (error) { + return SW_SECURITY_INTERNAL; + } + error = cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + if (error) { + return SW_SECURITY_INTERNAL; + } memcpy(W, &Pxy[1], 32); + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_ecmul_H(unsigned char *W, unsigned char *scalar32) { - unsigned char Pxy[65]; +int monero_ecmul_H(unsigned char *W, unsigned char *scalar32, size_t W_len, size_t scalar32_len) { + unsigned char Pxy[PXY_SIZE]; unsigned char s[32]; - monero_reverse32(s, scalar32); + int error = 0; + + if (!W || W_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } + error = monero_reverse32(s, scalar32, sizeof(s), scalar32_len); + if (error) { + return error; + } Pxy[0] = 0x02; memcpy(&Pxy[1], C_ED25519_Hy, 32); - cx_edwards_decompress_point(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + + error |= cx_ecfp_scalar_mult_no_throw(CX_CURVE_Ed25519, Pxy, s, 32); - cx_ecfp_scalar_mult(CX_CURVE_Ed25519, Pxy, sizeof(Pxy), s, 32); - cx_edwards_compress_point(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + + if (error) { + return SW_SECURITY_INTERNAL; + } memcpy(W, &Pxy[1], 32); + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_ecmul_k(unsigned char *W, unsigned char *P, unsigned char *scalar32) { - unsigned char Pxy[65]; +int monero_ecmul_k(unsigned char *W, unsigned char *P, unsigned char *scalar32, size_t W_len, + size_t P_len, size_t scalar32_len) { + unsigned char Pxy[PXY_SIZE]; unsigned char s[32]; + int error = 0; + + if (!W || W_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } - monero_reverse32(s, scalar32); + if (!P || P_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } + error = monero_reverse32(s, scalar32, sizeof(s), scalar32_len); + if (error) { + return error; + } Pxy[0] = 0x02; memcpy(&Pxy[1], P, 32); - cx_edwards_decompress_point(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); - cx_ecfp_scalar_mult(CX_CURVE_Ed25519, Pxy, sizeof(Pxy), s, 32); - cx_edwards_compress_point(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_ecfp_scalar_mult_no_throw(CX_CURVE_Ed25519, Pxy, s, 32); + error |= cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + if (error) { + return SW_SECURITY_INTERNAL; + } memcpy(W, &Pxy[1], 32); + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_ecmul_8k(unsigned char *W, unsigned char *P, unsigned char *scalar32) { +int monero_ecmul_8k(unsigned char *W, unsigned char *P, unsigned char *scalar32, size_t W_len, + size_t P_len, size_t scalar32_len) { unsigned char s[32]; - monero_multm_8(s, scalar32); - monero_ecmul_k(W, P, s); + int error = 0; + error = monero_multm_8(s, scalar32, sizeof(s), scalar32_len); + if (error) { + return error; + } + + error = monero_ecmul_k(W, P, s, W_len, P_len, sizeof(s)); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_ecmul_8(unsigned char *W, unsigned char *P) { - unsigned char Pxy[65]; +int monero_ecmul_8(unsigned char *W, unsigned char *P, size_t W_len, size_t P_len) { + unsigned char Pxy[PXY_SIZE]; + int error = 0; + + if (!W || W_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } + + if (!P || P_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } Pxy[0] = 0x02; memcpy(&Pxy[1], P, 32); - cx_edwards_decompress_point(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); - cx_ecfp_add_point(CX_CURVE_Ed25519, Pxy, Pxy, Pxy, sizeof(Pxy)); - cx_ecfp_add_point(CX_CURVE_Ed25519, Pxy, Pxy, Pxy, sizeof(Pxy)); - cx_ecfp_add_point(CX_CURVE_Ed25519, Pxy, Pxy, Pxy, sizeof(Pxy)); - cx_edwards_compress_point(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_ecfp_add_point_no_throw(CX_CURVE_Ed25519, Pxy, Pxy, Pxy); + error |= cx_ecfp_add_point_no_throw(CX_CURVE_Ed25519, Pxy, Pxy, Pxy); + error |= cx_ecfp_add_point_no_throw(CX_CURVE_Ed25519, Pxy, Pxy, Pxy); + error |= cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + if (error) { + return SW_SECURITY_INTERNAL; + } memcpy(W, &Pxy[1], 32); + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_ecadd(unsigned char *W, unsigned char *P, unsigned char *Q) { - unsigned char Pxy[65]; - unsigned char Qxy[65]; +int monero_ecadd(unsigned char *W, unsigned char *P, unsigned char *Q, size_t W_len, size_t P_len, + size_t Q_len) { + unsigned char Pxy[PXY_SIZE]; + unsigned char Qxy[PXY_SIZE]; + int error = 0; + + if (!W || W_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } + + if (!P || P_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } + + if (!Q || Q_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } Pxy[0] = 0x02; memcpy(&Pxy[1], P, 32); - cx_edwards_decompress_point(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); Qxy[0] = 0x02; memcpy(&Qxy[1], Q, 32); - cx_edwards_decompress_point(CX_CURVE_Ed25519, Qxy, sizeof(Qxy)); + error |= cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Qxy, sizeof(Qxy)); - cx_ecfp_add_point(CX_CURVE_Ed25519, Pxy, Pxy, Qxy, sizeof(Pxy)); + error |= cx_ecfp_add_point_no_throw(CX_CURVE_Ed25519, Pxy, Pxy, Qxy); - cx_edwards_compress_point(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); memcpy(W, &Pxy[1], 32); + + if (error) { + return SW_SECURITY_INTERNAL; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_ecsub(unsigned char *W, unsigned char *P, unsigned char *Q) { - unsigned char Pxy[65]; - unsigned char Qxy[65]; +int monero_ecsub(unsigned char *W, unsigned char *P, unsigned char *Q, size_t W_len, size_t P_len, + size_t Q_len) { + unsigned char Pxy[PXY_SIZE]; + unsigned char Qxy[PXY_SIZE]; + int error = 0; + + if (!W || W_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } + + if (!P || P_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } + + if (!Q || Q_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } Pxy[0] = 0x02; memcpy(&Pxy[1], P, 32); - cx_edwards_decompress_point(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); Qxy[0] = 0x02; memcpy(&Qxy[1], Q, 32); - cx_edwards_decompress_point(CX_CURVE_Ed25519, Qxy, sizeof(Qxy)); + error |= cx_edwards_decompress_point_no_throw(CX_CURVE_Ed25519, Qxy, sizeof(Qxy)); - cx_math_sub(Qxy + 1, (unsigned char *)C_ED25519_FIELD, Qxy + 1, 32); - cx_ecfp_add_point(CX_CURVE_Ed25519, Pxy, Pxy, Qxy, sizeof(Pxy)); + error |= cx_math_sub(Qxy + 1, (unsigned char *)C_ED25519_FIELD, Qxy + 1, 32); + error |= cx_ecfp_add_point_no_throw(CX_CURVE_Ed25519, Pxy, Pxy, Qxy); - cx_edwards_compress_point(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); + error |= cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519, Pxy, sizeof(Pxy)); memcpy(W, &Pxy[1], 32); + + if (error) { + return SW_SECURITY_INTERNAL; + } + return 0; } /* ----------------------------------------------------------------------- */ @@ -747,11 +1100,19 @@ void monero_ecsub(unsigned char *W, unsigned char *P, unsigned char *Q) { return hash; } */ -void monero_ecdhHash(unsigned char *x, unsigned char *k) { +int monero_ecdhHash(unsigned char *x, unsigned char *k, size_t k_len) { unsigned char data[38]; + int error; + + if (!k || k_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA; + } + memcpy(data, "amount", 6); memcpy(data + 6, k, 32); - monero_keccak_F(data, 38, x); + error = monero_keccak_F(data, 38, x); + return error; } /* ----------------------------------------------------------------------- */ @@ -768,93 +1129,188 @@ void monero_ecdhHash(unsigned char *x, unsigned char *k) { return scalar; } */ -void monero_genCommitmentMask(unsigned char *c, unsigned char *sk) { +int monero_genCommitmentMask(unsigned char *c, unsigned char *sk, size_t c_len, size_t sk_len) { unsigned char data[15 + 32]; + int error; + + if (!sk || sk_len < 32) { + PRINTF("Buffer Error: %s:%d \n", __LINE__); + return SW_WRONG_DATA_RANGE; + } + memcpy(data, "commitment_mask", 15); memcpy(data + 15, sk, 32); - monero_hash_to_scalar(c, data, 15 + 32); + error = monero_hash_to_scalar(c, data, c_len, 15 + 32); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_addm(unsigned char *r, unsigned char *a, unsigned char *b) { +int monero_addm(unsigned char *r, unsigned char *a, unsigned char *b, size_t r_len, size_t a_len, + size_t b_len) { unsigned char ra[32]; unsigned char rb[32]; + int error; - monero_reverse32(ra, a); - monero_reverse32(rb, b); - cx_math_addm(r, ra, rb, (unsigned char *)C_ED25519_ORDER, 32); - monero_reverse32(r, r); + error = monero_reverse32(ra, a, sizeof(ra), a_len); + if (error) { + return error; + } + error = monero_reverse32(rb, b, sizeof(rb), b_len); + if (error) { + return error; + } + error = cx_math_addm_no_throw(r, ra, rb, (unsigned char *)C_ED25519_ORDER, 32); + if (error) { + return SW_SECURITY_INTERNAL; + } + + error = monero_reverse32(r, r, r_len, r_len); + if (error) { + return error; + } + + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_subm(unsigned char *r, unsigned char *a, unsigned char *b) { +int monero_subm(unsigned char *r, unsigned char *a, unsigned char *b, size_t r_len, size_t a_len, + size_t b_len) { unsigned char ra[32]; unsigned char rb[32]; + int error; + + error = monero_reverse32(ra, a, sizeof(ra), a_len); + if (error) { + return error; + } + error = monero_reverse32(rb, b, sizeof(rb), b_len); + if (error) { + return error; + } + error = cx_math_subm_no_throw(r, ra, rb, (unsigned char *)C_ED25519_ORDER, 32); + if (error) { + return SW_SECURITY_INTERNAL; + } - monero_reverse32(ra, a); - monero_reverse32(rb, b); - cx_math_subm(r, ra, rb, (unsigned char *)C_ED25519_ORDER, 32); - monero_reverse32(r, r); + error = monero_reverse32(r, r, r_len, r_len); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_multm(unsigned char *r, unsigned char *a, unsigned char *b) { +int monero_multm(unsigned char *r, unsigned char *a, unsigned char *b, size_t r_len, size_t a_len, + size_t b_len) { unsigned char ra[32]; unsigned char rb[32]; + int error; + + error = monero_reverse32(ra, a, sizeof(ra), a_len); + if (error) { + return error; + } + error = monero_reverse32(rb, b, sizeof(rb), b_len); + if (error) { + return error; + } + error = cx_math_multm_no_throw(r, ra, rb, (unsigned char *)C_ED25519_ORDER, 32); + if (error) { + return SW_SECURITY_INTERNAL; + } - monero_reverse32(ra, a); - monero_reverse32(rb, b); - cx_math_multm(r, ra, rb, (unsigned char *)C_ED25519_ORDER, 32); - monero_reverse32(r, r); + error = monero_reverse32(r, r, r_len, r_len); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_multm_8(unsigned char *r, unsigned char *a) { +int monero_multm_8(unsigned char *r, unsigned char *a, size_t r_len, size_t a_len) { unsigned char ra[32]; unsigned char rb[32]; + int error; - monero_reverse32(ra, a); + error = monero_reverse32(ra, a, sizeof(ra), a_len); + if (error) { + return error; + } memset(rb, 0, 32); rb[31] = 8; - cx_math_multm(r, ra, rb, (unsigned char *)C_ED25519_ORDER, 32); - monero_reverse32(r, r); + error = cx_math_multm_no_throw(r, ra, rb, (unsigned char *)C_ED25519_ORDER, 32); + if (error) { + return SW_SECURITY_INTERNAL; + } + error = monero_reverse32(r, r, r_len, r_len); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_reduce(unsigned char *r, unsigned char *a) { +int monero_reduce(unsigned char *r, unsigned char *a, size_t r_len, size_t a_len) { unsigned char ra[32]; - monero_reverse32(ra, a); - cx_math_modm(ra, 32, (unsigned char *)C_ED25519_ORDER, 32); - monero_reverse32(r, ra); + int error; + + error = monero_reverse32(ra, a, sizeof(ra), a_len); + if (error) { + return error; + } + error = cx_math_modm_no_throw(ra, 32, (unsigned char *)C_ED25519_ORDER, 32); + if (error) { + return SW_SECURITY_INTERNAL; + } + error = monero_reverse32(r, ra, r_len, sizeof(ra)); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_rng_mod_order(unsigned char *r) { +int monero_rng_mod_order(unsigned char *r, size_t r_len) { unsigned char rnd[32 + 8]; + int error; cx_rng(rnd, 32 + 8); - cx_math_modm(rnd, 32 + 8, (unsigned char *)C_ED25519_ORDER, 32); - monero_reverse32(r, rnd + 8); + error = cx_math_modm_no_throw(rnd, 32 + 8, (unsigned char *)C_ED25519_ORDER, 32); + if (error) { + return SW_SECURITY_INTERNAL; + } + error = monero_reverse32(r, rnd + 8, r_len, 32); + if (error) { + return error; + } + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ /* return 0 if ok, 1 if missing decimal */ -void monero_uint642str(uint64_t val, char *str, unsigned int str_len) { +unsigned int monero_uint642str(uint64_t val, char *str, unsigned int str_len) { char stramount[22]; unsigned int offset, len; + if (!str) { + PRINTF("%d \n\n", __LINE__); + return SW_WRONG_DATA; + } memset(str, 0, str_len); offset = 22; @@ -865,9 +1321,10 @@ void monero_uint642str(uint64_t val, char *str, unsigned int str_len) { } len = sizeof(stramount) - offset; if (len > str_len) { - THROW(SW_WRONG_DATA_RANGE); + return SW_WRONG_DATA_RANGE; } memcpy(str, stramount + offset, len); + return 0; } /* ----------------------------------------------------------------------- */ @@ -877,8 +1334,12 @@ void monero_uint642str(uint64_t val, char *str, unsigned int str_len) { int monero_amount2str(uint64_t xmr, char *str, unsigned int str_len) { // max uint64 is 18446744073709551616, aka 20 char, plus dot char stramount[22]; - unsigned int offset, len, ov; + unsigned int offset, len; + if (!str) { + PRINTF("%d \n\n", __LINE__); + return SW_WRONG_DATA; + } memset(str, 0, str_len); memset(stramount, '0', sizeof(stramount)); @@ -886,7 +1347,7 @@ int monero_amount2str(uint64_t xmr, char *str, unsigned int str_len) { // special case if (xmr == 0) { str[0] = '0'; - return 1; + return 0; } // uint64 units to str @@ -917,21 +1378,23 @@ int monero_amount2str(uint64_t xmr, char *str, unsigned int str_len) { len--; } len = len - offset + 1; - ov = 0; if (len > (str_len - 1)) { len = str_len - 1; - ov = 1; } memcpy(str, stramount + offset, len); - return ov; + return 0; } /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -uint64_t monero_bamount2uint64(unsigned char *binary) { +uint64_t monero_bamount2uint64(unsigned char *binary, size_t binary_len) { uint64_t xmr; int i; + if (!binary || binary_len < 8) { + PRINTF("%d \n\n", __LINE__); + return 0; + } xmr = 0; for (i = 7; i >= 0; i--) { xmr = xmr * 256 + binary[i]; @@ -942,8 +1405,8 @@ uint64_t monero_bamount2uint64(unsigned char *binary) { /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -int monero_bamount2str(unsigned char *binary, char *str, unsigned int str_len) { - return monero_amount2str(monero_bamount2uint64(binary), str, str_len); +int monero_bamount2str(unsigned char *binary, char *str, size_t binary_len, unsigned int str_len) { + return monero_amount2str(monero_bamount2uint64(binary, binary_len), str, str_len); } /* ----------------------------------------------------------------------- */ @@ -951,6 +1414,10 @@ int monero_bamount2str(unsigned char *binary, char *str, unsigned int str_len) { /* ----------------------------------------------------------------------- */ int monero_vamount2str(unsigned char *binary, char *str, unsigned int str_len) { uint64_t amount; - monero_decode_varint(binary, 8, &amount); + unsigned int out_len; + unsigned int error = monero_decode_varint(binary, 8, &amount, &out_len); + if (error) { + return error; + } return monero_amount2str(amount, str, str_len); } diff --git a/src/monero_dispatch.c b/src/monero_dispatch.c index 4280260..0766560 100644 --- a/src/monero_dispatch.c +++ b/src/monero_dispatch.c @@ -22,30 +22,19 @@ #include "monero_api.h" #include "monero_vars.h" -void update_protocol() { +static void update_protocol(void) { G_monero_vstate.tx_state_ins = G_monero_vstate.io_ins; G_monero_vstate.tx_state_p1 = G_monero_vstate.io_p1; G_monero_vstate.tx_state_p2 = G_monero_vstate.io_p2; } -void clear_protocol() { +static void clear_protocol(void) { G_monero_vstate.tx_state_ins = 0; G_monero_vstate.tx_state_p1 = 0; G_monero_vstate.tx_state_p2 = 0; } -int check_potocol() { - /* if locked and pin is veririfed, unlock */ - if ((G_monero_vstate.protocol_barrier == PROTOCOL_LOCKED_UNLOCKABLE) && - (os_global_pin_is_validated() == PIN_VERIFIED)) { - G_monero_vstate.protocol_barrier = PROTOCOL_UNLOCKED; - } - - /* if we are locked, deny all command! */ - if (G_monero_vstate.protocol_barrier != PROTOCOL_UNLOCKED) { - return SW_SECURITY_LOCKED; - } - +static int check_protocol(void) { /* the first command enforce the protocol version until application quits */ switch (G_monero_vstate.io_protocol_version) { case 0x00: /* the first one: PCSC epoch */ @@ -72,7 +61,6 @@ int check_ins_access() { } switch (G_monero_vstate.io_ins) { - case INS_LOCK_DISPLAY: case INS_RESET: case INS_PUT_KEY: case INS_GET_KEY: @@ -103,9 +91,6 @@ int check_ins_access() { case INS_OPEN_TX: case INS_SET_SIGNATURE_MODE: - if (os_global_pin_is_validated() != PIN_VERIFIED) { - return SW_SECURITY_PIN_LOCKED; - } return SW_OK; case INS_GEN_TXOUT_KEYS: @@ -115,13 +100,13 @@ int check_ins_access() { case INS_MLSAG: case INS_CLSAG: case INS_GEN_COMMITMENT_MASK: - if (os_global_pin_is_validated() != PIN_VERIFIED) { - return SW_SECURITY_PIN_LOCKED; - } if (G_monero_vstate.tx_in_progress != 1) { return SW_COMMAND_NOT_ALLOWED; } return SW_OK; + case INS_LOCK_DISPLAY: + // Deprecated command + return SW_INS_NOT_SUPPORTED; } return SW_INS_NOT_SUPPORTED; @@ -130,7 +115,14 @@ int check_ins_access() { int monero_dispatch() { int sw; - if (((sw = check_potocol()) != SW_OK) || ((sw = check_ins_access() != SW_OK))) { + sw = check_protocol(); + if (sw != SW_OK) { + monero_io_discard(0); + return sw; + } + + sw = check_ins_access(); + if (sw != SW_OK) { monero_io_discard(0); return sw; } @@ -142,13 +134,6 @@ int monero_dispatch() { return sw; } - if (G_monero_vstate.io_ins == INS_LOCK_DISPLAY) { - sw = monero_apdu_lock(); - return sw; - } - - sw = 0x6F01; - switch (G_monero_vstate.io_ins) { /* --- KEYS --- */ case INS_PUT_KEY: @@ -238,10 +223,13 @@ int monero_dispatch() { case INS_OPEN_TX: // state machine check if (G_monero_vstate.tx_state_ins != 0) { - THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } // 2. command process sw = monero_apdu_open_tx(); + if (sw != 0 && sw != SW_OK) { + return sw; + } update_protocol(); break; @@ -255,7 +243,7 @@ int monero_dispatch() { // 1. state machine check if (G_monero_vstate.tx_in_progress != 0) { // Change sig mode during transacation is not allowed - THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } // 2. command process sw = monero_apdu_set_signature_mode(); @@ -267,14 +255,17 @@ int monero_dispatch() { if (G_monero_vstate.tx_in_progress == 1) { if ((G_monero_vstate.tx_state_ins != INS_OPEN_TX) && (G_monero_vstate.tx_state_ins != INS_STEALTH)) { - THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } if ((G_monero_vstate.io_p1 != 0) || (G_monero_vstate.io_p2 != 0)) { - THROW(SW_WRONG_P1P2); + return SW_WRONG_P1P2; } } // 2. command process sw = monero_apdu_stealth(); + if (sw != 0 && sw != SW_OK) { + return sw; + } if (G_monero_vstate.tx_in_progress == 1) { update_protocol(); } @@ -286,20 +277,23 @@ int monero_dispatch() { if ((G_monero_vstate.tx_state_ins != INS_OPEN_TX) && (G_monero_vstate.tx_state_ins != INS_GEN_TXOUT_KEYS) && (G_monero_vstate.tx_state_ins != INS_STEALTH)) { - THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } if (G_monero_vstate.protocol == 3) { if ((G_monero_vstate.tx_state_ins != INS_OPEN_TX) && (G_monero_vstate.tx_state_ins != INS_GEN_TXOUT_KEYS) && (G_monero_vstate.tx_state_ins != INS_STEALTH)) { - THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } } if ((G_monero_vstate.io_p1 != 0) || (G_monero_vstate.io_p2 != 0)) { - THROW(SW_WRONG_P1P2); + return SW_WRONG_P1P2; } // 2. command process sw = monero_apu_generate_txout_keys(); + if (sw != 0 && sw != SW_OK) { + return sw; + } update_protocol(); break; @@ -308,7 +302,7 @@ int monero_dispatch() { // 1. state machine check if ((G_monero_vstate.tx_state_ins != INS_GEN_TXOUT_KEYS) && (G_monero_vstate.tx_state_ins != INS_PREFIX_HASH)) { - THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } // init prefixhash state machine if (G_monero_vstate.tx_state_ins == INS_GEN_TXOUT_KEYS) { @@ -319,19 +313,19 @@ int monero_dispatch() { // check new state is allowed if (G_monero_vstate.tx_state_p1 == 0) { if (1 != G_monero_vstate.io_p1) { - THROW(SW_SUBCOMMAND_NOT_ALLOWED); + return SW_SUBCOMMAND_NOT_ALLOWED; } } else if (G_monero_vstate.tx_state_p1 == 1) { if ((G_monero_vstate.io_p1 != 2) || (G_monero_vstate.io_p2 != 1)) { - THROW(SW_SUBCOMMAND_NOT_ALLOWED); + return SW_SUBCOMMAND_NOT_ALLOWED; } } else if (G_monero_vstate.tx_state_p1 == 2) { if ((G_monero_vstate.io_p1 != 2) || (G_monero_vstate.io_p2 - 1 != G_monero_vstate.tx_state_p2)) { - THROW(SW_SUBCOMMAND_NOT_ALLOWED); + return SW_SUBCOMMAND_NOT_ALLOWED; } } else { - THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } // 2. command process if (G_monero_vstate.io_p1 == 1) { @@ -339,7 +333,10 @@ int monero_dispatch() { } else if (G_monero_vstate.io_p1 == 2) { sw = monero_apdu_prefix_hash_update(); } else { - THROW(SW_WRONG_P1P2); + return SW_WRONG_P1P2; + } + if (sw != 0 && sw != SW_OK) { + return sw; } update_protocol(); break; @@ -350,15 +347,18 @@ int monero_dispatch() { if (G_monero_vstate.protocol == 3) { if ((G_monero_vstate.tx_state_ins != INS_PREFIX_HASH) && (G_monero_vstate.tx_state_ins != INS_GEN_COMMITMENT_MASK)) { - THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } } if ((G_monero_vstate.io_p1 != 0) || (G_monero_vstate.io_p2 != 0)) { - THROW(SW_WRONG_P1P2); + return SW_WRONG_P1P2; } // 2. command process sw = monero_apdu_gen_commitment_mask(); + if (sw != 0 && sw != SW_OK) { + return sw; + } update_protocol(); break; @@ -369,22 +369,25 @@ int monero_dispatch() { if (G_monero_vstate.protocol == 3) { if ((G_monero_vstate.tx_state_ins != INS_PREFIX_HASH) && (G_monero_vstate.tx_state_ins != INS_BLIND)) { - THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } } } else if (G_monero_vstate.tx_sig_mode == TRANSACTION_CREATE_REAL) { if ((G_monero_vstate.tx_state_ins != INS_GEN_COMMITMENT_MASK) && (G_monero_vstate.tx_state_ins != INS_BLIND)) { - THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } } else { - THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } // 2. command process if ((G_monero_vstate.io_p1 != 0) || (G_monero_vstate.io_p2 != 0)) { - THROW(SW_WRONG_P1P2); + return SW_WRONG_P1P2; } sw = monero_apdu_blind(); + if (sw != 0 && sw != SW_OK) { + return sw; + } update_protocol(); break; @@ -393,7 +396,7 @@ int monero_dispatch() { // 1. state machine check if ((G_monero_vstate.tx_state_ins != INS_BLIND) && (G_monero_vstate.tx_state_ins != INS_VALIDATE)) { - THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } // init PREHASH state machine if (G_monero_vstate.tx_state_ins == INS_BLIND) { @@ -401,20 +404,20 @@ int monero_dispatch() { G_monero_vstate.tx_state_p1 = 1; G_monero_vstate.tx_state_p2 = 0; if ((G_monero_vstate.io_p1 != 1) || (G_monero_vstate.io_p2 != 1)) { - THROW(SW_SUBCOMMAND_NOT_ALLOWED); + return SW_SUBCOMMAND_NOT_ALLOWED; } } // check new state is allowed if (G_monero_vstate.tx_state_p1 == G_monero_vstate.io_p1) { if (G_monero_vstate.tx_state_p2 != G_monero_vstate.io_p2 - 1) { - THROW(SW_SUBCOMMAND_NOT_ALLOWED); + return SW_SUBCOMMAND_NOT_ALLOWED; } } else if (G_monero_vstate.tx_state_p1 == G_monero_vstate.io_p1 - 1) { if (1 != G_monero_vstate.io_p2) { - THROW(SW_SUBCOMMAND_NOT_ALLOWED); + return SW_SUBCOMMAND_NOT_ALLOWED; } } else { - THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } // 2. command process if (G_monero_vstate.io_p1 == 1) { @@ -424,7 +427,10 @@ int monero_dispatch() { } else if (G_monero_vstate.io_p1 == 3) { sw = monero_apdu_mlsag_prehash_finalize(); } else { - THROW(SW_WRONG_P1P2); + return SW_WRONG_P1P2; + } + if (sw != 0 && sw != SW_OK) { + return sw; } update_protocol(); break; @@ -435,28 +441,28 @@ int monero_dispatch() { if ((G_monero_vstate.tx_state_ins != INS_VALIDATE) && // (G_monero_vstate.tx_state_ins != INS_MLSAG) && // (G_monero_vstate.protocol != 3 && G_monero_vstate.protocol != 4)) { - THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } if (G_monero_vstate.tx_state_ins == INS_VALIDATE) { if ((G_monero_vstate.tx_state_p1 != 3) || (G_monero_vstate.io_p1 != 1) || (G_monero_vstate.io_p2 != 0)) { - THROW(SW_SUBCOMMAND_NOT_ALLOWED); + return SW_SUBCOMMAND_NOT_ALLOWED; } } else { if (G_monero_vstate.tx_state_p1 == 1) { if (2 != G_monero_vstate.io_p1) { - THROW(SW_SUBCOMMAND_NOT_ALLOWED); + return SW_SUBCOMMAND_NOT_ALLOWED; } } else if (G_monero_vstate.tx_state_p1 == 2) { if ((2 != G_monero_vstate.io_p1) && (3 != G_monero_vstate.io_p1)) { - THROW(SW_SUBCOMMAND_NOT_ALLOWED); + return SW_SUBCOMMAND_NOT_ALLOWED; } } else if (G_monero_vstate.tx_state_p1 == 3) { if (1 != G_monero_vstate.io_p1) { - THROW(SW_SUBCOMMAND_NOT_ALLOWED); + return SW_SUBCOMMAND_NOT_ALLOWED; } } else { - THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } } @@ -468,7 +474,10 @@ int monero_dispatch() { } else if (G_monero_vstate.io_p1 == 3) { sw = monero_apdu_mlsag_sign(); } else { - THROW(SW_WRONG_P1P2); + return SW_WRONG_P1P2; + } + if (sw != 0 && sw != SW_OK) { + return sw; } update_protocol(); break; @@ -479,28 +488,28 @@ int monero_dispatch() { if ((G_monero_vstate.tx_state_ins != INS_VALIDATE) && // (G_monero_vstate.tx_state_ins != INS_CLSAG) && // (G_monero_vstate.protocol != 4)) { - THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } if (G_monero_vstate.tx_state_ins == INS_VALIDATE) { if ((G_monero_vstate.tx_state_p1 != 3) || (G_monero_vstate.io_p1 != 1) || (G_monero_vstate.io_p2 != 0)) { - THROW(SW_SUBCOMMAND_NOT_ALLOWED); + return SW_SUBCOMMAND_NOT_ALLOWED; } } else { if (G_monero_vstate.tx_state_p1 == 1) { if (2 != G_monero_vstate.io_p1) { - THROW(SW_SUBCOMMAND_NOT_ALLOWED); + return SW_SUBCOMMAND_NOT_ALLOWED; } } else if (G_monero_vstate.tx_state_p1 == 2) { if ((2 != G_monero_vstate.io_p1) && (3 != G_monero_vstate.io_p1)) { - THROW(SW_SUBCOMMAND_NOT_ALLOWED); + return SW_SUBCOMMAND_NOT_ALLOWED; } } else if (G_monero_vstate.tx_state_p1 == 3) { if (1 != G_monero_vstate.io_p1) { - THROW(SW_SUBCOMMAND_NOT_ALLOWED); + return SW_SUBCOMMAND_NOT_ALLOWED; } } else { - THROW(SW_COMMAND_NOT_ALLOWED); + return SW_COMMAND_NOT_ALLOWED; } } @@ -512,7 +521,10 @@ int monero_dispatch() { } else if (G_monero_vstate.io_p1 == 3) { sw = monero_apdu_clsag_sign(); } else { - THROW(SW_WRONG_P1P2); + return SW_WRONG_P1P2; + } + if (sw != 0 && sw != SW_OK) { + return sw; } update_protocol(); break; @@ -520,8 +532,7 @@ int monero_dispatch() { /* --- KEYS --- */ default: - THROW(SW_INS_NOT_SUPPORTED); - break; + return SW_INS_NOT_SUPPORTED; } return sw; } diff --git a/src/monero_init.c b/src/monero_init.c index 215f9b4..69472ee 100644 --- a/src/monero_init.c +++ b/src/monero_init.c @@ -37,7 +37,7 @@ const unsigned char C_FAKE_SEC_SPEND_KEY[32] = { /* ----------------------------------------------------------------------- */ /* --- Boot --- */ /* ----------------------------------------------------------------------- */ -void monero_init() { +unsigned int monero_init() { memset(&G_monero_vstate, 0, sizeof(monero_v_state_t)); // first init ? @@ -50,32 +50,30 @@ void monero_init() { } G_monero_vstate.protocol = 0xff; - G_monero_vstate.protocol_barrier = PROTOCOL_UNLOCKED; // load key - monero_init_private_key(); + unsigned error = monero_init_private_key(); + if (error) { + return error; + } // ux conf - monero_init_ux(); + error = monero_init_ux(); + if (error) { + return error; + } // Let's go! G_monero_vstate.state = STATE_IDLE; + return 0; } /* ----------------------------------------------------------------------- */ /* --- init private keys --- */ /* ----------------------------------------------------------------------- */ -void monero_wipe_private_key() { - memset(G_monero_vstate.a, 0, 32); - memset(G_monero_vstate.b, 0, 32); - memset(G_monero_vstate.A, 0, 32); - memset(G_monero_vstate.B, 0, 32); - memset(&G_monero_vstate.spk, 0, sizeof(G_monero_vstate.spk)); - G_monero_vstate.key_set = 0; -} - -void monero_init_private_key() { +int monero_init_private_key(void) { unsigned int path[5]; - unsigned char seed[32]; + unsigned char seed[64]; unsigned char chain[32]; + int error; // generate account keys @@ -86,15 +84,34 @@ void monero_init_private_key() { path[2] = 0x80000000 | N_monero_pstate->account_id; path[3] = 0x00000000; path[4] = 0x00000000; - os_perso_derive_node_bip32(CX_CURVE_SECP256K1, path, 5, seed, chain); + if (os_derive_bip32_no_throw(CX_CURVE_SECP256K1, path, 5, seed, chain)) { + return SW_SECURITY_INTERNAL; + } switch (N_monero_pstate->key_mode) { case KEY_MODE_SEED: - monero_keccak_F(seed, 32, G_monero_vstate.b); - monero_reduce(G_monero_vstate.b, G_monero_vstate.b); - monero_keccak_F(G_monero_vstate.b, 32, G_monero_vstate.a); - monero_reduce(G_monero_vstate.a, G_monero_vstate.a); + error = monero_keccak_F(seed, 32, G_monero_vstate.b); + if (error) { + return error; + } + + error = monero_reduce(G_monero_vstate.b, G_monero_vstate.b, sizeof(G_monero_vstate.b), + sizeof(G_monero_vstate.b)); + if (error) { + return error; + } + + error = monero_keccak_F(G_monero_vstate.b, 32, G_monero_vstate.a); + if (error) { + return error; + } + + error = monero_reduce(G_monero_vstate.a, G_monero_vstate.a, sizeof(G_monero_vstate.a), + sizeof(G_monero_vstate.a)); + if (error) { + return error; + } break; case KEY_MODE_EXTERNAL: @@ -103,30 +120,43 @@ void monero_init_private_key() { break; default: - THROW(SW_SECURITY_LOAD_KEY); - return; + return SW_SECURITY_LOAD_KEY; + } + error = monero_ecmul_G(G_monero_vstate.A, G_monero_vstate.a, sizeof(G_monero_vstate.A), + sizeof(G_monero_vstate.a)); + if (error) { + return error; + } + error = monero_ecmul_G(G_monero_vstate.B, G_monero_vstate.b, sizeof(G_monero_vstate.B), + sizeof(G_monero_vstate.b)); + if (error) { + return error; } - monero_ecmul_G(G_monero_vstate.A, G_monero_vstate.a); - monero_ecmul_G(G_monero_vstate.B, G_monero_vstate.b); // generate key protection - monero_aes_derive(&G_monero_vstate.spk, chain, G_monero_vstate.a, G_monero_vstate.b); + error = monero_aes_derive(&G_monero_vstate.spk, chain, G_monero_vstate.a, G_monero_vstate.b); + if (error) { + return error; + } G_monero_vstate.key_set = 1; + return 0; } /* ----------------------------------------------------------------------- */ /* --- Set up ui/ux --- */ /* ----------------------------------------------------------------------- */ -void monero_init_ux() { - monero_base58_public_key(G_monero_vstate.ux_address, G_monero_vstate.A, G_monero_vstate.B, 0, - NULL); +int monero_init_ux() { + int error = monero_base58_public_key(G_monero_vstate.ux_address, G_monero_vstate.A, + G_monero_vstate.B, 0, NULL); + if (error) { + return error; + } + memset(G_monero_vstate.ux_wallet_public_short_address, '.', sizeof(G_monero_vstate.ux_wallet_public_short_address)); -#ifdef HAVE_UX_FLOW - -#ifdef UI_NANO_X +#ifndef TARGET_NANOS snprintf(G_monero_vstate.ux_wallet_account_name, sizeof(G_monero_vstate.ux_wallet_account_name), "XMR / %d", N_monero_pstate->account_id); memcpy(G_monero_vstate.ux_wallet_public_short_address, G_monero_vstate.ux_address, 5); @@ -142,16 +172,7 @@ void monero_init_ux() { G_monero_vstate.ux_wallet_public_short_address[10] = 0; #endif -#else - - snprintf(G_monero_vstate.ux_wallet_account_name, sizeof(G_monero_vstate.ux_wallet_account_name), - "XMR / %d", N_monero_pstate->account_id); - memcpy(G_monero_vstate.ux_wallet_public_short_address, G_monero_vstate.ux_address, 5); - memcpy(G_monero_vstate.ux_wallet_public_short_address + 7, G_monero_vstate.ux_address + 95 - 5, - 5); - G_monero_vstate.ux_wallet_public_short_address[12] = 0; - -#endif + return 0; } /* ----------------------------------------------------------------------- */ @@ -209,37 +230,23 @@ int monero_apdu_reset() { memset(client_version, '\0', 16); client_version_len = G_monero_vstate.io_length - G_monero_vstate.io_offset; if (client_version_len > 14) { - THROW(SW_CLIENT_NOT_SUPPORTED + 1); + return SW_CLIENT_NOT_SUPPORTED + 1; } monero_io_fetch((unsigned char*)&client_version[0], client_version_len); // Add '.' suffix to avoid 'X.1' prefixing 'X.10' client_version[client_version_len] = '.'; if (!is_client_version_valid(client_version)) { - THROW(SW_CLIENT_NOT_SUPPORTED); + return SW_CLIENT_NOT_SUPPORTED; } monero_io_discard(0); - monero_init(); + unsigned int error = monero_init(); + if (error) { + return error; + } monero_io_insert_u8(MONERO_VERSION_MAJOR); monero_io_insert_u8(MONERO_VERSION_MINOR); monero_io_insert_u8(MONERO_VERSION_MICRO); return SW_OK; } - -/* ----------------------------------------------------------------------- */ -/* --- LOCK --- */ -/* ----------------------------------------------------------------------- */ -int monero_apdu_lock() { - monero_io_discard(0); - monero_lock_and_throw(SW_SECURITY_LOCKED); - return SW_SECURITY_LOCKED; -} - -void monero_lock_and_throw(int sw) { - G_monero_vstate.protocol_barrier = PROTOCOL_LOCKED; - snprintf(G_monero_vstate.ux_info1, sizeof(G_monero_vstate.ux_info1), "Security Err"); - snprintf(G_monero_vstate.ux_info2, sizeof(G_monero_vstate.ux_info2), "%x", sw); - ui_menu_show_security_error(); - THROW(sw); -} diff --git a/src/monero_io.c b/src/monero_io.c index 0f350bb..84f1d39 100644 --- a/src/monero_io.c +++ b/src/monero_io.c @@ -21,6 +21,8 @@ #include "monero_types.h" #include "monero_api.h" #include "monero_vars.h" +#include "os_utils.h" +#include "read.h" #if defined(IODUMMYCRYPT) #warning IODUMMYCRYPT activated @@ -38,19 +40,7 @@ /* ----------------------------------------------------------------------- */ /* MISC */ /* ----------------------------------------------------------------------- */ -void monero_io_set_offset(unsigned int offset) { - if (offset == IO_OFFSET_END) { - G_monero_vstate.io_offset = G_monero_vstate.io_length; - } else if (offset == IO_OFFSET_MARK) { - G_monero_vstate.io_offset = G_monero_vstate.io_mark; - } else if (offset < G_monero_vstate.io_length) { - G_monero_vstate.io_offset = offset; - } else { - THROW(ERROR_IO_OFFSET); - } -} - -void monero_io_mark() { +void monero_io_mark(void) { G_monero_vstate.io_mark = G_monero_vstate.io_offset; } @@ -68,7 +58,7 @@ void monero_io_discard(int clear) { } } -void monero_io_clear() { +void monero_io_clear(void) { memset(G_monero_vstate.io_buffer, 0, MONERO_IO_BUFFER_LENGTH); } @@ -78,7 +68,7 @@ void monero_io_clear() { void monero_io_hole(unsigned int sz) { if ((G_monero_vstate.io_length + sz) > MONERO_IO_BUFFER_LENGTH) { - THROW(ERROR_IO_FULL); + send_error_and_kill_app(ERROR_IO_FULL); } memmove(G_monero_vstate.io_buffer + G_monero_vstate.io_offset + sz, G_monero_vstate.io_buffer + G_monero_vstate.io_offset, @@ -87,15 +77,21 @@ void monero_io_hole(unsigned int sz) { } void monero_io_insert(unsigned char const* buff, unsigned int len) { + if (!buff) { + send_error_and_kill_app(ERROR_IO_FULL); + } monero_io_hole(len); memcpy(G_monero_vstate.io_buffer + G_monero_vstate.io_offset, buff, len); G_monero_vstate.io_offset += len; } void monero_io_insert_hmac_for(unsigned char* buffer, int len, int type) { + if (!buffer) { + send_error_and_kill_app(ERROR_IO_FULL); + } // for now, only 32bytes block are allowed if (len != 32) { - THROW(SW_WRONG_DATA); + send_error_and_kill_app(ERROR_IO_FULL); } unsigned char hmac[32 + 1 + 4]; @@ -117,23 +113,29 @@ void monero_io_insert_hmac_for(unsigned char* buffer, int len, int type) { monero_io_insert(hmac, 32); } -void monero_io_insert_encrypt(unsigned char* buffer, int len, int type) { +void monero_io_insert_encrypt(unsigned char* buffer, size_t len, int type) { + if (!buffer) { + send_error_and_kill_app(ERROR_IO_FULL); + } + // for now, only 32bytes block are allowed if (len != 32) { - THROW(SW_WRONG_DATA); + send_error_and_kill_app(ERROR_IO_FULL); } monero_io_hole(len); #if defined(IODUMMYCRYPT) - for (int i = 0; i < len; i++) { + for (unsigned int i = 0; i < len; i++) { G_monero_vstate.io_buffer[G_monero_vstate.io_offset + i] = buffer[i] ^ 0x55; } #elif defined(IONOCRYPT) memcpy(G_monero_vstate.io_buffer + G_monero_vstate.io_offset, buffer, len); #else - cx_aes(&G_monero_vstate.spk, CX_ENCRYPT | CX_CHAIN_CBC | CX_LAST | CX_PAD_NONE, buffer, len, - G_monero_vstate.io_buffer + G_monero_vstate.io_offset, len); + if (cx_aes_no_throw(&G_monero_vstate.spk, CX_ENCRYPT | CX_CHAIN_CBC | CX_LAST | CX_PAD_NONE, + buffer, len, G_monero_vstate.io_buffer + G_monero_vstate.io_offset, &len)) { + send_error_and_kill_app(SW_SECURITY_INTERNAL); + } #endif G_monero_vstate.io_offset += len; if (G_monero_vstate.tx_in_progress) { @@ -144,25 +146,13 @@ void monero_io_insert_encrypt(unsigned char* buffer, int len, int type) { void monero_io_insert_u32(unsigned int v32) { monero_io_hole(4); - G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 0] = v32 >> 24; - G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 1] = v32 >> 16; - G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 2] = v32 >> 8; - G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 3] = v32 >> 0; + U4BE_ENCODE(G_monero_vstate.io_buffer, G_monero_vstate.io_offset, v32); G_monero_vstate.io_offset += 4; } -void monero_io_insert_u24(unsigned int v24) { - monero_io_hole(3); - G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 0] = v24 >> 16; - G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 1] = v24 >> 8; - G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 2] = v24 >> 0; - G_monero_vstate.io_offset += 3; -} - void monero_io_insert_u16(unsigned int v16) { monero_io_hole(2); - G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 0] = v16 >> 8; - G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 1] = v16 >> 0; + U2BE_ENCODE(G_monero_vstate.io_buffer, G_monero_vstate.io_offset, v16); G_monero_vstate.io_offset += 2; } @@ -205,24 +195,33 @@ int monero_io_fetch_available(void) { } void monero_io_assert_available(int sz) { if ((G_monero_vstate.io_length - G_monero_vstate.io_offset) < sz) { - THROW(SW_WRONG_LENGTH + (sz & 0xFF)); + send_error_and_kill_app(ERROR_IO_FULL); } } +void monero_io_skip(int len) { + monero_io_assert_available(len); + G_monero_vstate.io_offset += len; +} + int monero_io_fetch(unsigned char* buffer, int len) { monero_io_assert_available(len); - if (buffer) { - memcpy(buffer, G_monero_vstate.io_buffer + G_monero_vstate.io_offset, len); + if (!buffer) { + send_error_and_kill_app(ERROR_IO_FULL); } + memcpy(buffer, G_monero_vstate.io_buffer + G_monero_vstate.io_offset, len); G_monero_vstate.io_offset += len; return len; } -static void monero_io_verify_hmac_for(const unsigned char* buffer, int len, - unsigned char* expected_hmac, int type) { +static int monero_io_verify_hmac_for(const unsigned char* buffer, int len, + unsigned char* expected_hmac, int type) { + if (!buffer || !expected_hmac) { + return SW_WRONG_DATA; + } // for now, only 32bytes block allowed if (len != 32) { - THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; } unsigned char hmac[37]; @@ -241,35 +240,41 @@ static void monero_io_verify_hmac_for(const unsigned char* buffer, int len, } cx_hmac_sha256(G_monero_vstate.hmac_key, 32, hmac, 37, hmac, 32); if (memcmp(hmac, expected_hmac, 32) != 0) { - monero_lock_and_throw(SW_SECURITY_HMAC); + return SW_SECURITY_HMAC; } + return 0; } -int monero_io_fetch_decrypt(unsigned char* buffer, int len, int type) { +int monero_io_fetch_decrypt(unsigned char* buffer, size_t len, int type) { + int error = 0; // for now, only 32bytes block allowed if (len != 32) { - THROW(SW_WRONG_LENGTH); + return SW_WRONG_LENGTH; } if (G_monero_vstate.tx_in_progress) { monero_io_assert_available(len + 32); - monero_io_verify_hmac_for(G_monero_vstate.io_buffer + G_monero_vstate.io_offset, len, - G_monero_vstate.io_buffer + G_monero_vstate.io_offset + len, - type); + error = monero_io_verify_hmac_for( + G_monero_vstate.io_buffer + G_monero_vstate.io_offset, len, + G_monero_vstate.io_buffer + G_monero_vstate.io_offset + len, type); + if (error) { + return error; + } } else { monero_io_assert_available(len); } if (buffer) { #if defined(IODUMMYCRYPT) - for (int i = 0; i < len; i++) { + for (unsigned int i = 0; i < len; i++) { buffer[i] = G_monero_vstate.io_buffer[G_monero_vstate.io_offset + i] ^ 0x55; } #elif defined(IONOCRYPT) memcpy(buffer, G_monero_vstate.io_buffer + G_monero_vstate.io_offset, len); #else // IOCRYPT - cx_aes(&G_monero_vstate.spk, CX_DECRYPT | CX_CHAIN_CBC | CX_LAST | CX_PAD_NONE, - G_monero_vstate.io_buffer + G_monero_vstate.io_offset, len, buffer, len); + error = cx_aes_no_throw( + &G_monero_vstate.spk, CX_DECRYPT | CX_CHAIN_CBC | CX_LAST | CX_PAD_NONE, + G_monero_vstate.io_buffer + G_monero_vstate.io_offset, len, buffer, &len); #endif } G_monero_vstate.io_offset += len; @@ -279,22 +284,27 @@ int monero_io_fetch_decrypt(unsigned char* buffer, int len, int type) { if (buffer) { switch (type) { case TYPE_SCALAR: - monero_check_scalar_range_1N(buffer); - break; + return monero_check_scalar_range_1N(buffer, len); case TYPE_AMOUNT_KEY: case TYPE_DERIVATION: case TYPE_ALPHA: - monero_check_scalar_not_null(buffer); - break; + return monero_check_scalar_not_null(buffer); default: - THROW(SW_SECURITY_INTERNAL); + return SW_SECURITY_INTERNAL; } } - return len; + return error; } -int monero_io_fetch_decrypt_key(unsigned char* buffer) { +int monero_io_fetch_decrypt_key(unsigned char* buffer, size_t buffer_size) { unsigned char* k; + int error = 0; + if (!buffer) { + return SW_WRONG_DATA; + } + if (buffer_size > 32) { + return SW_WRONG_DATA_RANGE; + } monero_io_assert_available(32); k = G_monero_vstate.io_buffer + G_monero_vstate.io_offset; @@ -303,13 +313,16 @@ int monero_io_fetch_decrypt_key(unsigned char* buffer) { G_monero_vstate.io_offset += 32; if (G_monero_vstate.tx_in_progress) { monero_io_assert_available(32); - monero_io_verify_hmac_for(C_FAKE_SEC_VIEW_KEY, 32, - G_monero_vstate.io_buffer + G_monero_vstate.io_offset, - TYPE_SCALAR); + error = monero_io_verify_hmac_for(C_FAKE_SEC_VIEW_KEY, 32, + G_monero_vstate.io_buffer + G_monero_vstate.io_offset, + TYPE_SCALAR); + if (error) { + return error; + } G_monero_vstate.io_offset += 32; } memcpy(buffer, G_monero_vstate.a, 32); - return 32; + return 0; } // spend? else if (memcmp(k, C_FAKE_SEC_SPEND_KEY, 32) == 0) { @@ -319,17 +332,20 @@ int monero_io_fetch_decrypt_key(unsigned char* buffer) { // case INS_GET_SUBADDRESS_SPEND_PUBLIC_KEY: break; default: - THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; } G_monero_vstate.io_offset += 32; if (G_monero_vstate.tx_in_progress) { monero_io_assert_available(32); - monero_io_verify_hmac_for(C_FAKE_SEC_SPEND_KEY, 32, - G_monero_vstate.io_buffer + G_monero_vstate.io_offset, - TYPE_SCALAR); + error = monero_io_verify_hmac_for(C_FAKE_SEC_SPEND_KEY, 32, + G_monero_vstate.io_buffer + G_monero_vstate.io_offset, + TYPE_SCALAR); + if (error) { + return error; + } } memcpy(buffer, G_monero_vstate.b, 32); - return 32; + return 0; } // else else { @@ -337,45 +353,35 @@ int monero_io_fetch_decrypt_key(unsigned char* buffer) { } } -uint64_t monero_io_fetch_varint() { - uint64_t v64; - G_monero_vstate.io_offset += - monero_decode_varint(G_monero_vstate.io_buffer + G_monero_vstate.io_offset, - MIN(8, G_monero_vstate.io_length - G_monero_vstate.io_offset), &v64); - return v64; +int monero_io_fetch_varint(uint64_t* out_v64) { + if (!out_v64) { + return SW_WRONG_DATA; + } + unsigned int out_len = 0; + unsigned int error = monero_decode_varint( + G_monero_vstate.io_buffer + G_monero_vstate.io_offset, + MIN(8, G_monero_vstate.io_length - G_monero_vstate.io_offset), out_v64, &out_len); + G_monero_vstate.io_offset += out_len; + return error; } -unsigned int monero_io_fetch_u32() { +unsigned int monero_io_fetch_u32(void) { unsigned int v32; monero_io_assert_available(4); - v32 = ((G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 0] << 24) | - (G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 1] << 16) | - (G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 2] << 8) | - (G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 3] << 0)); + v32 = read_u32_be(G_monero_vstate.io_buffer, G_monero_vstate.io_offset); G_monero_vstate.io_offset += 4; return v32; } -unsigned int monero_io_fetch_u24() { - unsigned int v24; - monero_io_assert_available(3); - v24 = ((G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 0] << 16) | - (G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 1] << 8) | - (G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 2] << 0)); - G_monero_vstate.io_offset += 3; - return v24; -} - -unsigned int monero_io_fetch_u16() { +unsigned int monero_io_fetch_u16(void) { unsigned int v16; monero_io_assert_available(2); - v16 = ((G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 0] << 8) | - (G_monero_vstate.io_buffer[G_monero_vstate.io_offset + 1] << 0)); + v16 = read_u16_be(G_monero_vstate.io_buffer, G_monero_vstate.io_offset); G_monero_vstate.io_offset += 2; return v16; } -unsigned int monero_io_fetch_u8() { +unsigned int monero_io_fetch_u8(void) { unsigned int v8; monero_io_assert_available(1); v8 = G_monero_vstate.io_buffer[G_monero_vstate.io_offset]; @@ -436,7 +442,7 @@ int monero_io_do(unsigned int io_flags) { else { G_monero_vstate.io_offset = 0; if (G_monero_vstate.io_length > MAX_OUT) { - THROW(SW_IO_FULL); + return SW_IO_FULL; } memcpy(G_io_apdu_buffer, G_monero_vstate.io_buffer + G_monero_vstate.io_offset, G_monero_vstate.io_length); @@ -456,7 +462,6 @@ int monero_io_do(unsigned int io_flags) { G_monero_vstate.io_ins = G_io_apdu_buffer[1]; G_monero_vstate.io_p1 = G_io_apdu_buffer[2]; G_monero_vstate.io_p2 = G_io_apdu_buffer[3]; - G_monero_vstate.io_lc = 0; G_monero_vstate.io_le = 0; G_monero_vstate.io_lc = G_io_apdu_buffer[4]; memcpy(G_monero_vstate.io_buffer, G_io_apdu_buffer + 5, G_monero_vstate.io_lc); diff --git a/src/monero_key.c b/src/monero_key.c index a24df6f..2170e05 100644 --- a/src/monero_key.c +++ b/src/monero_key.c @@ -85,13 +85,13 @@ void monero_clear_words(void) { * word_list * len : word_list length */ -static void monero_set_word(unsigned int n, unsigned int idx, unsigned int w_start, - unsigned char *word_list, int len) { +static int monero_set_word(unsigned int n, unsigned int idx, unsigned int w_start, + unsigned char *word_list, int len) { while (w_start < idx) { len -= 1 + word_list[0]; if (len < 0) { monero_clear_words(); - THROW(SW_WRONG_DATA + 1); + return SW_WRONG_DATA + 1; } word_list += 1 + word_list[0]; w_start++; @@ -99,11 +99,12 @@ static void monero_set_word(unsigned int n, unsigned int idx, unsigned int w_sta if ((w_start != idx) || (word_list[0] > (len - 1)) || (word_list[0] > 19)) { monero_clear_words(); - THROW(SW_WRONG_DATA + 2); + return SW_WRONG_DATA + 2; } len = word_list[0]; word_list++; monero_nvm_write((void *)N_monero_pstate->words[n], word_list, len); + return 0; } #define word_list_length 1626 @@ -112,6 +113,7 @@ static void monero_set_word(unsigned int n, unsigned int idx, unsigned int w_sta int monero_apdu_manage_seedwords(void) { unsigned int w_start, w_end; unsigned short wc[4]; + int err = 0; switch (G_monero_vstate.io_p1) { // SETUP @@ -119,7 +121,7 @@ int monero_apdu_manage_seedwords(void) { w_start = monero_io_fetch_u32(); w_end = w_start + monero_io_fetch_u32(); if ((w_start >= word_list_length) || (w_end > word_list_length) || (w_start > w_end)) { - THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; } for (int i = 0; i < 8; i++) { unsigned int val = (seed[i * 4 + 0] << 0) | (seed[i * 4 + 1] << 8) | @@ -130,9 +132,12 @@ int monero_apdu_manage_seedwords(void) { for (int wi = 0; wi < 3; wi++) { if ((wc[wi] >= w_start) && (wc[wi] < w_end)) { - monero_set_word(i * 3 + wi, wc[wi], w_start, - G_monero_vstate.io_buffer + G_monero_vstate.io_offset, - MONERO_IO_BUFFER_LENGTH - G_monero_vstate.io_offset); + err = monero_set_word(i * 3 + wi, wc[wi], w_start, + G_monero_vstate.io_buffer + G_monero_vstate.io_offset, + MONERO_IO_BUFFER_LENGTH - G_monero_vstate.io_offset); + if (err) { + return err; + } } } } @@ -150,7 +155,6 @@ int monero_apdu_manage_seedwords(void) { monero_nvm_write((void *)N_monero_pstate->words[24], (void *)N_monero_pstate->words[w_start], WORDS_MAX_LENGTH); -#ifdef HAVE_UX_FLOW // transform to list ready to display unsigned char word[21]; w_start = 0; @@ -162,7 +166,6 @@ int monero_apdu_manage_seedwords(void) { monero_nvm_write((char *)N_monero_pstate->words_list + w_start, word, w_end); w_start += w_end; } -#endif } break; @@ -199,6 +202,7 @@ int monero_apdu_display_address() { unsigned char payment_id[8]; unsigned char C[32]; unsigned char D[32]; + int error = 0; // fetch monero_io_fetch(index, 8); @@ -208,12 +212,15 @@ int monero_apdu_display_address() { major = (index[0] << 0) | (index[1] << 8) | (index[2] << 16) | (index[3] << 24); minor = (index[4] << 0) | (index[5] << 8) | (index[6] << 16) | (index[7] << 24); if ((minor | major) && (G_monero_vstate.io_p1 == 1)) { - THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; } // retrieve pub keys if (minor | major) { - monero_get_subaddress(C, D, index); + error = monero_get_subaddress(C, D, index, sizeof(C), sizeof(D), sizeof(index)); + if (error) { + return error; + } } else { memcpy(C, G_monero_vstate.A, 32); memcpy(D, G_monero_vstate.B, 32); @@ -233,9 +240,9 @@ int monero_apdu_display_address() { } } - ui_menu_any_pubaddr_display(0, C, D, (minor | major) ? 1 : 0, - (G_monero_vstate.io_p1 == 1) ? payment_id : NULL); - return 0; + error = ui_menu_any_pubaddr_display(0, C, D, (minor | major) ? 1 : 0, + (G_monero_vstate.io_p1 == 1) ? payment_id : NULL); + return error; } /* ----------------------------------------------------------------------- */ @@ -256,19 +263,22 @@ int monero_apdu_put_key() { unsigned char raw[32]; unsigned char pub[32]; unsigned char sec[32]; + int err; // option + priv/pub view key + priv/pub spend key + base58 address if (G_monero_vstate.io_length != (1 + 32 * 2 + 32 * 2 + 95)) { - THROW(SW_WRONG_LENGTH); return SW_WRONG_LENGTH; } // view key monero_io_fetch(sec, 32); monero_io_fetch(pub, 32); - monero_ecmul_G(raw, sec); + err = monero_ecmul_G(raw, sec, sizeof(raw), sizeof(sec)); + if (err) { + return err; + } + if (memcmp(pub, raw, 32) != 0) { - THROW(SW_WRONG_DATA); return SW_WRONG_DATA; } nvm_write((void *)N_monero_pstate->a, sec, 32); @@ -276,9 +286,12 @@ int monero_apdu_put_key() { // spend key monero_io_fetch(sec, 32); monero_io_fetch(pub, 32); - monero_ecmul_G(raw, sec); + err = monero_ecmul_G(raw, sec, sizeof(raw), sizeof(sec)); + if (err) { + return err; + } + if (memcmp(pub, raw, 32) != 0) { - THROW(SW_WRONG_DATA); return SW_WRONG_DATA; } nvm_write((void *)N_monero_pstate->b, sec, 32); @@ -305,8 +318,12 @@ int monero_apdu_get_key() { // spend key monero_io_insert(G_monero_vstate.B, 32); // public base address - monero_base58_public_key((char *)G_monero_vstate.io_buffer + G_monero_vstate.io_offset, - G_monero_vstate.A, G_monero_vstate.B, 0, NULL); + int error = monero_base58_public_key( + (char *)G_monero_vstate.io_buffer + G_monero_vstate.io_offset, G_monero_vstate.A, + G_monero_vstate.B, 0, NULL); + if (error) { + return 0; + } monero_io_inserted(95); break; @@ -325,7 +342,7 @@ int monero_apdu_get_key() { // get info case 3: { unsigned int path[5]; - unsigned char seed[32]; + unsigned char seed[64]; // m/44'/128'/0'/0/0 path[0] = 0x8000002C; @@ -334,7 +351,9 @@ int monero_apdu_get_key() { path[3] = 0x00000000; path[4] = 0x00000000; - os_perso_derive_node_bip32(CX_CURVE_SECP256K1, path, 5, seed, G_monero_vstate.a); + if (os_derive_bip32_no_throw(CX_CURVE_SECP256K1, path, 5, seed, G_monero_vstate.a)) { + return SW_WRONG_DATA; + } monero_io_insert(seed, 32); monero_io_insert(G_monero_vstate.b, 32); @@ -351,7 +370,7 @@ int monero_apdu_get_key() { #endif default: - THROW(SW_WRONG_P1P2); + return SW_WRONG_P1P2; } return SW_OK; } @@ -364,12 +383,20 @@ int monero_apdu_verify_key() { unsigned char priv[32]; unsigned char computed_pub[32]; unsigned int verified = 0; + int err = 0; - monero_io_fetch_decrypt_key(priv); + err = monero_io_fetch_decrypt_key(priv, sizeof(priv)); + if (err) { + return err; + } monero_io_fetch(pub, 32); switch (G_monero_vstate.io_p1) { case 0: - monero_secret_key_to_public_key(computed_pub, priv); + err = monero_secret_key_to_public_key(computed_pub, priv, sizeof(computed_pub), + sizeof(priv)); + if (err) { + return err; + } break; case 1: memcpy(computed_pub, G_monero_vstate.A, 32); @@ -378,7 +405,7 @@ int monero_apdu_verify_key() { memcpy(computed_pub, G_monero_vstate.B, 32); break; default: - THROW(SW_WRONG_P1P2); + return SW_WRONG_P1P2; } if (memcmp(computed_pub, pub, 32) == 0) { verified = 1; @@ -401,7 +428,10 @@ int monero_apdu_get_chacha8_prekey(/*char *prekey*/) { memcpy(abt, G_monero_vstate.a, 32); memcpy(abt + 32, G_monero_vstate.b, 32); abt[64] = CHACHA8_KEY_TAIL; - monero_keccak_F(abt, 65, pre); + int error = monero_keccak_F(abt, 65, pre); + if (error) { + return error; + } monero_io_insert((unsigned char *)G_monero_vstate.keccakF.acc, 200); return SW_OK; } @@ -414,9 +444,16 @@ int monero_apdu_sc_add(/*unsigned char *r, unsigned char *s1, unsigned char *s2* unsigned char s1[32]; unsigned char s2[32]; unsigned char r[32]; + int err; // fetch - monero_io_fetch_decrypt(s1, 32, TYPE_SCALAR); - monero_io_fetch_decrypt(s2, 32, TYPE_SCALAR); + err = monero_io_fetch_decrypt(s1, 32, TYPE_SCALAR); + if (err) { + return err; + } + err = monero_io_fetch_decrypt(s2, 32, TYPE_SCALAR); + if (err) { + return err; + } monero_io_discard(0); if (G_monero_vstate.tx_in_progress) { // During a transaction, only "last_derive_secret_key+last_get_subaddress_secret_key" @@ -426,10 +463,13 @@ int monero_apdu_sc_add(/*unsigned char *r, unsigned char *s1, unsigned char *s2* // hwdev.sc_secret_add(scalar_step2, scalar_step1,subaddr_sk); if ((memcmp(s1, G_monero_vstate.last_derive_secret_key, 32) != 0) || (memcmp(s2, G_monero_vstate.last_get_subaddress_secret_key, 32) != 0)) { - monero_lock_and_throw(SW_WRONG_DATA); + return SW_WRONG_DATA; } } - monero_addm(r, s1, s2); + err = monero_addm(r, s1, s2, sizeof(r), sizeof(s1), sizeof(s2)); + if (err) { + return err; + } monero_io_insert_encrypt(r, 32, TYPE_SCALAR); return SW_OK; } @@ -441,12 +481,20 @@ int monero_apdu_scal_mul_key(/*const rct::key &pub, const rct::key &sec, rct::ke unsigned char pub[32]; unsigned char sec[32]; unsigned char r[32]; + int err = 0; + // fetch monero_io_fetch(pub, 32); - monero_io_fetch_decrypt_key(sec); + err = monero_io_fetch_decrypt_key(sec, sizeof(sec)); + if (err) { + return err; + } monero_io_discard(0); - monero_ecmul_k(r, pub, sec); + err = monero_ecmul_k(r, pub, sec, sizeof(r), sizeof(pub), sizeof(sec)); + if (err) { + return err; + } monero_io_insert(r, 32); return SW_OK; } @@ -457,11 +505,19 @@ int monero_apdu_scal_mul_key(/*const rct::key &pub, const rct::key &sec, rct::ke int monero_apdu_scal_mul_base(/*const rct::key &sec, rct::key mulkey*/) { unsigned char sec[32]; unsigned char r[32]; + int err; // fetch - monero_io_fetch_decrypt(sec, 32, TYPE_SCALAR); + err = monero_io_fetch_decrypt(sec, 32, TYPE_SCALAR); + if (err) { + return err; + } monero_io_discard(0); - monero_ecmul_G(r, sec); + err = monero_ecmul_G(r, sec, sizeof(r), sizeof(sec)); + if (err) { + return err; + } + monero_io_insert(r, 32); return SW_OK; } @@ -474,7 +530,10 @@ int monero_apdu_generate_keypair(/*crypto::public_key &pub, crypto::secret_key & unsigned char pub[32]; monero_io_discard(0); - monero_generate_keypair(pub, sec); + int error = monero_generate_keypair(pub, sec, sizeof(pub), sizeof(sec)); + if (error) { + return error; + } monero_io_insert(pub, 32); monero_io_insert_encrypt(sec, 32, TYPE_SCALAR); return SW_OK; @@ -488,10 +547,17 @@ int monero_apdu_secret_key_to_public_key( unsigned char sec[32]; unsigned char pub[32]; // fetch - monero_io_fetch_decrypt(sec, 32, TYPE_SCALAR); + int err = monero_io_fetch_decrypt(sec, 32, TYPE_SCALAR); + if (err) { + return err; + } monero_io_discard(0); // pub - monero_ecmul_G(pub, sec); + err = monero_ecmul_G(pub, sec, sizeof(pub), sizeof(sec)); + if (err) { + return err; + } + // pub key monero_io_insert(pub, 32); return SW_OK; @@ -504,14 +570,22 @@ int monero_apdu_generate_key_derivation(/*const crypto::public_key &pub, const c unsigned char pub[32]; unsigned char sec[32]; unsigned char drv[32]; + int err = 0; + // fetch monero_io_fetch(pub, 32); - monero_io_fetch_decrypt_key(sec); + err = monero_io_fetch_decrypt_key(sec, sizeof(sec)); + if (err) { + return err; + } monero_io_discard(0); // Derive and keep - monero_generate_key_derivation(drv, pub, sec); + err = monero_generate_key_derivation(drv, pub, sec, sizeof(drv), sizeof(pub), sizeof(sec)); + if (err) { + return err; + } monero_io_insert_encrypt(drv, 32, TYPE_DERIVATION); return SW_OK; @@ -527,12 +601,19 @@ int monero_apdu_derivation_to_scalar( unsigned char res[32]; // fetch - monero_io_fetch_decrypt(derivation, 32, TYPE_DERIVATION); + int err = monero_io_fetch_decrypt(derivation, 32, TYPE_DERIVATION); + if (err) { + return err; + } output_index = monero_io_fetch_u32(); monero_io_discard(0); // pub - monero_derivation_to_scalar(res, derivation, output_index); + err = + monero_derivation_to_scalar(res, derivation, output_index, sizeof(res), sizeof(derivation)); + if (err) { + return err; + } // pub key monero_io_insert_encrypt(res, 32, TYPE_SCALAR); @@ -549,13 +630,20 @@ int monero_apdu_derive_public_key(/*const crypto::key_derivation &derivation, co unsigned char drvpub[32]; // fetch - monero_io_fetch_decrypt(derivation, 32, TYPE_DERIVATION); + int err = monero_io_fetch_decrypt(derivation, 32, TYPE_DERIVATION); + if (err) { + return err; + } output_index = monero_io_fetch_u32(); monero_io_fetch(pub, 32); monero_io_discard(0); // pub - monero_derive_public_key(drvpub, derivation, output_index, pub); + int error = monero_derive_public_key(drvpub, derivation, output_index, pub, sizeof(drvpub), + sizeof(derivation), sizeof(pub)); + if (error) { + return error; + } // pub key monero_io_insert(drvpub, 32); @@ -570,15 +658,26 @@ int monero_apdu_derive_secret_key(/*const crypto::key_derivation &derivation, co unsigned int output_index; unsigned char sec[32]; unsigned char drvsec[32]; + int err = 0; // fetch - monero_io_fetch_decrypt(derivation, 32, TYPE_DERIVATION); + err = monero_io_fetch_decrypt(derivation, 32, TYPE_DERIVATION); + if (err) { + return err; + } output_index = monero_io_fetch_u32(); - monero_io_fetch_decrypt_key(sec); + err = monero_io_fetch_decrypt_key(sec, sizeof(sec)); + if (err) { + return err; + } monero_io_discard(0); // pub - monero_derive_secret_key(drvsec, derivation, output_index, sec); + err = monero_derive_secret_key(drvsec, derivation, output_index, sec, sizeof(drvsec), + sizeof(derivation), sizeof(sec)); + if (err) { + return err; + } // sec key memcpy(G_monero_vstate.last_derive_secret_key, drvsec, 32); @@ -597,11 +696,17 @@ int monero_apdu_generate_key_image( // fetch monero_io_fetch(pub, 32); - monero_io_fetch_decrypt(sec, 32, TYPE_SCALAR); + int err = monero_io_fetch_decrypt(sec, 32, TYPE_SCALAR); + if (err) { + return err; + } monero_io_discard(0); // pub - monero_generate_key_image(image, pub, sec); + err = monero_generate_key_image(image, pub, sec, sizeof(image), sizeof(sec)); + if (err) { + return err; + } // pub key monero_io_insert(image, 32); @@ -616,14 +721,21 @@ int monero_apdu_derive_view_tag( unsigned char derivation[32]; unsigned int output_index; unsigned char res[1]; + int err; // fetch - monero_io_fetch_decrypt(derivation, 32, TYPE_DERIVATION); + err = monero_io_fetch_decrypt(derivation, 32, TYPE_DERIVATION); + if (err) { + return err; + } output_index = monero_io_fetch_u32(); monero_io_discard(0); // derive and keep - monero_derive_view_tag(res, derivation, output_index); + err = monero_derive_view_tag(res, derivation, output_index); + if (err) { + return err; + } monero_io_insert(res, 1); return SW_OK; @@ -640,12 +752,19 @@ int monero_apdu_derive_subaddress_public_key(/*const crypto::public_key &pub, co // fetch monero_io_fetch(pub, 32); - monero_io_fetch_decrypt(derivation, 32, TYPE_DERIVATION); + int err = monero_io_fetch_decrypt(derivation, 32, TYPE_DERIVATION); + if (err) { + return err; + } output_index = monero_io_fetch_u32(); monero_io_discard(0); // pub - monero_derive_subaddress_public_key(sub_pub, pub, derivation, output_index); + err = monero_derive_subaddress_public_key(sub_pub, pub, derivation, output_index, + sizeof(sub_pub), sizeof(pub), sizeof(derivation)); + if (err) { + return err; + } // pub key monero_io_insert(sub_pub, 32); return SW_OK; @@ -665,7 +784,10 @@ int monero_apdu_get_subaddress( monero_io_discard(0); // pub - monero_get_subaddress(C, D, index); + int error = monero_get_subaddress(C, D, index, sizeof(C), sizeof(D), sizeof(index)); + if (error) { + return error; + } // pub key monero_io_insert(C, 32); @@ -686,7 +808,10 @@ int monero_apdu_get_subaddress_spend_public_key( monero_io_discard(1); // pub - monero_get_subaddress_spend_public_key(D, index); + int error = monero_get_subaddress_spend_public_key(D, index, sizeof(D), sizeof(index)); + if (error) { + return error; + } // pub key monero_io_insert(D, 32); @@ -701,12 +826,20 @@ int monero_apdu_get_subaddress_secret_key(/*const crypto::secret_key& sec, const unsigned char sec[32]; unsigned char index[8]; unsigned char sub_sec[32]; + int err = 0; - monero_io_fetch_decrypt_key(sec); + err = monero_io_fetch_decrypt_key(sec, sizeof(sec)); + if (err) { + return err; + } monero_io_fetch(index, 8); monero_io_discard(0); - monero_get_subaddress_secret_key(sub_sec, sec, index); + err = monero_get_subaddress_secret_key(sub_sec, sec, index, sizeof(sub_sec), sizeof(sec), + sizeof(index)); + if (err) { + return err; + } memcpy(G_monero_vstate.last_get_subaddress_secret_key, sub_sec, 32); monero_io_insert_encrypt(sub_sec, 32, TYPE_SCALAR); @@ -736,41 +869,65 @@ int monero_apu_generate_txout_keys(/*size_t tx_version, crypto::secret_key tx_se unsigned char view_tag[1]; // TMP unsigned char derivation[32]; + int err = 0; monero_io_fetch_u32(); // skip tx_version - monero_io_fetch_decrypt_key(tx_key); + err = monero_io_fetch_decrypt_key(tx_key, sizeof(tx_key)); + if (err) { + return err; + } txkey_pub = G_monero_vstate.io_buffer + G_monero_vstate.io_offset; - monero_io_fetch(NULL, 32); + monero_io_skip(32); Aout = G_monero_vstate.io_buffer + G_monero_vstate.io_offset; - monero_io_fetch(NULL, 32); + monero_io_skip(32); Bout = G_monero_vstate.io_buffer + G_monero_vstate.io_offset; - monero_io_fetch(NULL, 32); + monero_io_skip(32); output_index = monero_io_fetch_u32(); is_change = monero_io_fetch_u8(); is_subaddress = monero_io_fetch_u8(); need_additional_txkeys = monero_io_fetch_u8(); if (need_additional_txkeys) { - monero_io_fetch_decrypt_key(additional_txkey_sec); + err = monero_io_fetch_decrypt_key(additional_txkey_sec, sizeof(additional_txkey_sec)); + if (err) { + return err; + } } else { - monero_io_fetch(NULL, 32); + monero_io_skip(32); } use_view_tags = monero_io_fetch_u8(); // update outkeys hash control if (G_monero_vstate.tx_sig_mode == TRANSACTION_CREATE_REAL) { if (G_monero_vstate.io_protocol_version >= 2) { - monero_sha256_outkeys_update(Aout, 32); - monero_sha256_outkeys_update(Bout, 32); - monero_sha256_outkeys_update(&is_change, 1); + err = monero_sha256_outkeys_update(Aout, 32); + if (err) { + return err; + } + err = monero_sha256_outkeys_update(Bout, 32); + if (err) { + return err; + } + err = monero_sha256_outkeys_update(&is_change, 1); + if (err) { + return err; + } } } // make additional tx pubkey if necessary if (need_additional_txkeys) { if (is_subaddress) { - monero_ecmul_k(additional_txkey_pub, Bout, additional_txkey_sec); + err = monero_ecmul_k(additional_txkey_pub, Bout, additional_txkey_sec, + sizeof(additional_txkey_pub), 32, sizeof(additional_txkey_sec)); + if (err) { + return err; + } } else { - monero_ecmul_G(additional_txkey_pub, additional_txkey_sec); + err = monero_ecmul_G(additional_txkey_pub, additional_txkey_sec, + sizeof(additional_txkey_pub), sizeof(additional_txkey_sec)); + if (err) { + return err; + } } } else { memset(additional_txkey_pub, 0, 32); @@ -778,27 +935,49 @@ int monero_apu_generate_txout_keys(/*size_t tx_version, crypto::secret_key tx_se // derivation if (is_change) { - monero_generate_key_derivation(derivation, txkey_pub, G_monero_vstate.a); + err = monero_generate_key_derivation(derivation, txkey_pub, G_monero_vstate.a, + sizeof(derivation), 32, sizeof(G_monero_vstate.a)); + if (err) { + return err; + } } else { - monero_generate_key_derivation( + err = monero_generate_key_derivation( derivation, Aout, - (is_subaddress && need_additional_txkeys) ? additional_txkey_sec : tx_key); + (is_subaddress && need_additional_txkeys) ? additional_txkey_sec : tx_key, + sizeof(derivation), 32, 32); + if (err) { + return err; + } } // compute amount key AKout (scalar1), version is always greater than 1 - monero_derivation_to_scalar(amount_key, derivation, output_index); + err = monero_derivation_to_scalar(amount_key, derivation, output_index, sizeof(amount_key), + sizeof(derivation)); + if (err) { + return err; + } if (G_monero_vstate.tx_sig_mode == TRANSACTION_CREATE_REAL) { if (G_monero_vstate.io_protocol_version >= 2) { - monero_sha256_outkeys_update(amount_key, 32); + err = monero_sha256_outkeys_update(amount_key, 32); + if (err) { + return err; + } } } // compute ephemeral output key - monero_derive_public_key(out_eph_public_key, derivation, output_index, Bout); + err = monero_derive_public_key(out_eph_public_key, derivation, output_index, Bout, + sizeof(out_eph_public_key), sizeof(derivation), 32); + if (err) { + return err; + } // compute view tag if (use_view_tags) { - monero_derive_view_tag(view_tag, derivation, output_index); + err = monero_derive_view_tag(view_tag, derivation, output_index); + if (err) { + return err; + } } // send all diff --git a/src/monero_main.c b/src/monero_main.c index 8d4bc94..9a26165 100644 --- a/src/monero_main.c +++ b/src/monero_main.c @@ -27,218 +27,50 @@ #include "os_io_seproxyhal.h" #include "string.h" #include "glyphs.h" +#include "io.h" -#ifdef HAVE_UX_FLOW #include "ux.h" -#endif /* ----------------------------------------------------------------------- */ /* --- Application Entry --- */ /* ----------------------------------------------------------------------- */ +void __attribute__((noreturn)) app_exit(void); -void monero_main(void) { - unsigned int io_flags, cont; - io_flags = 0; - cont = 1; - while (cont) { - volatile unsigned short sw = 0; - BEGIN_TRY { - TRY { - monero_io_do(io_flags); - sw = monero_dispatch(); - } - CATCH(EXCEPTION_IO_RESET) { - sw = 0; - cont = 0; - monero_io_discard(1); - } - CATCH_OTHER(e) { - monero_reset_tx(1); - if (((e & 0xF000) == 0x9000) || ((e & 0xFF00) == 0x6400)) { - sw = e; - } else { - monero_io_discard(1); - if ((e & 0xFFFF0000) || ((e & 0xF000) != 0x6000)) { - monero_io_insert_u32(e); - sw = 0x6f42; - } else { - sw = e; - } - } - } - FINALLY { - if (sw) { - monero_io_insert_u16(sw); - io_flags = 0; - } else { - io_flags = IO_ASYNCH_REPLY; - } - } - } - END_TRY; - } +void __attribute__((noreturn)) send_error_and_kill_app(int sw) { + monero_io_discard(1); + monero_io_insert_u16(sw); + monero_io_do(IO_RETURN_AFTER_TX); + memset(&G_monero_vstate, 0, sizeof(G_monero_vstate)); + app_exit(); } -unsigned char io_event(unsigned char channel __attribute__((unused))) { - unsigned int s_before; - unsigned int s_after; - - s_before = os_global_pin_is_validated(); - - // 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]) { - case SEPROXYHAL_TAG_FINGER_EVENT: - UX_FINGER_EVENT(G_io_seproxyhal_spi_buffer); - break; - // power off if long push, else pass to the application callback if any - case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT: // for Nano S -#ifdef HAVE_BAGL - UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer); -#endif - break; - - // other events are propagated to the UX just in case - default: - UX_DEFAULT_EVENT(); - break; - - case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT: -#ifdef HAVE_BAGL - UX_DISPLAYED_EVENT({}); -#endif // HAVE_BAGL -#ifdef HAVE_NBGL - UX_DEFAULT_EVENT(); -#endif // HAVE_NBGL - break; - case SEPROXYHAL_TAG_TICKER_EVENT: - UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, { -#ifdef HAVE_BAGL - // only allow display when not locked of overlayed by an OS UX. - if (UX_ALLOWED) { - UX_REDISPLAY(); - } -#endif - }); - break; - } +void app_main(void) { + unsigned int io_flags; + unsigned int error; + io_flags = 0; - // close the event if not done previously (by a display or whatever) - if (!io_seproxyhal_spi_is_status_sent()) { - io_seproxyhal_general_status(); + error = monero_init(); + if (error) { + memset(&G_monero_vstate, 0, sizeof(G_monero_vstate)); + app_exit(); } - s_after = os_global_pin_is_validated(); + // set up initial screen + ui_init(); - if (s_before != s_after) { - if (s_after == PIN_VERIFIED) { - monero_init_private_key(); + for (;;) { + volatile unsigned short sw = 0; + monero_io_do(io_flags); + sw = monero_dispatch(); + if (sw == 0) { + io_flags = IO_ASYNCH_REPLY; + } else if (sw == SW_OK) { + monero_io_insert_u16(sw); + io_flags = 0; } else { - ; // do nothing, allowing TX parsing in lock mode - // monero_wipe_private_key(); - } - } - - // command has been processed, DO NOT reset the current APDU transport - return 1; -} - -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; - } - return 0; -} - -void app_exit(void) { - BEGIN_TRY_L(exit) { - TRY_L(exit) { - os_sched_exit(-1); - } - FINALLY_L(exit) { + send_error_and_kill_app(sw); } } - END_TRY_L(exit); -} - -/* -------------------------------------------------------------- */ - -__attribute__((section(".boot"))) int main(void) { - // exit critical section - __asm volatile("cpsie i"); - unsigned int cont = 1; - - // ensure exception will work as planned - os_boot(); - while (cont) { - // Initialize the UX system - UX_INIT(); - - BEGIN_TRY { - TRY { - // start communication with MCU - io_seproxyhal_init(); - - USB_power(0); - USB_power(1); - -#ifdef HAVE_USB_CLASS_CCID - io_usb_ccid_set_card_inserted(1); -#endif - -#ifdef HAVE_BLE - G_io_app.plane_mode = os_setting_get(OS_SETTING_PLANEMODE, NULL, 0); - BLE_power(0, NULL); - BLE_power(1, NULL); -#endif // HAVE_BLE - - monero_init(); - - // set up initial screen - ui_init(); - - // start the application - // the first exchange will: - // - display the initial screen - // - send the ATR - // - receive the first command - monero_main(); - } - CATCH(EXCEPTION_IO_RESET) { - // reset IO and UX - CLOSE_TRY; - ; - } - CATCH_OTHER(e) { - cont = 0; - CLOSE_TRY; - } - FINALLY { - } - } - END_TRY; - } - app_exit(); } #endif diff --git a/src/monero_mlsag.c b/src/monero_mlsag.c index 7c255d5..d9eecec 100644 --- a/src/monero_mlsag.c +++ b/src/monero_mlsag.c @@ -31,10 +31,11 @@ int monero_apdu_mlsag_prepare() { unsigned char xin[32]; unsigned char alpha[32]; unsigned char mul[32]; + int err; G_monero_vstate.tx_sign_cnt++; if (G_monero_vstate.tx_sign_cnt == 0) { - monero_lock_and_throw(SW_SECURITY_MAX_SIGNATURE_REACHED); + return SW_SECURITY_MAX_SIGNATURE_REACHED; } if (G_monero_vstate.io_length > 1) { @@ -42,7 +43,10 @@ int monero_apdu_mlsag_prepare() { if (G_monero_vstate.options & 0x40) { monero_io_fetch(xin, 32); } else { - monero_io_fetch_decrypt(xin, 32, TYPE_SCALAR); + err = monero_io_fetch_decrypt(xin, 32, TYPE_SCALAR); + if (err) { + return err; + } } options = 1; } else { @@ -52,20 +56,38 @@ int monero_apdu_mlsag_prepare() { monero_io_discard(1); // ai - monero_rng_mod_order(alpha); - monero_reduce(alpha, alpha); + err = monero_rng_mod_order(alpha, sizeof(alpha)); + if (err) { + return err; + } + + err = monero_reduce(alpha, alpha, sizeof(alpha), sizeof(alpha)); + if (err) { + return err; + } + monero_io_insert_encrypt(alpha, 32, TYPE_ALPHA); // ai.G - monero_ecmul_G(mul, alpha); + err = monero_ecmul_G(mul, alpha, sizeof(mul), sizeof(alpha)); + if (err) { + return err; + } + monero_io_insert(mul, 32); if (options) { // ai.Hi - monero_ecmul_k(mul, Hi, alpha); + err = monero_ecmul_k(mul, Hi, alpha, sizeof(mul), sizeof(Hi), sizeof(alpha)); + if (err) { + return err; + } monero_io_insert(mul, 32); // IIi = xin.Hi - monero_ecmul_k(mul, Hi, xin); + err = monero_ecmul_k(mul, Hi, xin, sizeof(mul), sizeof(Hi), sizeof(xin)); + if (err) { + return err; + } monero_io_insert(mul, 32); } return SW_OK; @@ -77,18 +99,32 @@ int monero_apdu_mlsag_prepare() { int monero_apdu_mlsag_hash() { unsigned char msg[32]; unsigned char c[32]; + int err; if (G_monero_vstate.io_p2 == 1) { - monero_keccak_init_H(); + if (monero_keccak_init_H()) { + return SW_WRONG_DATA; + } memcpy(msg, G_monero_vstate.mlsagH, 32); } else { monero_io_fetch(msg, 32); } monero_io_discard(1); - monero_keccak_update_H(msg, 32); + err = monero_keccak_update_H(msg, 32); + if (err) { + return err; + } + if ((G_monero_vstate.options & 0x80) == 0) { - monero_keccak_final_H(c); - monero_reduce(c, c); + err = monero_keccak_final_H(c); + if (err) { + return err; + } + + err = monero_reduce(c, c, sizeof(c), sizeof(c)); + if (err) { + return err; + } monero_io_insert(c, 32); memcpy(G_monero_vstate.c, c, 32); } @@ -103,29 +139,53 @@ int monero_apdu_mlsag_sign() { unsigned char alpha[32]; unsigned char ss[32]; unsigned char ss2[32]; + int err; if (G_monero_vstate.tx_sig_mode == TRANSACTION_CREATE_FAKE) { monero_io_fetch(xin, 32); monero_io_fetch(alpha, 32); } else if (G_monero_vstate.tx_sig_mode == TRANSACTION_CREATE_REAL) { - monero_io_fetch_decrypt(xin, 32, TYPE_SCALAR); - monero_io_fetch_decrypt(alpha, 32, TYPE_ALPHA); + err = monero_io_fetch_decrypt(xin, 32, TYPE_SCALAR); + if (err) { + return err; + } + err = monero_io_fetch_decrypt(alpha, 32, TYPE_ALPHA); + if (err) { + return err; + } } else { - monero_lock_and_throw(SW_SECURITY_INTERNAL); + return SW_SECURITY_INTERNAL; } monero_io_discard(1); // check xin and alpha are not null if (cx_math_is_zero(xin, 32) || cx_math_is_zero(alpha, 32)) { - monero_lock_and_throw(SW_SECURITY_RANGE_VALUE); + return SW_SECURITY_RANGE_VALUE; } - monero_reduce(ss, G_monero_vstate.c); - monero_reduce(xin, xin); - monero_multm(ss, ss, xin); + err = monero_reduce(ss, G_monero_vstate.c, sizeof(ss), sizeof(G_monero_vstate.c)); + if (err) { + return err; + } - monero_reduce(alpha, alpha); - monero_subm(ss2, alpha, ss); + err = monero_reduce(xin, xin, sizeof(xin), sizeof(xin)); + if (err) { + return err; + } + + err = monero_multm(ss, ss, xin, sizeof(ss), sizeof(ss), sizeof(xin)); + if (err) { + return err; + } + + err = monero_reduce(alpha, alpha, sizeof(alpha), sizeof(alpha)); + if (err) { + return err; + } + err = monero_subm(ss2, alpha, ss, sizeof(ss2), sizeof(alpha), sizeof(ss)); + if (err) { + return err; + } monero_io_insert(ss2, 32); monero_io_insert_u32(G_monero_vstate.tx_sig_mode); diff --git a/src/monero_monero.c b/src/monero_monero.c index 598a82b..297465d 100644 --- a/src/monero_monero.c +++ b/src/monero_monero.c @@ -122,6 +122,7 @@ int monero_base58_public_key(char* str_b58, unsigned char* view, unsigned char* unsigned char data[72 + 8]; unsigned int offset; unsigned int prefix; + int error = 0; switch (N_monero_pstate->network_id) { case TESTNET: @@ -157,7 +158,10 @@ int monero_base58_public_key(char* str_b58, unsigned char* view, unsigned char* str_b58[0] = 0; return 0; } - offset = monero_encode_varint(data, 8, prefix); + error = monero_encode_varint(data, 8, prefix, &offset); + if (error) { + return error; + } memcpy(data + offset, spend, 32); memcpy(data + offset + 32, view, 32); @@ -166,7 +170,10 @@ int monero_base58_public_key(char* str_b58, unsigned char* view, unsigned char* memcpy(data + offset, paymanetID, 8); offset += 8; } - monero_keccak_F(data, offset, G_monero_vstate.mlsagH); + error = monero_keccak_F(data, offset, G_monero_vstate.mlsagH); + if (error) { + return error; + } memcpy(data + offset, G_monero_vstate.mlsagH, 4); offset += 4; diff --git a/src/monero_open_tx.c b/src/monero_open_tx.c index b799781..8e8183d 100644 --- a/src/monero_open_tx.c +++ b/src/monero_open_tx.c @@ -25,12 +25,16 @@ /* ----------------------------------------------------------------------- */ /* --- --- */ /* ----------------------------------------------------------------------- */ -void monero_reset_tx(int reset_tx_cnt) { +int monero_reset_tx(int reset_tx_cnt) { + int error; memset(G_monero_vstate.r, 0, 32); memset(G_monero_vstate.R, 0, 32); cx_rng(G_monero_vstate.hmac_key, 32); - monero_keccak_init_H(); + error = monero_keccak_init_H(); + if (error) { + return error; + } monero_sha256_commitment_init(); monero_sha256_outkeys_init(); G_monero_vstate.tx_in_progress = 0; @@ -38,6 +42,7 @@ void monero_reset_tx(int reset_tx_cnt) { if (reset_tx_cnt) { G_monero_vstate.tx_cnt = 0; } + return 0; } /* ----------------------------------------------------------------------- */ @@ -47,17 +52,22 @@ void monero_reset_tx(int reset_tx_cnt) { * HD wallet not yet supported : account is assumed to be zero */ int monero_apdu_open_tx() { + int error; monero_io_fetch_u32(); // skip account monero_io_discard(1); - monero_reset_tx(0); + error = monero_reset_tx(0); + if (error) { + return error; + } G_monero_vstate.tx_cnt++; ui_menu_opentx_display(0); return monero_apdu_open_tx_cont(); } int monero_apdu_open_tx_cont() { + int error; G_monero_vstate.tx_in_progress = 1; #ifdef DEBUG_HWDEVICE @@ -66,8 +76,16 @@ int monero_apdu_open_tx_cont() { cx_rng(G_monero_vstate.hmac_key, 32); #endif - monero_rng_mod_order(G_monero_vstate.r); - monero_ecmul_G(G_monero_vstate.R, G_monero_vstate.r); + error = monero_rng_mod_order(G_monero_vstate.r, sizeof(G_monero_vstate.r)); + if (error) { + return error; + } + + error = monero_ecmul_G(G_monero_vstate.R, G_monero_vstate.r, sizeof(G_monero_vstate.R), + sizeof(G_monero_vstate.r)); + if (error) { + return error; + } monero_io_insert(G_monero_vstate.R, 32); monero_io_insert_encrypt(G_monero_vstate.r, 32, TYPE_SCALAR); @@ -82,8 +100,12 @@ int monero_apdu_open_tx_cont() { /* --- --- */ /* ----------------------------------------------------------------------- */ int monero_apdu_close_tx() { + int error; monero_io_discard(1); - monero_reset_tx(G_monero_vstate.tx_sig_mode == TRANSACTION_CREATE_REAL); + error = monero_reset_tx(G_monero_vstate.tx_sig_mode == TRANSACTION_CREATE_REAL); + if (error) { + return error; + } #ifdef HAVE_BAGL ui_menu_main_display(); #endif @@ -114,7 +136,7 @@ int monero_apdu_set_signature_mode() { case TRANSACTION_CREATE_FAKE: break; default: - monero_lock_and_throw(SW_WRONG_DATA); + return SW_WRONG_DATA; } G_monero_vstate.tx_sig_mode = sig_mode; diff --git a/src/monero_prefix.c b/src/monero_prefix.c index 54d5ed6..0d81100 100644 --- a/src/monero_prefix.c +++ b/src/monero_prefix.c @@ -31,20 +31,35 @@ /* ----------------------------------------------------------------------- */ int monero_apdu_prefix_hash_init(void) { uint64_t timelock; + int error = 0; - monero_keccak_update_H(G_monero_vstate.io_buffer + G_monero_vstate.io_offset, - G_monero_vstate.io_length - G_monero_vstate.io_offset); + error = monero_keccak_update_H(G_monero_vstate.io_buffer + G_monero_vstate.io_offset, + G_monero_vstate.io_length - G_monero_vstate.io_offset); + if (error) { + return error; + } if (G_monero_vstate.tx_sig_mode == TRANSACTION_CREATE_REAL) { - monero_io_fetch_varint(); - timelock = monero_io_fetch_varint(); + error = monero_io_fetch_varint(&timelock); // DUmmy call TODO + if (error) { + return error; + } + + error = monero_io_fetch_varint(&timelock); + if (error) { + return error; + } + if (monero_io_fetch_available() != 0) { - THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; } // ask user monero_io_discard(1); if (timelock != 0) { - monero_uint642str(timelock, G_monero_vstate.ux_amount, 15); + error = monero_uint642str(timelock, G_monero_vstate.ux_amount, 15); + if (error) { + return error; + } ui_menu_timelock_validation_display(0); return 0; } else { @@ -60,11 +75,19 @@ int monero_apdu_prefix_hash_init(void) { /* --- --- */ /* ----------------------------------------------------------------------- */ int monero_apdu_prefix_hash_update(void) { - monero_keccak_update_H(G_monero_vstate.io_buffer + G_monero_vstate.io_offset, - G_monero_vstate.io_length - G_monero_vstate.io_offset); + int error; + error = monero_keccak_update_H(G_monero_vstate.io_buffer + G_monero_vstate.io_offset, + G_monero_vstate.io_length - G_monero_vstate.io_offset); + if (error) { + return error; + } + monero_io_discard(0); if ((G_monero_vstate.options & 0x80) == 0x00) { - monero_keccak_final_H(G_monero_vstate.prefixH); + error = monero_keccak_final_H(G_monero_vstate.prefixH); + if (error) { + return error; + } monero_io_insert(G_monero_vstate.prefixH, 32); } diff --git a/src/monero_prehash.c b/src/monero_prehash.c index 5735926..1405f8b 100644 --- a/src/monero_prehash.c +++ b/src/monero_prehash.c @@ -30,16 +30,26 @@ /* --- --- */ /* ----------------------------------------------------------------------- */ int monero_apdu_mlsag_prehash_init() { + int error = 0; if (G_monero_vstate.tx_sig_mode == TRANSACTION_CREATE_REAL) { if (G_monero_vstate.io_p2 == 1) { - monero_sha256_outkeys_final(G_monero_vstate.OUTK); + error = monero_sha256_outkeys_final(G_monero_vstate.OUTK); + if (error) { + return error; + } monero_sha256_outkeys_init(); monero_sha256_commitment_init(); - monero_keccak_init_H(); + error = monero_keccak_init_H(); + if (error) { + return error; + } } } - monero_keccak_update_H(G_monero_vstate.io_buffer + G_monero_vstate.io_offset, - G_monero_vstate.io_length - G_monero_vstate.io_offset); + error = monero_keccak_update_H(G_monero_vstate.io_buffer + G_monero_vstate.io_offset, + G_monero_vstate.io_length - G_monero_vstate.io_offset); + if (error) { + return error; + } if ((G_monero_vstate.tx_sig_mode == TRANSACTION_CREATE_REAL) && (G_monero_vstate.io_p2 == 1)) { // skip type monero_io_fetch_u8(); @@ -71,6 +81,7 @@ int monero_apdu_mlsag_prehash_update() { #define aH AKout unsigned char kG[32]; + int err = 0; // fetch destination is_subaddress = monero_io_fetch_u8(); @@ -80,10 +91,13 @@ int monero_apdu_mlsag_prehash_update() { is_change = 0; } Aout = G_monero_vstate.io_buffer + G_monero_vstate.io_offset; - monero_io_fetch(NULL, 32); + monero_io_skip(32); Bout = G_monero_vstate.io_buffer + G_monero_vstate.io_offset; - monero_io_fetch(NULL, 32); - monero_io_fetch_decrypt(AKout, 32, TYPE_AMOUNT_KEY); + monero_io_skip(32); + err = monero_io_fetch_decrypt(AKout, 32, TYPE_AMOUNT_KEY); + if (err) { + return err; + } monero_io_fetch(C, 32); monero_io_fetch(k, 32); monero_io_fetch(v, 32); @@ -92,59 +106,110 @@ int monero_apdu_mlsag_prehash_update() { // update MLSAG prehash if ((G_monero_vstate.options & 0x03) == 0x02) { - monero_keccak_update_H(v, 8); + err = monero_keccak_update_H(v, 8); + if (err) { + return err; + } + } else { - monero_keccak_update_H(k, 32); - monero_keccak_update_H(v, 32); + err = monero_keccak_update_H(k, 32); + if (err) { + return err; + } + + err = monero_keccak_update_H(v, 32); + if (err) { + return err; + } } if (G_monero_vstate.tx_sig_mode == TRANSACTION_CREATE_REAL) { if (is_change == 0) { // encode dest adress - monero_base58_public_key(&G_monero_vstate.ux_address[0], Aout, Bout, is_subaddress, - NULL); + err = monero_base58_public_key(&G_monero_vstate.ux_address[0], Aout, Bout, + is_subaddress, NULL); + if (err) { + return err; + } } // update destination hash control if (G_monero_vstate.io_protocol_version >= 2) { - monero_sha256_outkeys_update(Aout, 32); - monero_sha256_outkeys_update(Bout, 32); - monero_sha256_outkeys_update(&is_change, 1); - monero_sha256_outkeys_update(AKout, 32); + err = monero_sha256_outkeys_update(Aout, 32); + if (err) { + return err; + } + err = monero_sha256_outkeys_update(Bout, 32); + if (err) { + return err; + } + err = monero_sha256_outkeys_update(&is_change, 1); + if (err) { + return err; + } + err = monero_sha256_outkeys_update(AKout, 32); + if (err) { + return err; + } } // check C = aH+kG - monero_unblind(v, k, AKout, G_monero_vstate.options & 0x03); - monero_ecmul_G(kG, k); + err = monero_unblind(v, k, AKout, G_monero_vstate.options & 0x03, sizeof(v), sizeof(k), + sizeof(AKout)); + if (err) { + return err; + } + + err = monero_ecmul_G(kG, k, sizeof(kG), sizeof(k)); + if (err) { + return err; + } + if (!cx_math_is_zero(v, 32)) { - monero_ecmul_H(aH, v); - monero_ecadd(aH, kG, aH); + err = monero_ecmul_H(aH, v, sizeof(aH), sizeof(v)); + if (err) { + return err; + } + + err = monero_ecadd(aH, kG, aH, sizeof(aH), sizeof(kG), sizeof(aH)); + if (err) { + return err; + } } else { memcpy(aH, kG, 32); } if (memcmp(C, aH, 32) != 0) { #ifndef BYPASS_COMMITMENT_FOR_TESTS - monero_lock_and_throw(SW_SECURITY_COMMITMENT_CONTROL); + return SW_SECURITY_COMMITMENT_CHAIN_CONTROL; #endif } // update commitment hash control - monero_sha256_commitment_update(C, 32); + err = monero_sha256_commitment_update(C, 32); + if (err) { + return err; + } if ((G_monero_vstate.options & IN_OPTION_MORE_COMMAND) == 0) { if (G_monero_vstate.io_protocol_version >= 2) { // finalize and check destination hash_control - monero_sha256_outkeys_final(k); + err = monero_sha256_outkeys_final(k); + if (err) { + return err; + } if (memcmp(k, G_monero_vstate.OUTK, 32) != 0) { - monero_lock_and_throw(SW_SECURITY_OUTKEYS_CHAIN_CONTROL); + return SW_SECURITY_COMMITMENT_CHAIN_CONTROL; } } // finalize commitment hash control - monero_sha256_commitment_final(NULL); + err = monero_sha256_commitment_final(NULL); + if (err) { + return err; + } monero_sha256_commitment_init(); } // ask user uint64_t amount; - amount = monero_bamount2uint64(v); + amount = monero_bamount2uint64(v, sizeof(v)); if (amount) { monero_amount2str(amount, G_monero_vstate.ux_amount, 15); @@ -176,41 +241,74 @@ int monero_apdu_mlsag_prehash_finalize() { unsigned char message[32]; unsigned char proof[32]; unsigned char H[32]; + int error; if (G_monero_vstate.options & IN_OPTION_MORE_COMMAND) { // accumulate monero_io_fetch(H, 32); monero_io_discard(1); - monero_keccak_update_H(H, 32); - monero_sha256_commitment_update(H, 32); + error = monero_keccak_update_H(H, 32); + if (error) { + return error; + } + + error = monero_sha256_commitment_update(H, 32); + if (error) { + return error; + } } else { // Finalize and check commitment hash control if (G_monero_vstate.tx_sig_mode == TRANSACTION_CREATE_REAL) { - monero_sha256_commitment_final(H); + error = monero_sha256_commitment_final(H); + if (error) { + return error; + } if (memcmp(H, G_monero_vstate.C, 32) != 0) { #ifndef BYPASS_COMMITMENT_FOR_TESTS - monero_lock_and_throw(SW_SECURITY_COMMITMENT_CHAIN_CONTROL); + return SW_SECURITY_COMMITMENT_CHAIN_CONTROL; #endif } } // compute last H - monero_keccak_final_H(H); + error = monero_keccak_final_H(H); + if (error) { + return error; + } // compute last prehash monero_io_fetch(message, 32); monero_io_fetch(proof, 32); monero_io_discard(1); - monero_keccak_init_H(); + error = monero_keccak_init_H(); + if (error) { + return error; + } + if (G_monero_vstate.io_protocol_version >= 3) { if (memcmp(message, G_monero_vstate.prefixH, 32) != 0) { #ifndef BYPASS_COMMITMENT_FOR_TESTS - monero_lock_and_throw(SW_SECURITY_PREFIX_HASH); + return SW_SECURITY_PREFIX_HASH; #endif } } - monero_keccak_update_H(message, 32); - monero_keccak_update_H(H, 32); - monero_keccak_update_H(proof, 32); - monero_keccak_final_H(G_monero_vstate.mlsagH); + error = monero_keccak_update_H(message, 32); + if (error) { + return error; + } + + error = monero_keccak_update_H(H, 32); + if (error) { + return error; + } + + error = monero_keccak_update_H(proof, 32); + if (error) { + return error; + } + + error = monero_keccak_final_H(G_monero_vstate.mlsagH); + if (error) { + return error; + } monero_io_insert(G_monero_vstate.mlsagH, 32); diff --git a/src/monero_proof.c b/src/monero_proof.c index ca4b265..cfc013f 100644 --- a/src/monero_proof.c +++ b/src/monero_proof.c @@ -36,24 +36,33 @@ int monero_apdu_get_tx_proof() { unsigned char sig_c[32]; unsigned char sig_r[32]; unsigned char sep[32]; -#define k (G_monero_vstate.tmp + 256) + int err = 0; +#define k (G_monero_vstate.tmp + 256) +#define k_len (sizeof(G_monero_vstate.tmp) - 256) msg = G_monero_vstate.io_buffer + G_monero_vstate.io_offset; - monero_io_fetch(NULL, 32); + monero_io_skip(32); R = G_monero_vstate.io_buffer + G_monero_vstate.io_offset; - monero_io_fetch(NULL, 32); + monero_io_skip(32); A = G_monero_vstate.io_buffer + G_monero_vstate.io_offset; - monero_io_fetch(NULL, 32); + monero_io_skip(32); B = G_monero_vstate.io_buffer + G_monero_vstate.io_offset; - monero_io_fetch(NULL, 32); + monero_io_skip(32); D = G_monero_vstate.io_buffer + G_monero_vstate.io_offset; - monero_io_fetch(NULL, 32); - monero_io_fetch_decrypt_key(r); + monero_io_skip(32); + err = monero_io_fetch_decrypt_key(r, sizeof(r)); + if (err) { + return err; + } monero_io_discard(0); // Generate random k - monero_rng_mod_order(k); + err = monero_rng_mod_order(k, k_len); + if (err) { + return err; + } + // tmp = msg memcpy(G_monero_vstate.tmp + 32 * 0, msg, 32); // tmp = msg || D @@ -61,19 +70,31 @@ int monero_apdu_get_tx_proof() { if (G_monero_vstate.options & 1) { // X = kB - monero_ecmul_k(XY, B, k); + err = monero_ecmul_k(XY, B, k, sizeof(XY), 32, k_len); + if (err) { + return err; + } } else { // X = kG - monero_ecmul_G(XY, k); + err = monero_ecmul_G(XY, k, sizeof(XY), k_len); + if (err) { + return err; + } } // tmp = msg || D || X memcpy(G_monero_vstate.tmp + 32 * 2, XY, 32); // Y = kA - monero_ecmul_k(XY, A, k); + err = monero_ecmul_k(XY, A, k, sizeof(XY), 32, k_len); + if (err) { + return err; + } // tmp = msg || D || X || Y memcpy(G_monero_vstate.tmp + 32 * 3, XY, 32); - monero_keccak_H((unsigned char *)"TXPROOF_V2", 10, sep); + err = monero_keccak_H((unsigned char *)"TXPROOF_V2", 10, sep); + if (err) { + return err; + } // tmp = msg || D || X || Y || sep memcpy(G_monero_vstate.tmp + 32 * 4, sep, 32); // tmp = msg || D || X || Y || sep || R @@ -84,12 +105,22 @@ int monero_apdu_get_tx_proof() { memcpy(G_monero_vstate.tmp + 32 * 7, B, 32); // sig_c = H_n(tmp) - monero_hash_to_scalar(sig_c, &G_monero_vstate.tmp[0], 32 * 8); + err = monero_hash_to_scalar(sig_c, &G_monero_vstate.tmp[0], sizeof(sig_c), 32 * 8); + if (err) { + return err; + } // sig_c*r - monero_multm(XY, sig_c, r); + err = monero_multm(XY, sig_c, r, sizeof(XY), sizeof(sig_c), sizeof(r)); + if (err) { + return err; + } + // sig_r = k - sig_c*r - monero_subm(sig_r, k, XY); + err = monero_subm(sig_r, k, XY, sizeof(sig_r), k_len, sizeof(r)); + if (err) { + return err; + } monero_io_insert(sig_c, 32); monero_io_insert(sig_r, 32); diff --git a/src/monero_ram.c b/src/monero_ram.c index 7f7fd49..542fe72 100644 --- a/src/monero_ram.c +++ b/src/monero_ram.c @@ -24,20 +24,10 @@ #include "os_io_seproxyhal.h" -unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; - -#ifdef HAVE_UX_FLOW -/* --- "NANO-X" and "NANO-S flow" config --- */ +extern unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; #include "ux.h" -ux_state_t G_ux; -bolos_ux_params_t G_ux_params; - -#else -/* --- "NANO-S legacy" config --- */ - -ux_state_t ux; - -#endif +extern ux_state_t G_ux; +extern bolos_ux_params_t G_ux_params; monero_v_state_t G_monero_vstate; diff --git a/src/monero_stealth.c b/src/monero_stealth.c index 7d82e2a..97ea397 100644 --- a/src/monero_stealth.c +++ b/src/monero_stealth.c @@ -31,22 +31,32 @@ int monero_apdu_stealth() { unsigned char sec[32]; unsigned char drv[33]; unsigned char payID[8]; + int err = 0; // fetch pub monero_io_fetch(pub, 32); // fetch sec - monero_io_fetch_decrypt_key(sec); + err = monero_io_fetch_decrypt_key(sec, sizeof(sec)); + if (err) { + return err; + } // fetch paymentID monero_io_fetch(payID, 8); monero_io_discard(0); // Compute Dout - monero_generate_key_derivation(drv, pub, sec); + err = monero_generate_key_derivation(drv, pub, sec, sizeof(drv), sizeof(pub), sizeof(sec)); + if (err) { + return err; + } // compute mask drv[32] = ENCRYPTED_PAYMENT_ID_TAIL; - monero_keccak_F(drv, 33, sec); + err = monero_keccak_F(drv, 33, sec); + if (err) { + return err; + } // stealth! for (i = 0; i < 8; i++) { diff --git a/src/monero_types.h b/src/monero_types.h index d83c4d5..13eba01 100644 --- a/src/monero_types.h +++ b/src/monero_types.h @@ -21,18 +21,10 @@ #include "os_io_seproxyhal.h" -#if CX_APILEVEL == 8 -#define PIN_VERIFIED (!0) -#elif CX_APILEVEL >= 9 -#define PIN_VERIFIED BOLOS_UX_OK -#else -#error CX_APILEVEL not supported -#endif - /* cannot send more that F0 bytes in CCID, why? do not know for now - * So set up length to F0 minus 2 bytes for SW + * So set up length to F0 */ -#define MONERO_APDU_LENGTH 0xFE +#define MONERO_APDU_LENGTH 0xF0 /* big private DO */ #define MONERO_EXT_PRIVATE_DO_LENGTH 512 diff --git a/src/monero_ux_nano.c b/src/monero_ux_nano.c index 132bfcb..1b4523b 100644 --- a/src/monero_ux_nano.c +++ b/src/monero_ux_nano.c @@ -16,7 +16,7 @@ * limitations under the License. *****************************************************************************/ -#if defined(UI_NANO_X) || defined(UI_NANO_SX) +#ifdef HAVE_BAGL #include "os.h" #include "cx.h" @@ -36,39 +36,16 @@ #define ACCEPT 0xACCE #define REJECT ~ACCEPT +void __attribute__((noreturn)) app_exit(void); void ui_menu_main_display(); -/* -------------------------------------- LOCK--------------------------------------- */ - -void ui_menu_pinlock_display() { - struct { - bolos_ux_t ux_id; - // length of parameters in the u union to be copied during the syscall - unsigned int len; - union { - struct { - unsigned int cancellable; - } validate_pin; - } u; - - } ux_params; - - os_global_pin_invalidate(); - G_monero_vstate.protocol_barrier = PROTOCOL_LOCKED_UNLOCKABLE; - ux_params.ux_id = BOLOS_UX_VALIDATE_PIN; - ux_params.len = sizeof(ux_params.u.validate_pin); - ux_params.u.validate_pin.cancellable = 0; - os_ux((bolos_ux_params_t*)&ux_params); - ui_menu_main_display(); -} - /* -------------------------------------- 25 WORDS --------------------------------------- */ void ui_menu_words_display(unsigned int value); void ui_menu_words_clear(unsigned int value); void ui_menu_words_back(unsigned int value); UX_STEP_NOCB(ux_menu_words_1_step, -#ifdef UI_NANO_X +#ifndef TARGET_NANOS bnnn_paging, #else bn_paging, @@ -102,9 +79,7 @@ void settings_show_25_words(void) { ui_menu_words_display(0); } /* -------------------------------- INFO UX --------------------------------- */ -unsigned int ui_menu_info_action(unsigned int value); - -UX_STEP_CB(ux_menu_info_1_step, nn, ui_menu_info_action(0), +UX_STEP_CB(ux_menu_info_1_step, nn, (void)ui_menu_main_display(), { G_monero_vstate.ux_info1, G_monero_vstate.ux_info2, @@ -112,15 +87,6 @@ UX_STEP_CB(ux_menu_info_1_step, nn, ui_menu_info_action(0), UX_FLOW(ux_flow_info, &ux_menu_info_1_step); -unsigned int ui_menu_info_action(unsigned int value __attribute__((unused))) { - if (G_monero_vstate.protocol_barrier == PROTOCOL_LOCKED) { - ui_menu_pinlock_display(); - } else { - ui_menu_main_display(); - } - return 0; -} - static void ui_menu_info_display2(unsigned int value __attribute__((unused)), const char* line1, const char* line2) { snprintf(G_monero_vstate.ux_info1, sizeof(G_monero_vstate.ux_info1), "%s", line1); @@ -282,7 +248,7 @@ void ui_menu_validation_action(unsigned int value); UX_STEP_NOCB(ux_menu_validation_1_step, bn, {"Amount", G_monero_vstate.ux_amount}); UX_STEP_NOCB(ux_menu_validation_2_step, -#ifdef UI_NANO_X +#ifndef TARGET_NANOS bnnn_paging, #else bn_paging, @@ -562,7 +528,7 @@ void settings_submenu_selector(unsigned int idx) { #define STR(x) #x #define XSTR(x) STR(x) -#ifdef UI_NANO_X +#ifndef TARGET_NANOS UX_STEP_NOCB(ux_menu_about_1_step, bnnn, { "Monero", @@ -592,7 +558,7 @@ UX_STEP_CB(ux_menu_about_2_step, pb, ui_menu_main_display(), }); UX_FLOW(ux_flow_about, -#ifdef UI_NANO_X +#ifndef TARGET_NANOS &ux_menu_about_1_step, #else &ux_menu_about_1a_step, &ux_menu_about_1b_step, @@ -647,9 +613,9 @@ void ui_menu_pubaddr_action(unsigned int value __attribute__((unused))) { /** * */ -void ui_menu_any_pubaddr_display(unsigned int value __attribute__((unused)), - unsigned char* pub_view, unsigned char* pub_spend, - unsigned char is_subbadress, unsigned char* paymanetID) { +int ui_menu_any_pubaddr_display(unsigned int value __attribute__((unused)), unsigned char* pub_view, + unsigned char* pub_spend, unsigned char is_subbadress, + unsigned char* paymanetID) { memset(G_monero_vstate.ux_address, 0, sizeof(G_monero_vstate.ux_address)); switch (G_monero_vstate.disp_addr_mode) { @@ -673,17 +639,24 @@ void ui_menu_any_pubaddr_display(unsigned int value __attribute__((unused)), break; } - monero_base58_public_key(G_monero_vstate.ux_address, pub_view, pub_spend, is_subbadress, - paymanetID); + int error = monero_base58_public_key(G_monero_vstate.ux_address, pub_view, pub_spend, + is_subbadress, paymanetID); + if (error) { + return error; + } ux_layout_bnnn_paging_reset(); ux_flow_init(0, ux_flow_pubaddr, NULL); + return 0; } void ui_menu_pubaddr_display(unsigned int value) { G_monero_vstate.disp_addr_mode = 0; G_monero_vstate.disp_addr_M = 0; G_monero_vstate.disp_addr_m = 0; - ui_menu_any_pubaddr_display(value, G_monero_vstate.A, G_monero_vstate.B, 0, NULL); + int error = ui_menu_any_pubaddr_display(value, G_monero_vstate.A, G_monero_vstate.B, 0, NULL); + if (error) { + app_exit(); + } } #undef ADDR_TYPE @@ -705,7 +678,7 @@ UX_STEP_CB(ux_menu_main_2_step, pb, UX_STEP_CB(ux_menu_main_3_step, pb, ui_menu_about_display(), {&C_icon_certificate, "About"}); -UX_STEP_CB(ux_menu_main_4_step, pb, os_sched_exit(0), {&C_icon_dashboard_x, "Quit app"}); +UX_STEP_CB(ux_menu_main_4_step, pb, app_exit(), {&C_icon_dashboard_x, "Quit app"}); UX_FLOW(ux_flow_main, &ux_menu_main_1_step, &ux_menu_main_2_step, &ux_menu_main_3_step, &ux_menu_main_4_step); diff --git a/src/monero_ux_nanos.c b/src/monero_ux_nanos.c deleted file mode 100644 index c4519e0..0000000 --- a/src/monero_ux_nanos.c +++ /dev/null @@ -1,819 +0,0 @@ -/***************************************************************************** - * Ledger Monero App. - * (c) 2017-2020 Cedric Mesnil , Ledger SAS. - * (c) 2020 Ledger SAS. - * - * 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. - *****************************************************************************/ - -#ifdef UI_NANO_S - -#include "os.h" -#include "cx.h" -#include "monero_types.h" -#include "monero_api.h" -#include "monero_vars.h" - -#include "monero_ux_msg.h" -#include "os_io_seproxyhal.h" -#include "string.h" -#include "glyphs.h" - -/* ----------------------------------------------------------------------- */ -/* --- NanoS UI layout --- */ -/* ----------------------------------------------------------------------- */ - -const ux_menu_entry_t ui_menu_reset[]; -void ui_menu_reset_action(unsigned int value); - -const ux_menu_entry_t ui_menu_settings[]; - -const ux_menu_entry_t ui_menu_main[]; -void ui_menu_main_display_value(unsigned int value); -const bagl_element_t* ui_menu_main_preprocessor(const ux_menu_entry_t* entry, - bagl_element_t* element); - -void ui_menu_settings_display(unsigned int value); - -/* -------------------------------------- LOCK--------------------------------------- */ - -void ui_menu_pinlock_display() { - struct { - bolos_ux_t ux_id; - // length of parameters in the u union to be copied during the syscall - unsigned int len; - union { - struct { - unsigned int cancellable; - } validate_pin; - } u; - } ux_params; - - os_global_pin_invalidate(); - G_monero_vstate.protocol_barrier = PROTOCOL_LOCKED_UNLOCKABLE; - ux_params.ux_id = BOLOS_UX_VALIDATE_PIN; - ux_params.len = sizeof(ux_params.u.validate_pin); - ux_params.u.validate_pin.cancellable = 0; - os_ux((bolos_ux_params_t*)&ux_params); - ui_menu_main_display_value(0); -} - -/* -------------------------------------- 25 WORDS --------------------------------------- */ -void ui_menu_words_clear(unsigned int value); -void ui_menu_words_back(unsigned int value); -#define WORDS N_monero_pstate->words -const ux_menu_entry_t ui_menu_words[] = { - {NULL, ui_menu_words_back, 0, NULL, "", "", 0, 0}, - {NULL, ui_menu_words_back, 2, NULL, "", "", 0, 0}, - {NULL, ui_menu_words_back, 4, NULL, "", "", 0, 0}, - {NULL, ui_menu_words_back, 6, NULL, "", "", 0, 0}, - {NULL, ui_menu_words_back, 8, NULL, "", "", 0, 0}, - {NULL, ui_menu_words_back, 10, NULL, "", "", 0, 0}, - {NULL, ui_menu_words_back, 12, NULL, "", "", 0, 0}, - {NULL, ui_menu_words_back, 14, NULL, "", "", 0, 0}, - {NULL, ui_menu_words_back, 16, NULL, "", "", 0, 0}, - {NULL, ui_menu_words_back, 18, NULL, "", "", 0, 0}, - {NULL, ui_menu_words_back, 20, NULL, "", "", 0, 0}, - {NULL, ui_menu_words_back, 22, NULL, "", "", 0, 0}, - {NULL, ui_menu_words_back, 24, NULL, "", "", 0, 0}, - {NULL, ui_menu_words_clear, -1, NULL, "CLEAR WORDS", "(NO WIPE)", 0, 0}, - UX_MENU_END}; - -const bagl_element_t* ui_menu_words_preprocessor(const ux_menu_entry_t* entry, - bagl_element_t* element) { - if (entry->userid < 25) { - if (element->component.userid == 0x21) { - element->text = N_monero_pstate->words[entry->userid]; - } - - if ((element->component.userid == 0x22) && (entry->userid < 24)) { - element->text = N_monero_pstate->words[entry->userid + 1]; - } - } - - return element; -} - -void ui_menu_words_display(unsigned int value __attribute__((unused))) { - UX_MENU_DISPLAY(0, ui_menu_words, ui_menu_words_preprocessor); -} - -void ui_menu_words_clear(unsigned int value __attribute__((unused))) { - monero_clear_words(); - ui_menu_main_display_value(0); -} - -void ui_menu_words_back(unsigned int value __attribute__((unused))) { - ui_menu_settings_display(1); -} - -/* -------------------------------- INFO UX --------------------------------- */ -unsigned int ui_menu_info_button(unsigned int button_mask, unsigned int button_mask_counter); - -const bagl_element_t ui_menu_info[] = { - // type userid x y w h str rad fill fg bg - // font_id icon_id - {{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, NULL}, - - {{BAGL_LABELINE, 0x01, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, - BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, - G_monero_vstate.ux_info1}, - - {{BAGL_LABELINE, 0x02, 0, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, - BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, - G_monero_vstate.ux_info2}, -}; - -unsigned int ui_menu_info_button(unsigned int button_mask, - unsigned int button_mask_counter __attribute__((unused))) { - switch (button_mask) { - case BUTTON_EVT_RELEASED | BUTTON_RIGHT: - case BUTTON_EVT_RELEASED | BUTTON_LEFT: - if (G_monero_vstate.protocol_barrier == PROTOCOL_LOCKED) { - ui_menu_pinlock_display(); - } else { - ui_menu_main_display_value(0); - } - break; - - default: - return 0; - } - return 0; -} - -static void ui_menu_info_display2(unsigned int value __attribute__((unused)), const char* line1, - const char* line2) { - snprintf(G_monero_vstate.ux_info1, sizeof(G_monero_vstate.ux_info1), "%s", line1); - snprintf(G_monero_vstate.ux_info2, sizeof(G_monero_vstate.ux_info2), "%s", line2); - UX_DISPLAY(ui_menu_info, NULL); -} - -static void ui_menu_info_display(unsigned int value __attribute__((unused))) { - UX_DISPLAY(ui_menu_info, NULL); -} - -void ui_menu_show_tx_aborted(void) { - ui_menu_info_display2(0, "TX", "Aborted"); -} - -void ui_menu_show_security_error(void) { - ui_menu_info_display(0); -} - -/* -------------------------------- OPEN TX UX --------------------------------- */ - -unsigned int ui_menu_transaction_signed(void) { - return SW_OK; -} - -unsigned int ui_menu_transaction_start(void) { - return SW_OK; -} - -unsigned int ui_menu_opentx_button(unsigned int button_mask, unsigned int button_mask_counter); - -const bagl_element_t ui_menu_opentx[] = { - // type userid x y w h str rad fill fg bg - // font_id icon_id - {{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, NULL}, - - {{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS}, NULL}, - - {{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK}, NULL}, - - {{BAGL_LABELINE, 0x01, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, - BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, - "Process"}, - - {{BAGL_LABELINE, 0x02, 0, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, - BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, - "new TX ?"}, - -}; - -unsigned int ui_menu_opentx_button(unsigned int button_mask, - unsigned int button_mask_counter __attribute__((unused))) { - unsigned int sw = SW_OK; - unsigned char x[32]; - - monero_io_discard(0); - memset(x, 0, 32); - - switch (button_mask) { - case BUTTON_EVT_RELEASED | BUTTON_LEFT: // CANCEL - monero_abort_tx(); - sw = SW_DENY; - break; - - case BUTTON_EVT_RELEASED | BUTTON_RIGHT: // OK - sw = monero_apdu_open_tx_cont(); - break; - - default: - return 0; - } - monero_io_insert_u16(sw); - monero_io_do(IO_RETURN_AFTER_TX); - if (sw == SW_OK) { - ui_menu_info_display2(0, "Processing TX", "..."); - } else { - ui_menu_info_display2(0, "Transaction", "aborted"); - } - return 0; -} -#if 0 -void ui_menu_opentx_display(unsigned int value) { - if (G_monero_vstate.tx_sig_mode == TRANSACTION_CREATE_REAL) { - UX_DISPLAY(ui_menu_opentx, (void*)NULL); - } else { - snprintf(G_monero_vstate.ux_info1, sizeof(G_monero_vstate.ux_info1), "Prepare new"); - snprintf(G_monero_vstate.ux_info2, sizeof(G_monero_vstate.ux_info2), "TX / %d", G_monero_vstate.tx_cnt); - ui_menu_info_display(0); - } -} -#else -void ui_menu_opentx_display(unsigned int value __attribute__((unused))) { - uint32_t i; - if (G_monero_vstate.tx_sig_mode == TRANSACTION_CREATE_REAL) { - snprintf(G_monero_vstate.ux_info1, sizeof(G_monero_vstate.ux_info1), "Processing TX"); - } else { - snprintf(G_monero_vstate.ux_info1, sizeof(G_monero_vstate.ux_info1), "Preparing TX"); - } - for (i = 0; (i < G_monero_vstate.tx_cnt) && (i < 12); i++) { - G_monero_vstate.ux_info2[i] = '.'; - } - G_monero_vstate.ux_info2[i] = 0; - ui_menu_info_display(0); -} -#endif - -/* ----------------- FEE/CHANGE/TIMELOCK VALIDATION ----------------- */ - -#define ACCEPT 0xACCE -#define REJECT ~ACCEPT - -void ui_menu_amount_validation_action(unsigned int value); - -const ux_menu_entry_t ui_menu_fee_validation[] = { - {NULL, NULL, 1, NULL, " Fee", "?xmr?", 0, 0}, - {NULL, ui_menu_amount_validation_action, REJECT, NULL, "Reject", "Fee", 0, 0}, - {NULL, ui_menu_amount_validation_action, ACCEPT, NULL, "Accept", "Fee", 0, 0}, - UX_MENU_END}; -const ux_menu_entry_t ui_menu_change_validation[] = { - {NULL, NULL, 1, NULL, " Change", "?xmr?", 0, 0}, - {NULL, ui_menu_amount_validation_action, REJECT, NULL, "Reject", "Change", 0, 0}, - {NULL, ui_menu_amount_validation_action, ACCEPT, NULL, "Accept", "Change", 0, 0}, - UX_MENU_END}; -const ux_menu_entry_t ui_menu_timelock_validation[] = { - {NULL, NULL, 1, NULL, " Timelock", "?...?", 0, 0}, - {NULL, ui_menu_amount_validation_action, REJECT, NULL, "Reject", "Timelock", 0, 0}, - {NULL, ui_menu_amount_validation_action, ACCEPT, NULL, "Accept", "Timelock", 0, 0}, - UX_MENU_END}; -const bagl_element_t* ui_menu_amount_validation_preprocessor(const ux_menu_entry_t* entry, - bagl_element_t* element) { - /* --- Amount --- */ - if ((entry == &ui_menu_fee_validation[0]) || (entry == &ui_menu_change_validation[0]) || - (entry == &ui_menu_timelock_validation[0])) { - if (element->component.userid == 0x22) { - element->text = G_monero_vstate.ux_amount; - } - } - return element; -} - -void ui_menu_amount_validation_action(unsigned int value) { - unsigned short sw; - if (value == ACCEPT) { - sw = SW_OK; - } else { - sw = SW_DENY; - monero_abort_tx(); - } - monero_io_insert_u16(sw); - monero_io_do(IO_RETURN_AFTER_TX); - ui_menu_info_display2(0, "Processing TX", "..."); -} - -void ui_menu_fee_validation_display(unsigned int value __attribute__((unused))) { - UX_MENU_DISPLAY(0, ui_menu_fee_validation, ui_menu_amount_validation_preprocessor); -} -void ui_menu_change_validation_display(unsigned int value __attribute__((unused))) { - UX_MENU_DISPLAY(0, ui_menu_change_validation, ui_menu_amount_validation_preprocessor); -} -void ui_menu_change_validation_display_last(unsigned int value __attribute__((unused))) { - UX_MENU_DISPLAY(0, ui_menu_change_validation, ui_menu_amount_validation_preprocessor); -} -void ui_menu_timelock_validation_display(unsigned int value __attribute__((unused))) { - UX_MENU_DISPLAY(0, ui_menu_timelock_validation, ui_menu_amount_validation_preprocessor); -} - -/* ----------------------------- USER DEST/AMOUNT VALIDATION ----------------------------- */ -void ui_menu_validation_action(unsigned int value); - -const ux_menu_entry_t ui_menu_validation[] = { - {NULL, NULL, 1, NULL, " Amount", "?xmr?", 0, 0}, - {NULL, NULL, 3, NULL, "Destination", "?dest.1?", 0, 0}, - {NULL, NULL, 4, NULL, "?dest.2?", "?dest.2?", 0, 0}, - {NULL, NULL, 5, NULL, "?dest.3?", "?dest.3?", 0, 0}, - {NULL, NULL, 6, NULL, "?dest.4?", "?dest.4?", 0, 0}, - {NULL, NULL, 7, NULL, "?dest.5?", "?dest.5?", 0, 0}, - {NULL, ui_menu_validation_action, REJECT, NULL, "Reject", "TX", 0, 0}, - {NULL, ui_menu_validation_action, ACCEPT, NULL, "Accept", "TX", 0, 0}, - UX_MENU_END}; - -const bagl_element_t* ui_menu_validation_preprocessor(const ux_menu_entry_t* entry, - bagl_element_t* element) { - /* --- Amount --- */ - if (entry == &ui_menu_validation[0]) { - if (element->component.userid == 0x22) { - element->text = G_monero_vstate.ux_amount; - } - } - - /* --- Destination --- */ - if (entry == &ui_menu_validation[1]) { - if (element->component.userid == 0x22) { - memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)); - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 0, 11); - element->text = G_monero_vstate.ux_menu; - } - } - if (entry == &ui_menu_validation[2]) { - memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)); - if (element->component.userid == 0x21) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 1, 11); - } - if (element->component.userid == 0x22) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 2, 11); - } - element->text = G_monero_vstate.ux_menu; - } - if (entry == &ui_menu_validation[3]) { - memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)); - if (element->component.userid == 0x21) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 3, 11); - } - if (element->component.userid == 0x22) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 4, 11); - } - element->text = G_monero_vstate.ux_menu; - } - if (entry == &ui_menu_validation[4]) { - memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)); - if (element->component.userid == 0x21) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 5, 11); - } - if (element->component.userid == 0x22) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 6, 11); - } - element->text = G_monero_vstate.ux_menu; - } - if (entry == &ui_menu_validation[5]) { - memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)); - if (element->component.userid == 0x21) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 7, 11); - } - if (element->component.userid == 0x22) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 8, 7); - } - element->text = G_monero_vstate.ux_menu; - } - - return element; -} - -void ui_menu_validation_display(unsigned int value __attribute__((unused))) { - UX_MENU_DISPLAY(0, ui_menu_validation, ui_menu_validation_preprocessor); -} - -void ui_menu_validation_display_last(unsigned int value __attribute__((unused))) { - UX_MENU_DISPLAY(0, ui_menu_validation, ui_menu_validation_preprocessor); -} - -void ui_menu_validation_action(unsigned int value) { - unsigned short sw; - if (value == ACCEPT) { - sw = SW_OK; - } else { - sw = SW_DENY; - monero_abort_tx(); - } - monero_io_insert_u16(sw); - monero_io_do(IO_RETURN_AFTER_TX); - ui_menu_info_display2(0, "Processing TX", "..."); -} - -/* -------------------------------- EXPORT VIEW KEY UX --------------------------------- */ -unsigned int ui_export_viewkey_prepro(const bagl_element_t* element); -unsigned int ui_export_viewkey_button(unsigned int button_mask, unsigned int button_mask_counter); - -const bagl_element_t ui_export_viewkey[] = { - // type userid x y w h str rad fill fg bg - // font_id icon_id - {{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, NULL}, - - {{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS}, NULL}, - - {{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK}, NULL}, - - {{BAGL_LABELINE, 0x01, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, - BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, - G_monero_vstate.ux_menu}, - - {{BAGL_LABELINE, 0x02, 0, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, - BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, - G_monero_vstate.ux_menu}, -}; - -void ui_export_viewkey_display(unsigned int value __attribute__((unused))) { - UX_DISPLAY(ui_export_viewkey, (void*)ui_export_viewkey_prepro); -} - -unsigned int ui_export_viewkey_prepro(const bagl_element_t* element) { - if (element->component.userid == 1) { - snprintf(G_monero_vstate.ux_menu, sizeof(G_monero_vstate.ux_menu), "Export"); - return 1; - } - if (element->component.userid == 2) { - snprintf(G_monero_vstate.ux_menu, sizeof(G_monero_vstate.ux_menu), "View Key"); - return 1; - } - snprintf(G_monero_vstate.ux_menu, sizeof(G_monero_vstate.ux_menu), "Please Cancel"); - return 1; -} - -unsigned int ui_export_viewkey_button(unsigned int button_mask, - unsigned int button_mask_counter __attribute__((unused))) { - unsigned int sw; - unsigned char x[32]; - - monero_io_discard(0); - memset(x, 0, 32); - sw = SW_OK; - - switch (button_mask) { - case BUTTON_EVT_RELEASED | BUTTON_LEFT: // CANCEL - monero_io_insert(x, 32); - G_monero_vstate.export_view_key = 0; - break; - - case BUTTON_EVT_RELEASED | BUTTON_RIGHT: // OK - monero_io_insert(G_monero_vstate.a, 32); - G_monero_vstate.export_view_key = EXPORT_VIEW_KEY; - break; - - default: - return 0; - } - monero_io_insert_u16(sw); - monero_io_do(IO_RETURN_AFTER_TX); - ui_menu_main_display_value(0); - return 0; -} - -/* -------------------------------- ACCOUNT UX --------------------------------- */ - -void ui_menu_account_action(unsigned int value); -const ux_menu_entry_t ui_menu_account[] = { - {NULL, NULL, 0, NULL, "It will reset", "the application!", 0, 0}, - {NULL, ui_menu_main_display_value, 0, &C_badge_back, "Abort", NULL, 61, 40}, - {NULL, ui_menu_account_action, 0, NULL, "0", NULL, 0, 0}, - {NULL, ui_menu_account_action, 1, NULL, "1", NULL, 0, 0}, - {NULL, ui_menu_account_action, 2, NULL, "2", NULL, 0, 0}, - {NULL, ui_menu_account_action, 3, NULL, "3", NULL, 0, 0}, - {NULL, ui_menu_account_action, 4, NULL, "4", NULL, 0, 0}, - {NULL, ui_menu_account_action, 5, NULL, "5", NULL, 0, 0}, - {NULL, ui_menu_account_action, 6, NULL, "6", NULL, 0, 0}, - {NULL, ui_menu_account_action, 7, NULL, "7", NULL, 0, 0}, - {NULL, ui_menu_account_action, 8, NULL, "8", NULL, 0, 0}, - {NULL, ui_menu_account_action, 9, NULL, "9", NULL, 0, 0}, - UX_MENU_END}; - -const bagl_element_t* ui_menu_account_preprocessor(const ux_menu_entry_t* entry, - bagl_element_t* element) { - memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)); - for (unsigned int i = 2; i < 12; i++) { - if ((entry == &ui_menu_account[i]) && (element->component.userid == 0x20) && - (N_monero_pstate->account_id == (i - 2))) { - G_monero_vstate.ux_menu[0] = '0' + (i - 2); - G_monero_vstate.ux_menu[1] = ' '; - G_monero_vstate.ux_menu[2] = '+'; - element->text = G_monero_vstate.ux_menu; - } - } - return element; -} - -void ui_menu_account_action(unsigned int value) { - monero_nvm_write((void*)&N_monero_pstate->account_id, &value, sizeof(unsigned int)); - monero_init(); - ui_menu_main_display_value(0); -} - -void ui_menu_account_display(unsigned int value) { - UX_MENU_DISPLAY(value, ui_menu_account, ui_menu_account_preprocessor); -} - -/* -------------------------------- NETWORK UX --------------------------------- */ -void ui_menu_network_action(unsigned int value); -const ux_menu_entry_t ui_menu_network[] = { - {NULL, NULL, 0, NULL, "It will reset", "the application!", 0, 0}, - {NULL, ui_menu_main_display_value, 0, &C_badge_back, "Abort", NULL, 61, 40}, - {NULL, ui_menu_network_action, TESTNET, NULL, "Test Network ", NULL, 0, 0}, - {NULL, ui_menu_network_action, STAGENET, NULL, "Stage Network", NULL, 0, 0}, -#ifndef MONERO_ALPHA - {NULL, ui_menu_network_action, MAINNET, NULL, "Main Network", NULL, 0, 0}, -#endif - UX_MENU_END}; - -const bagl_element_t* ui_menu_network_preprocessor(const ux_menu_entry_t* entry, - bagl_element_t* element) { - memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)); - if ((entry == &ui_menu_network[2]) && (element->component.userid == 0x20) && - (N_monero_pstate->network_id == TESTNET)) { - memcpy(G_monero_vstate.ux_menu, "Test Network ", 14); - G_monero_vstate.ux_menu[13] = '+'; - element->text = G_monero_vstate.ux_menu; - } - if ((entry == &ui_menu_network[3]) && (element->component.userid == 0x20) && - (N_monero_pstate->network_id == STAGENET)) { - memcpy(G_monero_vstate.ux_menu, "Stage Network ", 14); - G_monero_vstate.ux_menu[13] = '+'; - element->text = G_monero_vstate.ux_menu; - } -#ifndef MONERO_ALPHA - if ((entry == &ui_menu_network[4]) && (element->component.userid == 0x20) && - (N_monero_pstate->network_id == MAINNET)) { - memcpy(G_monero_vstate.ux_menu, "Main Network ", 14); - G_monero_vstate.ux_menu[13] = '+'; - element->text = G_monero_vstate.ux_menu; - } -#endif - return element; -} - -void ui_menu_network_action(unsigned int value) { - monero_install(value); - monero_init(); - ui_menu_main_display_value(0); -} - -void ui_menu_network_display(unsigned int value) { - UX_MENU_DISPLAY(value, ui_menu_network, ui_menu_network_preprocessor); -} - -/* -------------------------------- RESET UX --------------------------------- */ - -const ux_menu_entry_t ui_menu_reset[] = { - {NULL, NULL, 0, NULL, "Really Reset ?", NULL, 0, 0}, - {NULL, ui_menu_main_display_value, 0, &C_badge_back, "No", NULL, 61, 40}, - {NULL, ui_menu_reset_action, 0, NULL, "Yes", NULL, 0, 0}, - UX_MENU_END}; - -void ui_menu_reset_action(unsigned int value __attribute__((unused))) { - unsigned char magic[4]; - magic[0] = 0; - magic[1] = 0; - magic[2] = 0; - magic[3] = 0; - monero_nvm_write(N_monero_pstate->magic, magic, 4); - monero_init(); - ui_menu_main_display_value(0); -} -/* ------------------------------- SETTINGS UX ------------------------------- */ - -const ux_menu_entry_t ui_menu_settings[] = { - {NULL, ui_menu_account_display, 0, NULL, "Select Wallet", NULL, 0, 0}, - {NULL, ui_menu_network_display, 0, NULL, "Select Network", NULL, 0, 0}, - {NULL, ui_menu_words_display, 0, NULL, "Show 25 words", NULL, 0, 0}, - {ui_menu_reset, NULL, 0, NULL, "Reset", NULL, 0, 0}, - {NULL, ui_menu_main_display_value, 2, &C_badge_back, "Back", NULL, 61, 40}, - UX_MENU_END}; - -void ui_menu_settings_display(unsigned int value) { - UX_MENU_DISPLAY(value, ui_menu_settings, NULL); -} - -/* --------------------------------- INFO UX --------------------------------- */ - -#define STR(x) #x -#define XSTR(x) STR(x) - -const ux_menu_entry_t ui_menu_about[] = { - {NULL, NULL, -1, NULL, "Monero", NULL, 0, 0}, - {NULL, NULL, -1, NULL, "(c) Ledger SAS", NULL, 0, 0}, - {NULL, NULL, -1, NULL, "Spec " XSTR(SPEC_VERSION), NULL, 0, 0}, - {NULL, NULL, -1, NULL, "App " XSTR(MONERO_VERSION), NULL, 0, 0}, - {NULL, ui_menu_main_display_value, 3, &C_badge_back, "Back", NULL, 61, 40}, - UX_MENU_END}; - -#undef STR -#undef XSTR - -/* ---------------------------- PUBLIC ADDRESS UX ---------------------------- */ - -void ui_menu_pubaddr_action(unsigned int value); - -const ux_menu_entry_t ui_menu_pubaddr[] = { - {NULL, NULL, 3, NULL, "t1.1", "t1.2", 0, 0}, - - {NULL, NULL, 3, NULL, "i1.1", "i1.2", 0, 0}, - - {NULL, NULL, 5, NULL, "l1.1", "l1.2", 0, 0}, - {NULL, NULL, 6, NULL, "l2.1", "l2.2", 0, 0}, - {NULL, NULL, 7, NULL, "l3.1", "l3.2", 0, 0}, - {NULL, NULL, 6, NULL, "l4.1", "l4.2", 0, 0}, - {NULL, NULL, 7, NULL, "l5.1", "l5.2", 0, 0}, - //{NULL, ui_menu_main_display_value, 0, &C_badge_back, "Back", NULL, 61, - // 40}, - {NULL, ui_menu_pubaddr_action, 0, &C_badge_back, "Ok", NULL, 61, 40}, - UX_MENU_END}; - -const bagl_element_t* ui_menu_pubaddr_preprocessor(const ux_menu_entry_t* entry, - bagl_element_t* element) { - /* --- address --- */ - if (entry == &ui_menu_pubaddr[0]) { - memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)); - if (element->component.userid == 0x21) { - switch (G_monero_vstate.disp_addr_mode) { - case 0: - case DISP_MAIN: - memcpy(G_monero_vstate.ux_menu, "Main", 4); - break; - case DISP_SUB: - memcpy(G_monero_vstate.ux_menu, "Sub", 3); - break; - case DISP_INTEGRATED: - memcpy(G_monero_vstate.ux_menu, "Integrated", 10); - break; - } - element->text = G_monero_vstate.ux_menu; - } - if (element->component.userid == 0x22) { - memcpy(G_monero_vstate.ux_menu, "Address", 7); - element->text = G_monero_vstate.ux_menu; - } - } - - if (entry == &ui_menu_pubaddr[1]) { - memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)); - if (element->component.userid == 0x21) { - switch (G_monero_vstate.disp_addr_mode) { - case 0: - case DISP_MAIN: - case DISP_SUB: - snprintf(G_monero_vstate.ux_menu, sizeof(G_monero_vstate.ux_menu), "Major: %d", - G_monero_vstate.disp_addr_M); - break; - case DISP_INTEGRATED: - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.payment_id, 8); - break; - } - element->text = G_monero_vstate.ux_menu; - } - if (element->component.userid == 0x22) { - switch (G_monero_vstate.disp_addr_mode) { - case 0: - case DISP_MAIN: - case DISP_SUB: - snprintf(G_monero_vstate.ux_menu, sizeof(G_monero_vstate.ux_menu), "minor: %d", - G_monero_vstate.disp_addr_m); - break; - case DISP_INTEGRATED: - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.payment_id + 8, 8); - break; - } - element->text = G_monero_vstate.ux_menu; - } - element->text = G_monero_vstate.ux_menu; - } - - if (entry == &ui_menu_pubaddr[2]) { - memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)); - if (element->component.userid == 0x21) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 0, 11); - } - if (element->component.userid == 0x22) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 1, 11); - } - element->text = G_monero_vstate.ux_menu; - } - if (entry == &ui_menu_pubaddr[3]) { - memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)); - if (element->component.userid == 0x21) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 2, 11); - } - if (element->component.userid == 0x22) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 3, 11); - } - element->text = G_monero_vstate.ux_menu; - } - if (entry == &ui_menu_pubaddr[4]) { - memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)); - if (element->component.userid == 0x21) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 4, 11); - } - if (element->component.userid == 0x22) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 5, 11); - } - element->text = G_monero_vstate.ux_menu; - } - if (entry == &ui_menu_pubaddr[5]) { - memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)); - if (element->component.userid == 0x21) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 6, 11); - } - if (element->component.userid == 0x22) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 7, 11); - } - element->text = G_monero_vstate.ux_menu; - } - - if (entry == &ui_menu_pubaddr[6]) { - memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)); - if (element->component.userid == 0x21) { - if (G_monero_vstate.disp_addr_mode == DISP_INTEGRATED) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 8, 11); - } else { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 8, 7); - } - } - if (element->component.userid == 0x22) { - if (G_monero_vstate.disp_addr_mode == DISP_INTEGRATED) { - memcpy(G_monero_vstate.ux_menu, G_monero_vstate.ux_address + 11 * 9, 7); - } - } - element->text = G_monero_vstate.ux_menu; - } - - return element; -} - -void ui_menu_pubaddr_action(unsigned int value __attribute__((unused))) { - if (G_monero_vstate.disp_addr_mode) { - monero_io_insert_u16(SW_OK); - monero_io_do(IO_RETURN_AFTER_TX); - } - G_monero_vstate.disp_addr_mode = 0; - G_monero_vstate.disp_addr_M = 0; - G_monero_vstate.disp_addr_m = 0; - ui_menu_main_display_value(0); -} - -void ui_menu_any_pubaddr_display(unsigned int value, unsigned char* pub_view, - unsigned char* pub_spend, unsigned char is_subbadress, - unsigned char* paymanetID) { - monero_base58_public_key(G_monero_vstate.ux_address, pub_view, pub_spend, is_subbadress, - paymanetID); - UX_MENU_DISPLAY(value, ui_menu_pubaddr, ui_menu_pubaddr_preprocessor); -} - -void ui_menu_pubaddr_display(unsigned int value) { - monero_base58_public_key(G_monero_vstate.ux_address, G_monero_vstate.A, G_monero_vstate.B, 0, - NULL); - G_monero_vstate.disp_addr_mode = 0; - G_monero_vstate.disp_addr_M = 0; - G_monero_vstate.disp_addr_m = 0; - UX_MENU_DISPLAY(value, ui_menu_pubaddr, ui_menu_pubaddr_preprocessor); -} - -/* --------------------------------- MAIN UX --------------------------------- */ - -const ux_menu_entry_t ui_menu_main[] = { - {NULL, ui_menu_pubaddr_display, 0, NULL, G_monero_vstate.ux_wallet_account_name, - G_monero_vstate.ux_wallet_public_short_address, 0, 0}, - {ui_menu_settings, NULL, 0, NULL, "Settings", NULL, 0, 0}, - {ui_menu_about, NULL, 0, NULL, "About", NULL, 0, 0}, - {NULL, (void*)os_sched_exit, 0, &C_icon_dashboard, "Quit app", NULL, 50, 29}, - UX_MENU_END}; - -void ui_menu_main_display_value(unsigned int value) { - UX_MENU_DISPLAY(value, ui_menu_main, NULL); -} - -void ui_menu_main_display(void) { - ui_menu_main_display_value(0); -} - -void ui_init(void) { - ui_menu_main_display_value(0); - // setup the first screen changing - UX_CALLBACK_SET_INTERVAL(1000); -} - -void io_seproxyhal_display(const bagl_element_t* element) { - io_seproxyhal_display_default((bagl_element_t*)element); -} - -#endif diff --git a/src/monero_ux_stax.c b/src/monero_ux_stax.c index 3a1d54d..d2c82ba 100644 --- a/src/monero_ux_stax.c +++ b/src/monero_ux_stax.c @@ -14,7 +14,7 @@ * limitations under the License. *****************************************************************************/ -#if defined(UI_STAX) +#ifdef HAVE_NBGL #include "os.h" #include "ux.h" @@ -57,46 +57,14 @@ static void release_context(void) { } } -/* -------------------------------------- LOCK--------------------------------------- */ - -void ui_menu_pinlock_display() { - struct { - bolos_ux_t ux_id; - // length of parameters in the u union to be copied during the syscall - unsigned int len; - union { - struct { - unsigned int cancellable; - } validate_pin; - } u; - - } ux_params; - - os_global_pin_invalidate(); - G_monero_vstate.protocol_barrier = PROTOCOL_LOCKED_UNLOCKABLE; - ux_params.ux_id = BOLOS_UX_VALIDATE_PIN; - ux_params.len = sizeof(ux_params.u.validate_pin); - ux_params.u.validate_pin.cancellable = 0; - os_ux((bolos_ux_params_t*)&ux_params); - ui_menu_main_display(); -} - /* -------------------------------- INFO UX --------------------------------- */ -static void ui_menu_info_action(void) { - if (G_monero_vstate.protocol_barrier == PROTOCOL_LOCKED) { - ui_menu_pinlock_display(); - } else { - ui_menu_main_display(); - } -} - void ui_menu_show_tx_aborted(void) { - nbgl_useCaseStatus("Transaction\ncancelled", false, ui_menu_info_action); + nbgl_useCaseStatus("Transaction\ncancelled", false, ui_menu_main_display); } void ui_menu_show_security_error(void) { - nbgl_useCaseStatus("Security Error", false, ui_menu_info_action); + nbgl_useCaseStatus("Security Error", false, ui_menu_main_display); } /* -------------------------------- OPEN TX UX --------------------------------- */ @@ -409,16 +377,21 @@ void display_account(void) { &transactionContext.tagValueList); } -void ui_menu_any_pubaddr_display(unsigned int value __attribute__((unused)), - unsigned char* pub_view, unsigned char* pub_spend, - unsigned char is_subbadress, unsigned char* paymanetID) { +int ui_menu_any_pubaddr_display(unsigned int value __attribute__((unused)), unsigned char* pub_view, + unsigned char* pub_spend, unsigned char is_subbadress, + unsigned char* paymanetID) { + int error; memset(G_monero_vstate.ux_address, 0, sizeof(G_monero_vstate.ux_address)); - monero_base58_public_key(G_monero_vstate.ux_address, pub_view, pub_spend, is_subbadress, - paymanetID); + error = monero_base58_public_key(G_monero_vstate.ux_address, pub_view, pub_spend, is_subbadress, + paymanetID); + if (error) { + return error; + } nbgl_useCaseReviewStart(&C_Monero_64px, "Review Address", "", "Cancel", display_account, ui_menu_pubaddr_action_cancelled); + return 0; } /* -------------------------------- EXPORT VIEW KEY UX --------------------------------- */ diff --git a/src/monero_ux_stax_menu.c b/src/monero_ux_stax_menu.c index 98d3f7a..b3bba36 100644 --- a/src/monero_ux_stax_menu.c +++ b/src/monero_ux_stax_menu.c @@ -14,7 +14,7 @@ * limitations under the License. *****************************************************************************/ -#if defined(UI_STAX) +#ifdef HAVE_NBGL #include "os.h" #include "ux.h" @@ -37,6 +37,8 @@ #define NB_PAGE_SETTING 3 #define IS_TOUCHABLE true +void __attribute__((noreturn)) app_exit(void); + /* ----------------------------------------------------------------------- */ /* --- Stax UI layout --- */ /* ----------------------------------------------------------------------- */ @@ -49,9 +51,6 @@ typedef struct { static TransactionContext_t transactionContext; -ux_state_t G_ux; -bolos_ux_params_t G_ux_params; - enum { ACCOUNT_TOKEN = FIRST_USER_TOKEN, NETWORK_TOKEN, @@ -85,10 +84,6 @@ static void update_account(void) { G_monero_vstate.disp_addr_m = 0; } -static void exit(void) { - os_sched_exit(-1); -} - static bool settings_navigation_cb(uint8_t page, nbgl_pageContent_t* content) { if (page == 0) { content->type = BARS_LIST; @@ -254,7 +249,7 @@ void ui_menu_main_display(void) { NULL); nbgl_useCaseHomeExt("Monero", &C_Monero_64px, NULL, true, transactionContext.buffer, - display_account, display_settings_menu, exit); + display_account, display_settings_menu, app_exit); } /* --- INIT --- */ diff --git a/tests/monero_client/monero_cmd.py b/tests/monero_client/monero_cmd.py index 3be68f0..f35228d 100644 --- a/tests/monero_client/monero_cmd.py +++ b/tests/monero_client/monero_cmd.py @@ -213,7 +213,7 @@ def prefix_hash_init(self, backend, test_name, firmware, navigator, version: int ]) if firmware.device == "nanos": - instructions = get_nano_review_instructions(2) + instructions = get_nano_review_instructions(1) elif firmware.device.startswith("nano"): instructions = get_nano_review_instructions(1) else: @@ -368,7 +368,7 @@ def validate_prehash_init(self, payload: bytes = struct.pack("B", txntype) + encode_varint(txnfee) if firmware.device == "nanos": - instructions = get_nano_review_instructions(2) + instructions = get_nano_review_instructions(1) elif firmware.device.startswith("nano"): instructions = get_nano_review_instructions(1) else: diff --git a/tests/monero_client/monero_crypto_cmd.py b/tests/monero_client/monero_crypto_cmd.py index 88680dd..eb12aea 100644 --- a/tests/monero_client/monero_crypto_cmd.py +++ b/tests/monero_client/monero_crypto_cmd.py @@ -115,7 +115,7 @@ def display_address(self, test_name, firmware, navigator, derivation: bytes, out ]) if firmware.device == "nanos": - instructions = get_nano_review_instructions(7) + instructions = get_nano_review_instructions(8) elif firmware.device.startswith("nano"): instructions = get_nano_review_instructions(4) else: diff --git a/tests/monero_client/snapshots/nanos/test_display_address/00000.png b/tests/monero_client/snapshots/nanos/test_display_address/00000.png index 4d3eebd..8392c00 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_address/00000.png and b/tests/monero_client/snapshots/nanos/test_display_address/00000.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_address/00001.png b/tests/monero_client/snapshots/nanos/test_display_address/00001.png index 4d8b084..beed0ae 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_address/00001.png and b/tests/monero_client/snapshots/nanos/test_display_address/00001.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_address/00002.png b/tests/monero_client/snapshots/nanos/test_display_address/00002.png index 47edabf..a6026d1 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_address/00002.png and b/tests/monero_client/snapshots/nanos/test_display_address/00002.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_address/00003.png b/tests/monero_client/snapshots/nanos/test_display_address/00003.png index 83b74d9..1dc79da 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_address/00003.png and b/tests/monero_client/snapshots/nanos/test_display_address/00003.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_address/00004.png b/tests/monero_client/snapshots/nanos/test_display_address/00004.png index 4609628..37dbedf 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_address/00004.png and b/tests/monero_client/snapshots/nanos/test_display_address/00004.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_address/00005.png b/tests/monero_client/snapshots/nanos/test_display_address/00005.png index a2dcfc1..6f53639 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_address/00005.png and b/tests/monero_client/snapshots/nanos/test_display_address/00005.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_address/00006.png b/tests/monero_client/snapshots/nanos/test_display_address/00006.png index f82ffd1..d9f596f 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_address/00006.png and b/tests/monero_client/snapshots/nanos/test_display_address/00006.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_address/00007.png b/tests/monero_client/snapshots/nanos/test_display_address/00007.png index c085273..3b1e327 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_address/00007.png and b/tests/monero_client/snapshots/nanos/test_display_address/00007.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_address/00008.png b/tests/monero_client/snapshots/nanos/test_display_address/00008.png index 1018f1a..bb6d52f 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_address/00008.png and b/tests/monero_client/snapshots/nanos/test_display_address/00008.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_address/00009.png b/tests/monero_client/snapshots/nanos/test_display_address/00009.png new file mode 100644 index 0000000..925ee99 Binary files /dev/null and b/tests/monero_client/snapshots/nanos/test_display_address/00009.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_subaddress/00000.png b/tests/monero_client/snapshots/nanos/test_display_subaddress/00000.png index 613d8fb..b4ba079 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_subaddress/00000.png and b/tests/monero_client/snapshots/nanos/test_display_subaddress/00000.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_subaddress/00001.png b/tests/monero_client/snapshots/nanos/test_display_subaddress/00001.png index 9fbb210..f5eefd4 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_subaddress/00001.png and b/tests/monero_client/snapshots/nanos/test_display_subaddress/00001.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_subaddress/00002.png b/tests/monero_client/snapshots/nanos/test_display_subaddress/00002.png index a7b616f..6b9a13d 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_subaddress/00002.png and b/tests/monero_client/snapshots/nanos/test_display_subaddress/00002.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_subaddress/00003.png b/tests/monero_client/snapshots/nanos/test_display_subaddress/00003.png index 95fcf48..3602291 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_subaddress/00003.png and b/tests/monero_client/snapshots/nanos/test_display_subaddress/00003.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_subaddress/00004.png b/tests/monero_client/snapshots/nanos/test_display_subaddress/00004.png index 041858e..571575f 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_subaddress/00004.png and b/tests/monero_client/snapshots/nanos/test_display_subaddress/00004.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_subaddress/00005.png b/tests/monero_client/snapshots/nanos/test_display_subaddress/00005.png index 7c9bca2..11691f5 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_subaddress/00005.png and b/tests/monero_client/snapshots/nanos/test_display_subaddress/00005.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_subaddress/00006.png b/tests/monero_client/snapshots/nanos/test_display_subaddress/00006.png index a8deabf..c47d4d6 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_subaddress/00006.png and b/tests/monero_client/snapshots/nanos/test_display_subaddress/00006.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_subaddress/00007.png b/tests/monero_client/snapshots/nanos/test_display_subaddress/00007.png index c085273..2606d53 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_subaddress/00007.png and b/tests/monero_client/snapshots/nanos/test_display_subaddress/00007.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_subaddress/00008.png b/tests/monero_client/snapshots/nanos/test_display_subaddress/00008.png index 1018f1a..bb6d52f 100644 Binary files a/tests/monero_client/snapshots/nanos/test_display_subaddress/00008.png and b/tests/monero_client/snapshots/nanos/test_display_subaddress/00008.png differ diff --git a/tests/monero_client/snapshots/nanos/test_display_subaddress/00009.png b/tests/monero_client/snapshots/nanos/test_display_subaddress/00009.png new file mode 100644 index 0000000..925ee99 Binary files /dev/null and b/tests/monero_client/snapshots/nanos/test_display_subaddress/00009.png differ diff --git a/tests/monero_client/snapshots/nanos/test_prefix_hash_hash_init/00000.png b/tests/monero_client/snapshots/nanos/test_prefix_hash_hash_init/00000.png index 6e08000..b9a2e0d 100644 Binary files a/tests/monero_client/snapshots/nanos/test_prefix_hash_hash_init/00000.png and b/tests/monero_client/snapshots/nanos/test_prefix_hash_hash_init/00000.png differ diff --git a/tests/monero_client/snapshots/nanos/test_prefix_hash_hash_init/00001.png b/tests/monero_client/snapshots/nanos/test_prefix_hash_hash_init/00001.png index 4b33233..1e284f0 100644 Binary files a/tests/monero_client/snapshots/nanos/test_prefix_hash_hash_init/00001.png and b/tests/monero_client/snapshots/nanos/test_prefix_hash_hash_init/00001.png differ diff --git a/tests/monero_client/snapshots/nanos/test_prefix_hash_hash_init/00002.png b/tests/monero_client/snapshots/nanos/test_prefix_hash_hash_init/00002.png index cb243a7..9c7e704 100644 Binary files a/tests/monero_client/snapshots/nanos/test_prefix_hash_hash_init/00002.png and b/tests/monero_client/snapshots/nanos/test_prefix_hash_hash_init/00002.png differ diff --git a/tests/monero_client/snapshots/nanos/test_private_view_key/00000.png b/tests/monero_client/snapshots/nanos/test_private_view_key/00000.png index 094f812..0384a5a 100644 Binary files a/tests/monero_client/snapshots/nanos/test_private_view_key/00000.png and b/tests/monero_client/snapshots/nanos/test_private_view_key/00000.png differ diff --git a/tests/monero_client/snapshots/nanos/test_private_view_key/00001.png b/tests/monero_client/snapshots/nanos/test_private_view_key/00001.png index 1018f1a..1e284f0 100644 Binary files a/tests/monero_client/snapshots/nanos/test_private_view_key/00001.png and b/tests/monero_client/snapshots/nanos/test_private_view_key/00001.png differ diff --git a/tests/monero_client/snapshots/nanos/test_private_view_key/00002.png b/tests/monero_client/snapshots/nanos/test_private_view_key/00002.png index 4d3eebd..925ee99 100644 Binary files a/tests/monero_client/snapshots/nanos/test_private_view_key/00002.png and b/tests/monero_client/snapshots/nanos/test_private_view_key/00002.png differ diff --git a/tests/monero_client/snapshots/nanos/test_validate_prehash_init/00000.png b/tests/monero_client/snapshots/nanos/test_validate_prehash_init/00000.png index b3351db..56beab6 100644 Binary files a/tests/monero_client/snapshots/nanos/test_validate_prehash_init/00000.png and b/tests/monero_client/snapshots/nanos/test_validate_prehash_init/00000.png differ diff --git a/tests/monero_client/snapshots/nanos/test_validate_prehash_init/00001.png b/tests/monero_client/snapshots/nanos/test_validate_prehash_init/00001.png index fba575a..1e284f0 100644 Binary files a/tests/monero_client/snapshots/nanos/test_validate_prehash_init/00001.png and b/tests/monero_client/snapshots/nanos/test_validate_prehash_init/00001.png differ diff --git a/tests/monero_client/snapshots/nanos/test_validate_prehash_init/00002.png b/tests/monero_client/snapshots/nanos/test_validate_prehash_init/00002.png index a65895a..9c7e704 100644 Binary files a/tests/monero_client/snapshots/nanos/test_validate_prehash_init/00002.png and b/tests/monero_client/snapshots/nanos/test_validate_prehash_init/00002.png differ diff --git a/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00000.png b/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00000.png index d9e8371..5e274cb 100644 Binary files a/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00000.png and b/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00000.png differ diff --git a/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00001.png b/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00001.png index c5849f7..05135fd 100644 Binary files a/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00001.png and b/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00001.png differ diff --git a/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00002.png b/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00002.png index e2c23b7..178c13d 100644 Binary files a/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00002.png and b/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00002.png differ diff --git a/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00003.png b/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00003.png index 53be236..2484877 100644 Binary files a/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00003.png and b/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00003.png differ diff --git a/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00004.png b/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00004.png index 5f6fc30..6146bbd 100644 Binary files a/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00004.png and b/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00004.png differ diff --git a/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00005.png b/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00005.png index fda1a11..145db6e 100644 Binary files a/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00005.png and b/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00005.png differ diff --git a/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00006.png b/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00006.png index 5eebeda..3084b7c 100644 Binary files a/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00006.png and b/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00006.png differ diff --git a/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00007.png b/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00007.png index 9af91ea..1e284f0 100644 Binary files a/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00007.png and b/tests/monero_client/snapshots/nanos/test_validate_prehash_update/00007.png differ diff --git a/tests/monero_client/snapshots/nanox/test_display_address/00001.png b/tests/monero_client/snapshots/nanox/test_display_address/00001.png index 688401e..a074d01 100644 Binary files a/tests/monero_client/snapshots/nanox/test_display_address/00001.png and b/tests/monero_client/snapshots/nanox/test_display_address/00001.png differ diff --git a/tests/monero_client/snapshots/nanox/test_display_address/00002.png b/tests/monero_client/snapshots/nanox/test_display_address/00002.png index fe01a44..224e7fd 100644 Binary files a/tests/monero_client/snapshots/nanox/test_display_address/00002.png and b/tests/monero_client/snapshots/nanox/test_display_address/00002.png differ diff --git a/tests/monero_client/snapshots/nanox/test_display_address/00003.png b/tests/monero_client/snapshots/nanox/test_display_address/00003.png index 74a8caf..c4ba482 100644 Binary files a/tests/monero_client/snapshots/nanox/test_display_address/00003.png and b/tests/monero_client/snapshots/nanox/test_display_address/00003.png differ diff --git a/tests/monero_client/snapshots/nanox/test_display_subaddress/00001.png b/tests/monero_client/snapshots/nanox/test_display_subaddress/00001.png index a135953..ab2a588 100644 Binary files a/tests/monero_client/snapshots/nanox/test_display_subaddress/00001.png and b/tests/monero_client/snapshots/nanox/test_display_subaddress/00001.png differ diff --git a/tests/monero_client/snapshots/nanox/test_display_subaddress/00002.png b/tests/monero_client/snapshots/nanox/test_display_subaddress/00002.png index 2801466..d7e3975 100644 Binary files a/tests/monero_client/snapshots/nanox/test_display_subaddress/00002.png and b/tests/monero_client/snapshots/nanox/test_display_subaddress/00002.png differ diff --git a/tests/monero_client/snapshots/nanox/test_display_subaddress/00003.png b/tests/monero_client/snapshots/nanox/test_display_subaddress/00003.png index d76b9d6..3aa6755 100644 Binary files a/tests/monero_client/snapshots/nanox/test_display_subaddress/00003.png and b/tests/monero_client/snapshots/nanox/test_display_subaddress/00003.png differ diff --git a/tests/monero_client/snapshots/nanox/test_validate_prehash_update/00001.png b/tests/monero_client/snapshots/nanox/test_validate_prehash_update/00001.png index 7f630e3..6204775 100644 Binary files a/tests/monero_client/snapshots/nanox/test_validate_prehash_update/00001.png and b/tests/monero_client/snapshots/nanox/test_validate_prehash_update/00001.png differ diff --git a/tests/monero_client/snapshots/nanox/test_validate_prehash_update/00002.png b/tests/monero_client/snapshots/nanox/test_validate_prehash_update/00002.png index e5c43c5..bac1f06 100644 Binary files a/tests/monero_client/snapshots/nanox/test_validate_prehash_update/00002.png and b/tests/monero_client/snapshots/nanox/test_validate_prehash_update/00002.png differ diff --git a/tests/monero_client/snapshots/stax/test_display_address/00000.png b/tests/monero_client/snapshots/stax/test_display_address/00000.png index b4122df..153d298 100644 Binary files a/tests/monero_client/snapshots/stax/test_display_address/00000.png and b/tests/monero_client/snapshots/stax/test_display_address/00000.png differ diff --git a/tests/monero_client/snapshots/stax/test_display_address/00001.png b/tests/monero_client/snapshots/stax/test_display_address/00001.png index d27964b..a793ded 100644 Binary files a/tests/monero_client/snapshots/stax/test_display_address/00001.png and b/tests/monero_client/snapshots/stax/test_display_address/00001.png differ diff --git a/tests/monero_client/snapshots/stax/test_display_address/00002.png b/tests/monero_client/snapshots/stax/test_display_address/00002.png index c367969..ec01c3d 100644 Binary files a/tests/monero_client/snapshots/stax/test_display_address/00002.png and b/tests/monero_client/snapshots/stax/test_display_address/00002.png differ diff --git a/tests/monero_client/snapshots/stax/test_display_address/00003.png b/tests/monero_client/snapshots/stax/test_display_address/00003.png index d27964b..a793ded 100644 Binary files a/tests/monero_client/snapshots/stax/test_display_address/00003.png and b/tests/monero_client/snapshots/stax/test_display_address/00003.png differ diff --git a/tests/monero_client/snapshots/stax/test_display_address/00004.png b/tests/monero_client/snapshots/stax/test_display_address/00004.png index 53a4fe3..1d12a31 100644 Binary files a/tests/monero_client/snapshots/stax/test_display_address/00004.png and b/tests/monero_client/snapshots/stax/test_display_address/00004.png differ diff --git a/tests/monero_client/snapshots/stax/test_display_address/00005.png b/tests/monero_client/snapshots/stax/test_display_address/00005.png index 96678cb..f59899e 100644 Binary files a/tests/monero_client/snapshots/stax/test_display_address/00005.png and b/tests/monero_client/snapshots/stax/test_display_address/00005.png differ diff --git a/tests/monero_client/snapshots/stax/test_display_address/00006.png b/tests/monero_client/snapshots/stax/test_display_address/00006.png index b2ac4ba..02f4af8 100644 Binary files a/tests/monero_client/snapshots/stax/test_display_address/00006.png and b/tests/monero_client/snapshots/stax/test_display_address/00006.png differ diff --git a/tests/monero_client/snapshots/stax/test_display_subaddress/00000.png b/tests/monero_client/snapshots/stax/test_display_subaddress/00000.png index b4122df..153d298 100644 Binary files a/tests/monero_client/snapshots/stax/test_display_subaddress/00000.png and b/tests/monero_client/snapshots/stax/test_display_subaddress/00000.png differ diff --git a/tests/monero_client/snapshots/stax/test_display_subaddress/00001.png b/tests/monero_client/snapshots/stax/test_display_subaddress/00001.png index 7ab4ba3..5066062 100644 Binary files a/tests/monero_client/snapshots/stax/test_display_subaddress/00001.png and b/tests/monero_client/snapshots/stax/test_display_subaddress/00001.png differ diff --git a/tests/monero_client/snapshots/stax/test_display_subaddress/00002.png b/tests/monero_client/snapshots/stax/test_display_subaddress/00002.png index edfef83..014f3cb 100644 Binary files a/tests/monero_client/snapshots/stax/test_display_subaddress/00002.png and b/tests/monero_client/snapshots/stax/test_display_subaddress/00002.png differ diff --git a/tests/monero_client/snapshots/stax/test_display_subaddress/00003.png b/tests/monero_client/snapshots/stax/test_display_subaddress/00003.png index 7ab4ba3..5066062 100644 Binary files a/tests/monero_client/snapshots/stax/test_display_subaddress/00003.png and b/tests/monero_client/snapshots/stax/test_display_subaddress/00003.png differ diff --git a/tests/monero_client/snapshots/stax/test_display_subaddress/00004.png b/tests/monero_client/snapshots/stax/test_display_subaddress/00004.png index 23ffdf3..4ca0934 100644 Binary files a/tests/monero_client/snapshots/stax/test_display_subaddress/00004.png and b/tests/monero_client/snapshots/stax/test_display_subaddress/00004.png differ diff --git a/tests/monero_client/snapshots/stax/test_display_subaddress/00005.png b/tests/monero_client/snapshots/stax/test_display_subaddress/00005.png index 96678cb..f59899e 100644 Binary files a/tests/monero_client/snapshots/stax/test_display_subaddress/00005.png and b/tests/monero_client/snapshots/stax/test_display_subaddress/00005.png differ diff --git a/tests/monero_client/snapshots/stax/test_display_subaddress/00006.png b/tests/monero_client/snapshots/stax/test_display_subaddress/00006.png index b2ac4ba..02f4af8 100644 Binary files a/tests/monero_client/snapshots/stax/test_display_subaddress/00006.png and b/tests/monero_client/snapshots/stax/test_display_subaddress/00006.png differ diff --git a/tests/monero_client/snapshots/stax/test_prefix_hash_hash_init/00000.png b/tests/monero_client/snapshots/stax/test_prefix_hash_hash_init/00000.png index 0a8b887..cfb9942 100644 Binary files a/tests/monero_client/snapshots/stax/test_prefix_hash_hash_init/00000.png and b/tests/monero_client/snapshots/stax/test_prefix_hash_hash_init/00000.png differ diff --git a/tests/monero_client/snapshots/stax/test_private_view_key/00000.png b/tests/monero_client/snapshots/stax/test_private_view_key/00000.png index d159885..5e2de95 100644 Binary files a/tests/monero_client/snapshots/stax/test_private_view_key/00000.png and b/tests/monero_client/snapshots/stax/test_private_view_key/00000.png differ diff --git a/tests/monero_client/snapshots/stax/test_private_view_key/00001.png b/tests/monero_client/snapshots/stax/test_private_view_key/00001.png index 1023fdc..ebc5b36 100644 Binary files a/tests/monero_client/snapshots/stax/test_private_view_key/00001.png and b/tests/monero_client/snapshots/stax/test_private_view_key/00001.png differ diff --git a/tests/monero_client/snapshots/stax/test_validate_prehash_update/00000.png b/tests/monero_client/snapshots/stax/test_validate_prehash_update/00000.png index 5b24cb3..9096b81 100644 Binary files a/tests/monero_client/snapshots/stax/test_validate_prehash_update/00000.png and b/tests/monero_client/snapshots/stax/test_validate_prehash_update/00000.png differ diff --git a/tests/monero_client/snapshots/stax/test_validate_prehash_update/00001.png b/tests/monero_client/snapshots/stax/test_validate_prehash_update/00001.png index 66176d8..d6aed2f 100644 Binary files a/tests/monero_client/snapshots/stax/test_validate_prehash_update/00001.png and b/tests/monero_client/snapshots/stax/test_validate_prehash_update/00001.png differ diff --git a/tests/monero_client/snapshots/stax/test_validate_prehash_update/00002.png b/tests/monero_client/snapshots/stax/test_validate_prehash_update/00002.png index 2a78db9..9c55ed6 100644 Binary files a/tests/monero_client/snapshots/stax/test_validate_prehash_update/00002.png and b/tests/monero_client/snapshots/stax/test_validate_prehash_update/00002.png differ diff --git a/tests/test_version.py b/tests/test_version.py index f074088..e17d544 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -8,7 +8,7 @@ def check_accepted_version(monero, valid_version: bytes): major, minor, patch = monero.reset_and_get_version( monero_client_version=valid_version ) # type: int, int, int - assert (major, minor, patch) == (1, 8, 2) # version of the Monero app + assert (major, minor, patch) == (1, 9, 0) # version of the Monero app def check_refused_version(monero, invalid_version: bytes):