diff --git a/Makefile b/Makefile
index e60c8af..9978fa8 100644
--- a/Makefile
+++ b/Makefile
@@ -32,11 +32,11 @@ ICONNAME = images/icon_monero.gif
endif
APPVERSION_M=1
-APPVERSION_N=0
-APPVERSION_P=1
+APPVERSION_N=1
+APPVERSION_P=3
APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)
-SPECVERSION="0.x.0"
+SPECVERSION="0.9.0"
DEFINES += $(MONERO_CONFIG) MONERO_VERSION=$(APPVERSION) MONERO_NAME=$(APPNAME) SPEC_VERSION=$(SPECVERSION)
@@ -65,7 +65,7 @@ DEFINES += UNUSED\(x\)=\(void\)x
DEFINES += APPVERSION=\"$(APPVERSION)\"
DEFINES += CUSTOM_IO_APDU_BUFFER_SIZE=\(255+5+64\)
-DEFINES += HAVE_USB_CLASS_CCID
+#DEFINES += HAVE_USB_CLASS_CCID
#DEFINES += IOCRYPT
@@ -94,6 +94,8 @@ CFLAGS += -O3 -Os
AS := $(GCCPATH)arm-none-eabi-gcc
LD := $(GCCPATH)arm-none-eabi-gcc
+SCRIPT_LD:=script.ld
+
#LDFLAGS += -O0 -gdwarf-2 -gstrict-dwarf
LDFLAGS += -O3 -Os
LDLIBS += -lm -lgcc -lc
diff --git a/README.md b/README.md
index d63d183..868fc0d 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,43 @@
Monero wallet application for Ledger Blue and Nano S
-# Revision
+# Revision
+
+## v1.1.3
+
+- Remove rolling address display
+- Allow STEALTH instruction outside TX
+- Doc fix
+
+## v1.1.2
+
+Fix stack overflow for 1.5.5 SDK
+
+## v1.1.1
+
+Allow transaction parsing when screen is locked
+
+## v1.1.0
+
+Initial Release
+
+Targeted Client: Monero 0.13.0.0+
+
+- Security fix: Screen lock management
+- Optimisation: New protocol V2 for future
+- Fix bug in large amount display that was truncated
+- Remove confirmation for zero amount (fake sweep change)
+- Better handling for change address to not display them
+- Dual id (PIN based) management
+- Add onscreen seed words display
+
+
+## v1.0.0
+
+Initial Release
+
+Targeted Client: Monero 0.13.0.0+
+
## v 0.12.4 / Beta 5
@@ -30,7 +66,7 @@ Targeted Client: Monero 0.12.1
## v 0.12.1 / Beta 2
Targeted Client: Monero 0.12.1
-
+
- Add second PIN support
- Remove key storage in NVRAM, always recompute secret key at boot
- Export secret viewkey, with agreement of user, to speed up tx scan
@@ -41,4 +77,4 @@ Targeted Client: Monero 0.12.1
Targeted Client: Monero 0.12.0
-- Initial Beta.
\ No newline at end of file
+- Initial Beta.
diff --git a/doc/user/bolos-app-monero.rst b/doc/user/bolos-app-monero.rst
index a0827ed..a9913b5 100644
--- a/doc/user/bolos-app-monero.rst
+++ b/doc/user/bolos-app-monero.rst
@@ -100,38 +100,17 @@ System Configuration
Linux
~~~~~
-The following packages must be installed: pcsc-tools pcscd libpcsclite1:amd64 .
-
-You have to have to add the NanoS to /etc/libccid_Info.plist
-
- In ifdVendorID add the entry 0x2C97
- In ifdProductID add the entry 0x0001
- In ifdFriendlyName add the entry Ledger Token
-
-These 3 entries must be added at the end of each list.
+TO BE REWRITE FOR HID
MAC
~~~
-The SmartCard service must be installed. See https://smartcardservices.github.io/
-
-1. First it is necessary to [disable SIP](https://developer.apple.com/library/mac/documentation/Security/Conceptual/System_Integrity_Protection_Guide/ConfiguringSystemIntegrityProtection/ConfiguringSystemIntegrityProtection.html) That doesn't allow the editing of files in /usr/.
-
-2. You have to add the Nano S to /usr/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist
-
-
- In ifdVendorID add the entry 0x2C97
- In ifdProductID add the entry 0x0001
- In ifdFriendlyName add the entry Ledger Token
-
-This 3 entries must be added at the end of each list.
-
-3. [Enable SIP](https://developer.apple.com/library/content/documentation/Security/Conceptual/System_Integrity_Protection_Guide/ConfiguringSystemIntegrityProtection/ConfiguringSystemIntegrityProtection.html)
+TO BE REWRITE FOR HID
Windows
~~~~~~~
-SmartCard service should be already installed. Maybe you have to start it.
+TO BE REWRITE FOR HID
diff --git a/script.ld b/script.ld
new file mode 100644
index 0000000..dea1fe5
--- /dev/null
+++ b/script.ld
@@ -0,0 +1,170 @@
+/*******************************************************************************
+* Ledger Blue - Secure firmware
+* (c) 2016, 2017, 2018, 2019 Ledger
+*
+* 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.
+********************************************************************************/
+
+/**
+ * Global chip memory layout and constants
+ *
+ */
+
+MEMORY
+{
+ DISCARD (rwx) : ORIGIN = 0xd0000000, LENGTH = 1M
+
+ FLASH (rx) : ORIGIN = 0xc0d00000, LENGTH = 400K
+ SRAM (rwx) : ORIGIN = 0x20001800, LENGTH = 4K
+}
+
+PAGE_SIZE = 64;
+STACK_SIZE = 768;
+END_STACK = ORIGIN(SRAM) + LENGTH(SRAM);
+
+SECTIONS
+{
+ ENTRY(main)
+
+ /****************************************************************/
+ /* This section locates the code in FLASH */
+ /****************************************************************/
+
+ /** put text in Flash memory, VMA will be equal to LMA */
+ .text :
+ {
+ /* provide start code symbol, shall be zero */
+ _text = .;
+ _nvram = .;
+
+ PROVIDE(_setjmp = setjmp); /*thanks clang*/
+
+ /* ensure main is always @ 0xC0D00000 */
+ *(.boot*)
+
+ /* place the other code and rodata defined BUT nvram variables that are displaced in a r/w area */
+ *(.text*)
+ *(.rodata)
+ *(.rodata.[^N]*) /*.data.rel.ro* not here to detect invalid PIC usage */
+ *(.rodata.N[^_]*)
+
+ . = ALIGN(4);
+
+ /* all code placed */
+ _etext = .;
+
+ . = ALIGN(PAGE_SIZE);
+
+ _nvram_data = .;
+
+ /* NVM data (ex-filesystem) */
+ *(.bss.N_* .rodata.N_*)
+
+ . = ALIGN(PAGE_SIZE);
+ _install_parameters = .;
+ PROVIDE(N_install_parameters = .);
+ _envram = .;
+ _nvram_data_size = _envram - _nvram_data;
+
+ } > FLASH = 0x00
+
+ .data (NOLOAD):
+ {
+ . = ALIGN(4);
+
+ /**
+ * Place RAM initialized variables
+ */
+ _data = .;
+
+ *(vtable)
+ *(.data*)
+
+ _edata = .;
+
+ } > DISCARD /*> SRAM AT>FLASH = 0x00 */
+
+ .bss :
+ {
+ /**
+ * Place RAM uninitialized variables
+ */
+ _bss = .;
+ *(.bss*)
+ _ebss = .;
+
+
+ /**
+ * Reserve stack size
+ */
+ . = ALIGN(4);
+ app_stack_canary = .;
+ PROVIDE(app_stack_canary = .);
+ . += 4;
+ _stack_validation = .;
+ . = _stack_validation + STACK_SIZE;
+ _stack = ABSOLUTE(END_STACK) - STACK_SIZE;
+ PROVIDE( _stack = ABSOLUTE(END_STACK) - STACK_SIZE);
+ _estack = ABSOLUTE(END_STACK);
+ PROVIDE( _estack = ABSOLUTE(END_STACK) );
+
+ } > SRAM = 0x00
+
+ /****************************************************************/
+ /* DEBUG */
+ /****************************************************************/
+
+ /* remove the debugging information from the standard libraries */
+ DEBUG (NOLOAD) :
+ {
+ libc.a ( * )
+ libm.a ( * )
+ libgcc.a ( * )
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ }
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+
+}
diff --git a/src/monero_api.h b/src/monero_api.h
index 91c1e79..c01f33b 100644
--- a/src/monero_api.h
+++ b/src/monero_api.h
@@ -47,6 +47,7 @@ int monero_apdu_get_subaddress_spend_public_key(void);
int monero_apdu_get_subaddress_secret_key(void);
int monero_apdu_open_tx(void);
+void monero_reset_tx(void);
int monero_apdu_open_subtx(void) ;
int monero_apdu_set_signature_mode(void) ;
int monero_apdu_stealth(void);
@@ -162,12 +163,13 @@ int monero_hash(unsigned int algo, cx_hash_t * hasher, unsigned char* buf, unsi
#define monero_sha256_commitment_final(out) \
monero_hash_final((cx_hash_t *)&G_monero_vstate.sha256_commitment, (out)?(out):G_monero_vstate.C)
-#define monero_sha256_amount_init() \
- monero_hash_init_sha256((cx_hash_t *)&G_monero_vstate.sha256_amount)
-#define monero_sha256_amount_update(buf,len) \
- monero_hash_update((cx_hash_t *)&G_monero_vstate.sha256_amount, (buf), (len))
-#define monero_sha256_amount_final(out) \
- monero_hash_final((cx_hash_t *)&G_monero_vstate.sha256_amount, (out)?(out):G_monero_vstate.KV)
+#define monero_sha256_outkeys_init() \
+ monero_hash_init_sha256((cx_hash_t *)&G_monero_vstate.sha256_out_keys)
+#define monero_sha256_outkeys_update(buf,len) \
+ monero_hash_update((cx_hash_t *)&G_monero_vstate.sha256_out_keys, (buf), (len))
+#define monero_sha256_outkeys_final(out) \
+ monero_hash_final((cx_hash_t *)&G_monero_vstate.sha256_out_keys, (out)?(out):G_monero_vstate.OUTK)
+
/**
* LE-7-bits encoding. High bit set says one more byte to decode.
diff --git a/src/monero_blind.c b/src/monero_blind.c
index 5ffbe8f..c0907b9 100644
--- a/src/monero_blind.c
+++ b/src/monero_blind.c
@@ -33,11 +33,6 @@ int monero_apdu_blind() {
monero_io_discard(1);
- //Update Hkv
- monero_sha256_amount_update(AKout,32);
- monero_sha256_amount_update(k,32);
- monero_sha256_amount_update(v,32);
-
//blind mask
monero_hash_to_scalar(AKout, AKout);
monero_addm(k,k,AKout);
diff --git a/src/monero_dispatch.c b/src/monero_dispatch.c
index 4df58b3..25d5aae 100644
--- a/src/monero_dispatch.c
+++ b/src/monero_dispatch.c
@@ -19,32 +19,100 @@
#include "monero_api.h"
#include "monero_vars.h"
-int monero_dispatch() {
- int sw;
+void check_potocol() {
+ /* the first command enforce the protocol version until application quits */
+ switch(G_monero_vstate.io_protocol_version) {
+ case 0x00: /* the first one: PCSC epoch */
+ case 0x02: /* protocol V2 */
+ if (G_monero_vstate.protocol == 0xff) {
+ G_monero_vstate.protocol = G_monero_vstate.io_protocol_version;
+ }
+ if (G_monero_vstate.protocol == G_monero_vstate.io_protocol_version) {
+ break;
+ }
+ //unknown protocol or hot protocol switch is not allowed
+ //FALL THROUGH
- if (os_global_pin_is_validated() != PIN_VERIFIED) {
- THROW(SW_SECURITY_STATUS_NOT_SATISFIED);
- return SW_SECURITY_STATUS_NOT_SATISFIED;
+ default:
+ THROW(SW_CLA_NOT_SUPPORTED);
+ return ;
}
- if (G_monero_vstate.key_set == 0) {
+}
+
+void check_ins_access() {
+
+ if (G_monero_vstate.key_set != 1) {
THROW(SW_CONDITIONS_NOT_SATISFIED);
- return SW_SECURITY_STATUS_NOT_SATISFIED;
+ return;
}
- if ((G_monero_vstate.io_cla != 0x00) && (G_monero_vstate.io_cla != 0x10)) {
- THROW(SW_CLA_NOT_SUPPORTED);
- return SW_CLA_NOT_SUPPORTED;
+ switch (G_monero_vstate.io_ins) {
+ case INS_RESET:
+ case INS_PUT_KEY:
+ case INS_GET_KEY:
+ case INS_VERIFY_KEY:
+ case INS_GET_CHACHA8_PREKEY:
+ case INS_GEN_KEY_DERIVATION:
+ case INS_DERIVATION_TO_SCALAR:
+ case INS_DERIVE_PUBLIC_KEY:
+ case INS_DERIVE_SECRET_KEY:
+ case INS_GEN_KEY_IMAGE:
+ case INS_SECRET_KEY_TO_PUBLIC_KEY:
+ case INS_SECRET_KEY_ADD:
+ case INS_SECRET_KEY_SUB:
+ case INS_GENERATE_KEYPAIR:
+ case INS_SECRET_SCAL_MUL_KEY:
+ case INS_SECRET_SCAL_MUL_BASE:
+ case INS_DERIVE_SUBADDRESS_PUBLIC_KEY:
+ case INS_GET_SUBADDRESS:
+ case INS_GET_SUBADDRESS_SPEND_PUBLIC_KEY:
+ case INS_GET_SUBADDRESS_SECRET_KEY:
+ case INS_MANAGE_SEEDWORDS:
+ case INS_UNBLIND:
+ case INS_STEALTH:
+ return;
+
+ case INS_OPEN_TX:
+ case INS_SET_SIGNATURE_MODE:
+ if (os_global_pin_is_validated() != PIN_VERIFIED) {
+ break;
+ }
+ return;
+
+ case INS_CLOSE_TX:
+ case INS_GEN_TXOUT_KEYS:
+ case INS_BLIND:
+ case INS_VALIDATE:
+ case INS_MLSAG:
+ if ((os_global_pin_is_validated() != PIN_VERIFIED) ||
+ (G_monero_vstate.tx_in_progress != 1)) {
+ break;
+ }
+ return;
}
+ THROW(SW_CONDITIONS_NOT_SATISFIED);
+ return;
+
+}
+
+int monero_dispatch() {
+
+ int sw;
+
+ check_potocol();
+ check_ins_access();
+
if (G_monero_vstate.io_ins == INS_RESET) {
- monero_io_discard(0);
+ monero_init();
return 0x9000;
}
- G_monero_vstate.options = monero_io_fetch_u8();
+ G_monero_vstate.options = monero_io_fetch_u8();
+
sw = 0x6F01;
switch (G_monero_vstate.io_ins) {
@@ -139,6 +207,11 @@ int monero_dispatch() {
sw = monero_apdu_get_subaddress_secret_key();
break;
+ /*--- TX OUT KEYS --- */
+ case INS_GEN_TXOUT_KEYS:
+ sw = monero_apu_generate_txout_keys();
+ break;
+
/* --- BLIND --- */
case INS_BLIND:
sw = monero_apdu_blind();
diff --git a/src/monero_init.c b/src/monero_init.c
index 47cd45e..1b961dd 100644
--- a/src/monero_init.c
+++ b/src/monero_init.c
@@ -38,16 +38,16 @@ void monero_init() {
monero_install(MAINNET);
}
+ G_monero_vstate.protocol = 0xff;
+
//generate key protection
monero_aes_generate(&G_monero_vstate.spk);
//load key
monero_init_private_key();
- monero_ecmul_G(G_monero_vstate.A, G_monero_vstate.a);
- monero_ecmul_G(G_monero_vstate.B, G_monero_vstate.b);
//ux conf
monero_init_ux();
// Let's go!
- G_monero_vstate.state = 42;
+ G_monero_vstate.state = STATE_IDLE;
}
/* ----------------------------------------------------------------------- */
@@ -75,6 +75,7 @@ void monero_init_private_key() {
switch(N_monero_pstate->key_mode) {
case KEY_MODE_SEED:
os_perso_derive_node_bip32(CX_CURVE_SECP256K1, path, 5 , seed, G_monero_vstate.a);
+
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);
diff --git a/src/monero_io.c b/src/monero_io.c
index b0fc142..8c877ff 100644
--- a/src/monero_io.c
+++ b/src/monero_io.c
@@ -334,42 +334,18 @@ int monero_io_fetch_nv(unsigned char* buffer, int len) {
int monero_io_do(unsigned int io_flags) {
- //if pending input chaining
- if (G_monero_vstate.io_cla & 0x01) {
- goto in_chaining;
- }
-
-
+
+ // if IO_ASYNCH_REPLY has been set,
+ // monero_io_exchange will return when IO_RETURN_AFTER_TX will set in ui
if (io_flags & IO_ASYNCH_REPLY) {
- // if IO_ASYNCH_REPLY has been set,
- // monero_io_exchange will return when IO_RETURN_AFTER_TX will set in ui
monero_io_exchange(CHANNEL_APDU | IO_ASYNCH_REPLY, 0);
- } else {
- // --- full out chaining ---
+ }
+ //else send data now
+ else {
G_monero_vstate.io_offset = 0;
- while(G_monero_vstate.io_length > MAX_OUT) {
- unsigned int tx,xx;
- //send chunk
- tx = MAX_OUT-2;
- os_memmove(G_io_apdu_buffer, G_monero_vstate.io_buffer+G_monero_vstate.io_offset, tx);
- G_monero_vstate.io_length -= tx;
- G_monero_vstate.io_offset += tx;
- G_io_apdu_buffer[tx] = 0x61;
- if (G_monero_vstate.io_length > MAX_OUT-2) {
- xx = MAX_OUT-2;
- } else {
- xx = G_monero_vstate.io_length-2;
- }
- G_io_apdu_buffer[tx+1] = xx;
- monero_io_exchange(CHANNEL_APDU, tx+2);
- //check get response
- if ((G_io_apdu_buffer[0] != 0x00) ||
- (G_io_apdu_buffer[1] != 0xc0) ||
- (G_io_apdu_buffer[2] != 0x00) ||
- (G_io_apdu_buffer[3] != 0x00) ) {
- THROW(SW_COMMAND_NOT_ALLOWED);
- return 0;
- }
+ if(G_monero_vstate.io_length > MAX_OUT) {
+ THROW(SW_FILE_FULL);
+ return SW_FILE_FULL;
}
os_memmove(G_io_apdu_buffer, G_monero_vstate.io_buffer+G_monero_vstate.io_offset, G_monero_vstate.io_length);
@@ -377,55 +353,23 @@ int monero_io_do(unsigned int io_flags) {
monero_io_exchange(CHANNEL_APDU |IO_RETURN_AFTER_TX, G_monero_vstate.io_length);
return 0;
} else {
- monero_io_exchange(CHANNEL_APDU, G_monero_vstate.io_length);
+ monero_io_exchange(CHANNEL_APDU, G_monero_vstate.io_length);
}
}
- //--- full in chaining ---
+ //--- set up received data ---
G_monero_vstate.io_offset = 0;
G_monero_vstate.io_length = 0;
- G_monero_vstate.io_cla = G_io_apdu_buffer[0];
+ G_monero_vstate.io_protocol_version = G_io_apdu_buffer[0];
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;
- switch (G_monero_vstate.io_ins) {
-
- case INS_GET_RESPONSE:
- G_monero_vstate.io_le = G_io_apdu_buffer[4];
- break;
-
- default:
- G_monero_vstate.io_lc = G_io_apdu_buffer[4];
- os_memmove(G_monero_vstate.io_buffer, G_io_apdu_buffer+5, G_monero_vstate.io_lc);
- G_monero_vstate.io_length = G_monero_vstate.io_lc;
- break;
- }
-
- while(G_monero_vstate.io_cla & 0x10) {
-
- G_io_apdu_buffer[0] = 0x90;
- G_io_apdu_buffer[1] = 0x00;
- monero_io_exchange(CHANNEL_APDU, 2);
- in_chaining:
- if (((G_io_apdu_buffer[0] & 0xEF) != (G_monero_vstate.io_cla& 0xEF)) ||
- (G_io_apdu_buffer[1] != G_monero_vstate.io_ins) ||
- (G_io_apdu_buffer[2] != G_monero_vstate.io_p1) ||
- (G_io_apdu_buffer[3] != G_monero_vstate.io_p2) ) {
- THROW(SW_COMMAND_NOT_ALLOWED);
- return SW_COMMAND_NOT_ALLOWED;
- }
- G_monero_vstate.io_cla = G_io_apdu_buffer[0];
- G_monero_vstate.io_lc = G_io_apdu_buffer[4];
- if ((G_monero_vstate.io_length + G_monero_vstate.io_lc) > MONERO_IO_BUFFER_LENGTH) {
- return 1;
- }
- os_memmove(G_monero_vstate.io_buffer+G_monero_vstate.io_length, G_io_apdu_buffer+5, G_monero_vstate.io_lc);
- G_monero_vstate.io_length += G_monero_vstate.io_lc;
- }
-
+ G_monero_vstate.io_lc = G_io_apdu_buffer[4];
+ os_memmove(G_monero_vstate.io_buffer, G_io_apdu_buffer+5, G_monero_vstate.io_lc);
+ G_monero_vstate.io_length = G_monero_vstate.io_lc;
return 0;
}
diff --git a/src/monero_key.c b/src/monero_key.c
index 40266e9..1e5d9b7 100644
--- a/src/monero_key.c
+++ b/src/monero_key.c
@@ -610,3 +610,94 @@ int monero_apdu_get_subaddress_secret_key(/*const crypto::secret_key& sec, const
monero_io_insert_encrypt(sub_sec,32);
return SW_OK;
}
+
+
+/* ----------------------------------------------------------------------- */
+/* --- --- */
+/* ----------------------------------------------------------------------- */
+// on device:
+ // if need_additional
+ // if is_subaddress:
+ // additional_pub = tx_sec.Bout
+ // else
+ // additional_pub = tx_sec.G
+ //
+ // if is_change
+ // generate_key_derivation(derivation <- tx_sec/a, R)
+ // else
+ // generate_key_derivation(derivation <- tx_sec, Aout)
+ //
+ // if (tx_version > 1)
+ // derivation_to_scalar(AKout <- derivation, output_index)
+ //
+ // derive_public_key(out_eph_public_key <- derivation, output_index, Bout)
+ //
+ // hash_update(Aout, Bout, AKout, out_eph_public_key)
+ //
+ // return additional_pub, Akout, out_eph_public_key
+
+int monero_apu_generate_txout_keys(/*size_t tx_version, crypto::secret_key tx_sec, crypto::public_key Aout, crypto::public_key Bout, size_t output_index, bool is_change, bool is_subaddress, bool need_additional_key*/) {
+ unsigned int tx_version;
+ unsigned char tx_sec[32];
+ unsigned char Aout[32];
+ unsigned char Bout[32];
+ unsigned int output_index;
+ unsigned char is_change;
+ unsigned char is_subaddress;
+ unsigned char need_additional_key;
+ unsigned char derivation[32];
+
+
+ tx_version = monero_io_fetch_u32();
+ monero_io_fetch_decrypt_key(tx_sec);
+ monero_io_fetch(Aout,32);
+ monero_io_fetch(Bout,32);
+ output_index = monero_io_fetch_u32();
+ is_change = monero_io_fetch_u8();
+ is_subaddress = monero_io_fetch_u8();
+ need_additional_key = monero_io_fetch_u8();
+
+
+
+ //additional pub key
+ monero_io_discard(1);
+
+
+ //update outkeys 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);
+ }
+
+ if (need_additional_key) {
+ if (is_subaddress) {
+ monero_ecmul_k(derivation, Bout, tx_sec);
+ } else {
+ monero_ecmul_G(derivation, tx_sec);
+ }
+ monero_io_insert(derivation,32);
+ }
+
+ //derivation
+ if (is_change) {
+ monero_generate_key_derivation(derivation, G_monero_vstate.R, tx_sec);
+ } else {
+ monero_generate_key_derivation(derivation, Aout, tx_sec);
+ }
+
+ //compute AKout (amount key)
+ monero_derivation_to_scalar(tx_sec, derivation, output_index);
+ if (G_monero_vstate.io_protocol_version == 2) {
+ monero_sha256_outkeys_update(tx_sec,32);
+ }
+ monero_io_insert_encrypt(tx_sec,32);
+
+
+ //compute ephemeral output key
+ monero_derive_public_key(tx_sec, derivation, output_index, Bout);
+ monero_io_insert(tx_sec,32);
+ return SW_OK;
+}
+
+
diff --git a/src/monero_main.c b/src/monero_main.c
index f09a9ea..c1d326e 100644
--- a/src/monero_main.c
+++ b/src/monero_main.c
@@ -45,6 +45,7 @@ void monero_main(void) {
}
CATCH_OTHER(e) {
monero_io_discard(1);
+ monero_reset_tx();
if ( (e & 0xFFFF0000) ||
( ((e&0xF000)!=0x6000) && ((e&0xF000)!=0x9000) ) ) {
monero_io_insert_u32(e);
@@ -117,7 +118,8 @@ unsigned char io_event(unsigned char channel) {
if (s_after == PIN_VERIFIED) {
monero_init_private_key();
} else {
- monero_wipe_private_key();
+ ;//do nothing, allowing TX parsing in lock mode
+ //monero_wipe_private_key();
}
}
diff --git a/src/monero_open_tx.c b/src/monero_open_tx.c
index 99435f2..03a7bc1 100644
--- a/src/monero_open_tx.c
+++ b/src/monero_open_tx.c
@@ -20,6 +20,19 @@
#include "monero_vars.h"
+/* ----------------------------------------------------------------------- */
+/* --- --- */
+/* ----------------------------------------------------------------------- */
+void monero_reset_tx() {
+ os_memset(G_monero_vstate.r, 0, 32);
+ os_memset(G_monero_vstate.R, 0, 32);
+ monero_keccak_init_H();
+ monero_sha256_commitment_init();
+ monero_sha256_outkeys_init();
+ G_monero_vstate.tx_in_progress = 0;
+ }
+
+
/* ----------------------------------------------------------------------- */
/* --- --- */
/* ----------------------------------------------------------------------- */
@@ -31,13 +44,11 @@ int monero_apdu_open_tx() {
unsigned int account;
- //monero_sha256_commitment_init();
- monero_sha256_amount_init();
-
account = monero_io_fetch_u32();
monero_io_discard(1);
-
+
+ monero_reset_tx();
monero_rng(G_monero_vstate.r,32);
monero_reduce(G_monero_vstate.r, G_monero_vstate.r);
monero_ecmul_G(G_monero_vstate.R, G_monero_vstate.r);
@@ -47,6 +58,7 @@ int monero_apdu_open_tx() {
#ifdef DEBUG_HWDEVICE
monero_io_insert(G_monero_vstate.r,32);
#endif
+ G_monero_vstate.tx_in_progress = 1;
return SW_OK;
}
#undef OPTION_KEEP_r
@@ -55,7 +67,9 @@ int monero_apdu_open_tx() {
/* --- --- */
/* ----------------------------------------------------------------------- */
int monero_apdu_close_tx() {
- monero_io_discard(0);
+ monero_io_discard(1);
+ monero_reset_tx();
+ G_monero_vstate.tx_in_progress = 0;
return SW_OK;
}
@@ -66,11 +80,7 @@ int monero_apdu_close_tx() {
* Sub dest address not yet supported: P1 = 2 not supported
*/
int monero_abort_tx() {
- os_memset(G_monero_vstate.r, 0, 32);
- os_memset(G_monero_vstate.R, 0, 32);
- monero_keccak_init_H();
- monero_sha256_commitment_init();
- monero_sha256_amount_init();
+ monero_reset_tx();
return 0;
}
diff --git a/src/monero_prehash.c b/src/monero_prehash.c
index e202e6d..fd49790 100644
--- a/src/monero_prehash.c
+++ b/src/monero_prehash.c
@@ -29,8 +29,8 @@
/* ----------------------------------------------------------------------- */
int monero_apdu_mlsag_prehash_init() {
if (G_monero_vstate.io_p2 == 1) {
- monero_sha256_amount_final(NULL);
- monero_sha256_amount_init();
+ monero_sha256_outkeys_final(NULL);
+ monero_sha256_outkeys_init();
monero_sha256_commitment_init();
monero_keccak_init_H();
}
@@ -56,46 +56,58 @@ int monero_apdu_mlsag_prehash_init() {
/* ----------------------------------------------------------------------- */
int monero_apdu_mlsag_prehash_update() {
unsigned char is_subaddress;
- unsigned char Aout[32];
- unsigned char Bout[32];
- #define aH Aout
- #define kG Bout
- #define AKout Aout
- unsigned char C[32];
- unsigned char v[32];
- unsigned char k[32];
- int changed;
- changed = 0;
-
+ unsigned char *Aout;
+ unsigned char *Bout;
+ unsigned char is_change;
+ unsigned char AKout[32];
+ unsigned char *C;
+ unsigned char *v;
+ unsigned char *k;
+
+ unsigned char aH[32];
+ unsigned char kG[32];
+
+
+
+ //fetch destination
is_subaddress = monero_io_fetch_u8();
- monero_io_fetch(Aout,32);
- monero_io_fetch(Bout,32);
+ if (G_monero_vstate.io_protocol_version == 2) {
+ is_change = monero_io_fetch_u8();
+ } else {
+ is_change = 0;
+ }
+ Aout = G_monero_vstate.io_buffer+G_monero_vstate.io_offset; monero_io_fetch(NULL,32);
+ Bout = G_monero_vstate.io_buffer+G_monero_vstate.io_offset; monero_io_fetch(Bout,32);
+ /*AKout = G_monero_vstate.io_buffer+G_monero_vstate.io_offset;*/ monero_io_fetch_decrypt(AKout,32);
+ C = G_monero_vstate.io_buffer+G_monero_vstate.io_offset; monero_io_fetch(NULL, 32);
+ k = G_monero_vstate.io_buffer+G_monero_vstate.io_offset; monero_io_fetch(NULL, 32);
+ v = G_monero_vstate.io_buffer+G_monero_vstate.io_offset; monero_io_fetch(NULL, 32);
+
+ monero_io_discard(0);
+
+ 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);
+ }
+
if (G_monero_vstate.sig_mode == TRANSACTION_CREATE_REAL) {
- if (os_memcmp(Aout, G_monero_vstate.A, 32) || os_memcmp(Bout, G_monero_vstate.B, 32) ) {
+ if ((os_memcmp(Aout, G_monero_vstate.A, 32) == 0) && (os_memcmp(Bout, G_monero_vstate.B, 32) == 0)) {
+ is_change = 1;
+ }
+ if (is_change == 0) {
//encode dest adress
monero_base58_public_key(&G_monero_vstate.ux_address[0], Aout, Bout, is_subaddress);
- } else {
- changed = 1;
}
}
- monero_io_fetch_decrypt(AKout,32);
- monero_io_fetch(C,32);
- monero_io_fetch(k,32);
- monero_io_fetch(v,32);
-
- monero_io_discard(1);
-
+
//update MLSAG prehash
monero_keccak_update_H(k,32);
monero_keccak_update_H(v,32);
- //unblind amount, mask and update amount hash control
- monero_sha256_amount_update(AKout,32);
- monero_unblind(v,k, AKout);
- monero_sha256_amount_update(k, 32);
- monero_sha256_amount_update(v, 32);
-
//check C = aH+kG
+ monero_unblind(v,k, AKout);
monero_ecmul_G(kG, k);
if (!cx_math_is_zero(v, 32)) {
monero_ecmul_H(aH, v);
@@ -106,15 +118,17 @@ int monero_apdu_mlsag_prehash_update() {
if (os_memcmp(C, k, 32)) {
THROW(SW_SECURITY_COMMITMENT_CONTROL);
}
-
//update commitment hash control
monero_sha256_commitment_update(C,32);
- if ((G_monero_vstate.options & IN_OPTION_MORE_COMMAND)==0) {
- //finalize and check amount hash_control
- monero_sha256_amount_final(k);
- if (os_memcmp(k, G_monero_vstate.KV, 32)) {
- THROW(SW_SECURITY_AMOUNT_CHAIN_CONTROL);
+
+ if ((G_monero_vstate.options & IN_OPTION_MORE_COMMAND)==0) {
+ if (G_monero_vstate.io_protocol_version == 2) {
+ //finalize and check outkeys hash_control
+ monero_sha256_outkeys_final(k);
+ if (os_memcmp(k, G_monero_vstate.OUTK, 32)) {
+ THROW(SW_SECURITY_OUTKEYS_CHAIN_CONTROL);
+ }
}
//finalize commitment hash control
monero_sha256_commitment_final(NULL);
@@ -125,7 +139,7 @@ int monero_apdu_mlsag_prehash_update() {
//ask user
uint64_t amount;
amount = monero_bamount2uint64(v);
- if (!changed && amount) {
+ if (!is_change && amount) {
monero_amount2str(amount, G_monero_vstate.ux_amount, 15);
ui_menu_validation_display(0);
return 0;
diff --git a/src/monero_types.h b/src/monero_types.h
index bcec891..4016a58 100644
--- a/src/monero_types.h
+++ b/src/monero_types.h
@@ -96,13 +96,14 @@ enum device_mode {
struct monero_v_state_s {
unsigned char state;
+ unsigned char protocol;
/* ------------------------------------------ */
/* --- IO --- */
/* ------------------------------------------ */
/* io state*/
- unsigned char io_cla;
+ unsigned char io_protocol_version;
unsigned char io_ins;
unsigned char io_p1;
unsigned char io_p2;
@@ -126,18 +127,18 @@ struct monero_v_state_s {
/* ------------------------------------------ */
/* --- Crypo --- */
/* ------------------------------------------ */
-
unsigned char a[32];
unsigned char A[32];
unsigned char b[32];
unsigned char B[32];
-
+
/* SPK */
cx_aes_key_t spk;
/* Tx state machine */
struct {
unsigned char key_set:1;
+ unsigned int tx_in_progress: 1;
unsigned int tx_state: 4;
};
@@ -153,8 +154,8 @@ struct monero_v_state_s {
unsigned char c[32];
/* -- track tx-in/out and commitment -- */
- cx_sha256_t sha256_amount;
- unsigned char KV[32];
+ cx_sha256_t sha256_out_keys;
+ unsigned char OUTK[32];
cx_sha256_t sha256_commitment;
unsigned char C[32];
@@ -183,6 +184,9 @@ typedef struct monero_v_state_s monero_v_state_t;
#define SIZEOF_TX_VSTATE (sizeof(monero_v_state_t) - OFFSETOF(monero_v_state_t, state))
+
+#define STATE_IDLE 0xC0
+
/* --- ... --- */
#define IO_OFFSET_END (unsigned int)-1
#define IO_OFFSET_MARK (unsigned int)-2
@@ -229,6 +233,7 @@ typedef struct monero_v_state_s monero_v_state_t;
#define INS_STEALTH 0x76
#define INS_BLIND 0x78
#define INS_UNBLIND 0x7A
+#define INS_GEN_TXOUT_KEYS 0x7B
#define INS_VALIDATE 0x7C
#define INS_MLSAG 0x7E
#define INS_CLOSE_TX 0x80
@@ -275,6 +280,7 @@ typedef struct monero_v_state_s monero_v_state_t;
#define SW_SECURITY_COMMITMENT_CONTROL 0x6911
#define SW_SECURITY_AMOUNT_CHAIN_CONTROL 0x6912
#define SW_SECURITY_COMMITMENT_CHAIN_CONTROL 0x6913
+#define SW_SECURITY_OUTKEYS_CHAIN_CONTROL 0x6914
#define SW_SECURITY_STATUS_NOT_SATISFIED 0x6982
#define SW_FILE_INVALID 0x6983
diff --git a/src/monero_ux_nanos.c b/src/monero_ux_nanos.c
index 5e1371a..8fcdacf 100644
--- a/src/monero_ux_nanos.c
+++ b/src/monero_ux_nanos.c
@@ -43,10 +43,6 @@ const bagl_element_t* ui_menu_main_preprocessor(const ux_menu_entry_t* entry, ba
void ui_menu_settings_display(unsigned int value);
/* ------------------------------- Helpers UX ------------------------------- */
-void ui_CCID_reset(void) {
- io_usb_ccid_set_card_inserted(0);
- io_usb_ccid_set_card_inserted(1);
-}
/*
void ui_info(const char* msg1, const char* msg2, const void *menu_display, unsigned int value) {
os_memset(&G_monero_vstate.ui_dogsays[0], 0, sizeof(ux_menu_entry_t));
@@ -76,7 +72,7 @@ const bagl_element_t* ui_menu_fee_validation_preprocessor(const ux_menu_entry_t*
/* --- Amount --- */
if (entry == &ui_menu_fee_validation[0]) {
- if(element->component.userid==0x22) {
+ if(element->component.userid==0x22) {
element->text = G_monero_vstate.ux_amount;
}
}
@@ -91,7 +87,7 @@ void ui_menu_fee_validation_action(unsigned int value) {
sw = SW_SECURITY_STATUS_NOT_SATISFIED;
monero_abort_tx();
}
- monero_io_insert_u16(sw);
+ monero_io_insert_u16(sw);
monero_io_do(IO_RETURN_AFTER_TX);
ui_menu_main_display(0);
}
@@ -125,12 +121,12 @@ const ux_menu_entry_t ui_menu_words[] = {
const bagl_element_t* ui_menu_words_preprocessor(const ux_menu_entry_t* entry, bagl_element_t* element) {
if ((entry->userid >= 0) && (entry->userid <25)) {
-
- if(element->component.userid==0x21) {
+
+ if(element->component.userid==0x21) {
element->text = N_monero_pstate->words[entry->userid];
}
-
- if ((element->component.userid==0x22)&&(entry->userid<24)) {
+
+ if ((element->component.userid==0x22)&&(entry->userid<24)) {
element->text = N_monero_pstate->words[entry->userid+1];
}
}
@@ -167,14 +163,14 @@ const bagl_element_t* ui_menu_validation_preprocessor(const ux_menu_entry_t* ent
/* --- Amount --- */
if (entry == &ui_menu_validation[0]) {
- if(element->component.userid==0x22) {
+ if(element->component.userid==0x22) {
element->text = G_monero_vstate.ux_amount;
}
}
#if 0
/* --- Fees --- */
if (entry == &ui_menu_validation[1]) {
- if(element->component.userid==0x22) {
+ if(element->component.userid==0x22) {
element->text = G_monero_vstate.ux_fees;
}
}
@@ -182,7 +178,7 @@ const bagl_element_t* ui_menu_validation_preprocessor(const ux_menu_entry_t* ent
/* --- Destination --- */
if (entry == &ui_menu_validation[1]) {
- if(element->component.userid==0x22) {
+ if(element->component.userid==0x22) {
os_memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)) ;
os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*0, 11);
element->text = G_monero_vstate.ux_menu;
@@ -190,40 +186,40 @@ const bagl_element_t* ui_menu_validation_preprocessor(const ux_menu_entry_t* ent
}
if (entry == &ui_menu_validation[2]) {
os_memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)) ;
- if(element->component.userid==0x21) {
- os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*1, 11);
+ if(element->component.userid==0x21) {
+ os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*1, 11);
}
- if(element->component.userid==0x22) {
+ if(element->component.userid==0x22) {
os_memmove(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]) {
os_memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)) ;
- if(element->component.userid==0x21) {
- os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*3, 11);
+ if(element->component.userid==0x21) {
+ os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*3, 11);
}
- if(element->component.userid==0x22) {
+ if(element->component.userid==0x22) {
os_memmove(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]) {
os_memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)) ;
- if(element->component.userid==0x21) {
- os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*5, 11);
+ if(element->component.userid==0x21) {
+ os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*5, 11);
}
- if(element->component.userid==0x22) {
+ if(element->component.userid==0x22) {
os_memmove(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]) {
os_memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)) ;
- if(element->component.userid==0x21) {
- os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*7, 11);
+ if(element->component.userid==0x21) {
+ os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*7, 11);
}
- if(element->component.userid==0x22) {
+ if(element->component.userid==0x22) {
os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*8, 7);
}
element->text = G_monero_vstate.ux_menu;
@@ -244,7 +240,7 @@ void ui_menu_validation_action(unsigned int value) {
sw = SW_SECURITY_STATUS_NOT_SATISFIED;
monero_abort_tx();
}
- monero_io_insert_u16(sw);
+ monero_io_insert_u16(sw);
monero_io_do(IO_RETURN_AFTER_TX);
ui_menu_main_display(0);
}
@@ -257,41 +253,41 @@ unsigned int ui_export_viewkey_button(unsigned int button_mask, unsigned int but
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,
- 0,
- 0, 0,
+ // 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,
+ 0,
+ 0, 0,
NULL, NULL, NULL},
- { {BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS },
- NULL,
- 0,
- 0, 0,
+ { {BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS },
+ NULL,
+ 0,
+ 0, 0,
NULL, NULL, NULL },
-
- { {BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK },
- NULL,
- 0,
- 0, 0,
+
+ { {BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK },
+ NULL,
+ 0,
+ 0, 0,
NULL, NULL, NULL },
- { {BAGL_LABELINE, 0x01, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 },
- G_monero_vstate.ux_menu,
- 0,
- 0, 0,
+ { {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,
+ 0,
+ 0, 0,
NULL, NULL, NULL },
-
- { {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,
- 0,
- 0, 0,
+
+ { {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,
+ 0,
+ 0, 0,
NULL, NULL, NULL },
-
+
};
void ui_export_viewkey_display(unsigned int value) {
- UX_DISPLAY(ui_export_viewkey, (void*)ui_export_viewkey_prepro);
+ UX_DISPLAY(ui_export_viewkey, (void*)ui_export_viewkey_prepro);
}
unsigned int ui_export_viewkey_prepro(const bagl_element_t* element) {
@@ -306,7 +302,7 @@ unsigned int ui_export_viewkey_prepro(const bagl_element_t* element) {
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) {
unsigned int sw;
unsigned char x[32];
@@ -314,19 +310,19 @@ unsigned int ui_export_viewkey_button(unsigned int button_mask, unsigned int but
monero_io_discard(0);
os_memset(x,0,32);
sw = 0x9000;
-
+
switch(button_mask) {
case BUTTON_EVT_RELEASED|BUTTON_LEFT: // CANCEL
- monero_io_insert(x, 32);
+ monero_io_insert(x, 32);
break;
case BUTTON_EVT_RELEASED|BUTTON_RIGHT: // OK
monero_io_insert(G_monero_vstate.a, 32);
#ifdef DEBUG_HWDEVICE
- monero_io_insert(G_monero_vstate.b, 32);
+ monero_io_insert(G_monero_vstate.b, 32);
#endif
break;
-
+
default:
return 0;
}
@@ -348,7 +344,7 @@ const ux_menu_entry_t ui_menu_network[] = {
};
const bagl_element_t* ui_menu_network_preprocessor(const ux_menu_entry_t* entry, bagl_element_t* element) {
- os_memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu));
+ os_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)) {
os_memmove(G_monero_vstate.ux_menu, "Test Network ", 14);
G_monero_vstate.ux_menu[13] = '+';
@@ -426,29 +422,98 @@ const ux_menu_entry_t ui_menu_info[] = {
#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, "XMR", "?addr.1?", 0, 0},
+ {NULL, NULL, 4, NULL, "?addr.2?", "?addr.2?", 0, 0},
+ {NULL, NULL, 5, NULL, "?addr.3?", "?addr.3?", 0, 0},
+ {NULL, NULL, 6, NULL, "?addr.4?", "?addr.4?", 0, 0},
+ {NULL, NULL, 7, NULL, "?addr.5?", "?addr.5?", 0, 0},
+ {NULL, ui_menu_main_display, 0, &C_badge_back, "Back", 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]) {
+ if(element->component.userid==0x22) {
+ os_memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)) ;
+ os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*0, 11);
+ element->text = G_monero_vstate.ux_menu;
+ }
+ }
+ if (entry == &ui_menu_pubaddr[1]) {
+ os_memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)) ;
+ if(element->component.userid==0x21) {
+ os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*1, 11);
+ }
+ if(element->component.userid==0x22) {
+ os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*2, 11);
+ }
+ element->text = G_monero_vstate.ux_menu;
+ }
+ if (entry == &ui_menu_pubaddr[2]) {
+ os_memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)) ;
+ if(element->component.userid==0x21) {
+ os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*3, 11);
+ }
+ if(element->component.userid==0x22) {
+ os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*4, 11);
+ }
+ element->text = G_monero_vstate.ux_menu;
+ }
+ if (entry == &ui_menu_pubaddr[3]) {
+ os_memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)) ;
+ if(element->component.userid==0x21) {
+ os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*5, 11);
+ }
+ if(element->component.userid==0x22) {
+ os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*6, 11);
+ }
+ element->text = G_monero_vstate.ux_menu;
+ }
+ if (entry == &ui_menu_pubaddr[4]) {
+ os_memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu)) ;
+ if(element->component.userid==0x21) {
+ os_memmove(G_monero_vstate.ux_menu, G_monero_vstate.ux_address+11*7, 11);
+ }
+ if(element->component.userid==0x22) {
+ os_memmove(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_pubaddr_display(unsigned int value) {
+ monero_base58_public_key(G_monero_vstate.ux_address, G_monero_vstate.A,G_monero_vstate.B, 0);
+ UX_MENU_DISPLAY(value, ui_menu_pubaddr, ui_menu_pubaddr_preprocessor);
+}
+
/* --------------------------------- MAIN UX --------------------------------- */
const ux_menu_entry_t ui_menu_main[] = {
- {NULL, NULL, 0, NULL, "", NULL, 0, 0},
+ {NULL, ui_menu_pubaddr_display, 0, NULL, "XWP", "", 0, 0},
{ui_menu_settings, NULL, 0, NULL, "Settings", NULL, 0, 0},
{ui_menu_info, NULL, 0, NULL, "About", NULL, 0, 0},
{NULL, os_sched_exit, 0, &C_icon_dashboard, "Quit app" , NULL, 50, 29},
UX_MENU_END
};
-extern const uint8_t N_USBD_CfgDesc[];
+
const bagl_element_t* ui_menu_main_preprocessor(const ux_menu_entry_t* entry, bagl_element_t* element) {
if (entry == &ui_menu_main[0]) {
- if(element->component.userid==0x20) {
+ if(element->component.userid==0x22) {
os_memset(G_monero_vstate.ux_menu, 0, sizeof(G_monero_vstate.ux_menu));
- os_memmove(G_monero_vstate.ux_menu, "< Swap: ", 8);
- monero_base58_public_key(G_monero_vstate.ux_menu+8, G_monero_vstate.A,G_monero_vstate.B, 0);
- G_monero_vstate.ux_menu[8+98+0] = ' ';
- G_monero_vstate.ux_menu[8+98+1] = '>';
-
- element->component.stroke = 10; // 1 second stop in each way
- element->component.icon_id = 48; // roundtrip speed in pixel/s
+ monero_base58_public_key(G_monero_vstate.ux_menu, G_monero_vstate.A,G_monero_vstate.B, 0);
+ os_memset(G_monero_vstate.ux_menu+5,'.',2);
+ os_memmove(G_monero_vstate.ux_menu+7, G_monero_vstate.ux_menu+95-5,5);
+ G_monero_vstate.ux_menu[12] = 0;
element->text = G_monero_vstate.ux_menu;
- UX_CALLBACK_SET_INTERVAL(bagl_label_roundtrip_duration_ms(element, 7));
}
}
return element;
diff --git a/tools/python/README.md b/tools/python/README.md
index e1e9dae..fa6b200 100644
--- a/tools/python/README.md
+++ b/tools/python/README.md
@@ -19,11 +19,11 @@ The following python package are required:
- Ecpy
- pycrytodome
- ledgerblue
-
- pip3 install pycryptodomex
- pip3 install ECPy
- pip3 install ledgerblue
-
+```
+ pip3 install pycryptodomex
+ pip3 install ECPy
+ pip3 install ledgerblue
+```
### Usage
In tools/python/ directory:
diff --git a/tools/python/src/ledger/monero/seedconv.py b/tools/python/src/ledger/monero/seedconv.py
index 1b88ef0..960eaaa 100644
--- a/tools/python/src/ledger/monero/seedconv.py
+++ b/tools/python/src/ledger/monero/seedconv.py
@@ -24,7 +24,7 @@
from ecpy import curves
from Cryptodome.Hash import keccak
-from ledgerblue.comm import getDongle
+
from .dictionaries.languages import monero_langs
@@ -35,6 +35,7 @@
MAJOR = 0
MINOR = 9
+DEBUG=False
def usage(c):
print('''
@@ -55,7 +56,8 @@ def banner():
'''%(MAJOR,MINOR))
def printdbg(*args):
- print(*args)
+ if DEBUG:
+ print(*args)
return
def error(msg):
@@ -302,7 +304,7 @@ def get_online_seed(lang):
send_dict_chunk(dongle,lang['prefix_length'], chunk, start, cnt)
print()
print("Done.")
- print("Your key words are avalaible on your device under 'Settings/Show keyword' menu.")
+ print("Your key words are avalaible on your device under 'Settings/Show 25 words' menu.")
print("You can delete it at the end of keyword list.")
def clear_online_seed(lang):
@@ -351,6 +353,7 @@ def max_wlen():
usage(0)
if sys.argv[1] == "online":
+ from ledgerblue.comm import getDongle
get_online_seed(retrieve_language(True))
elif sys.argv[1] == "offline":
get_offline_seed(retrieve_language(False))