Skip to content

Commit

Permalink
Fix BSS handling in SWAP mode
Browse files Browse the repository at this point in the history
Split swap features in several files
Reuse SWAP interface from SDK
Add a modal on Stax startup in SWAP mode
Return signing status to Exchange after a SWAP completion
Remove global hdPath usage in CHECK_ADDRESS
Improve security against double signing attempts
  • Loading branch information
fbeutin-ledger committed Oct 3, 2023
1 parent d98f2eb commit 44c3fb9
Show file tree
Hide file tree
Showing 12 changed files with 493 additions and 424 deletions.
14 changes: 11 additions & 3 deletions app/src/apdu_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

static bool tx_initialized = false;

void extractHDPath(uint32_t rx, uint32_t offset) {
static void extractHDPath(uint32_t rx, uint32_t offset) {
tx_initialized = false;

if ((rx - offset) < sizeof(uint32_t) * HDPATH_LEN_DEFAULT) {
Expand Down Expand Up @@ -175,7 +175,6 @@ __Z_INLINE void handleSign(volatile uint32_t *flags, volatile uint32_t *tx, uint
switch (key_type) {
case key_ed25519: {
if (G_swap_state.called_from_swap) {
G_swap_state.should_exit = 1;
app_sign_ed25519();
} else {
view_review_init(tx_getItem, tx_getNumItems, app_sign_ed25519);
Expand All @@ -191,7 +190,6 @@ __Z_INLINE void handleSign(volatile uint32_t *flags, volatile uint32_t *tx, uint
THROW(APDU_CODE_DATA_INVALID);
}
if (G_swap_state.called_from_swap) {
G_swap_state.should_exit = 1;
app_return_sr25519();
} else {
view_review_init(tx_getItem, tx_getNumItems, app_return_sr25519);
Expand Down Expand Up @@ -329,6 +327,16 @@ void handleApdu(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) {
}
FINALLY
{
#ifdef HAVE_SWAP
if (G_swap_state.called_from_swap && G_swap_state.should_exit) {
// Swap checking failed, send reply now and exit, don't wait next cycle
if (sw != 0) {
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, *tx);
}
// Go back to exchange and report our status
finalize_exchange_sign_transaction(sw == 0);
}
#endif
}
}
END_TRY;
Expand Down
90 changes: 69 additions & 21 deletions app/src/common/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
#include "app_main.h"
#include "view.h"
#include "swap.h"
#include "lib_standard_app/swap_lib_calls.h"

#include <os_io_seproxyhal.h>

// Helper to quit the application in a limited THROW context
static void app_exit(void) {
BEGIN_TRY_L(exit) {
TRY_L(exit) {
Expand All @@ -31,38 +33,84 @@ static void app_exit(void) {
END_TRY_L(exit);
}

// Helper to handle the different library commands
static void library_main(libargs_t *args) {
BEGIN_TRY {
TRY {
switch (args->command) {
case SIGN_TRANSACTION: {
// Backup up transaction parameters and wipe BSS to avoid collusion with
// app-exchange BSS data.
bool success = copy_transaction_parameters(args->create_transaction);
if (success) {
// BSS was wiped, we can now init these globals
G_swap_state.called_from_swap = true;
G_swap_state.should_exit = false;

#ifdef HAVE_NBGL
// On Stax, display a modal
nbgl_useCaseSpinner("Signing");
#endif // HAVE_NBGL

view_init();
app_init();
app_main();
}
break;
}
case CHECK_ADDRESS:
handle_check_address(args->check_address);
break;
case GET_PRINTABLE_AMOUNT:
handle_get_printable_amount(args->get_printable_amount);
break;
default:
break;
}
}
CATCH_OTHER(e)
{
}
FINALLY
{
os_lib_end();
}
}
END_TRY;
}

__attribute__((section(".boot"))) int
main(int arg0) {
// exit critical section
__asm volatile("cpsie i");

view_init();
os_boot();

if (arg0) {
libargs_s *args = (libargs_s *) arg0;
if (arg0 != 0) {
// The app has been started in library mode
libargs_t *args = (libargs_t *) arg0;
if (args->id != 0x100) {
// Invalid mode ID
app_exit();
return 0;
}

swap_handle_command(args);
if (!G_swap_state.called_from_swap) {
os_lib_end();
} else {
library_main(args);
}
}

BEGIN_TRY
{
TRY
} else {
// The app has been launched from the dashboard
G_swap_state.called_from_swap = false;
BEGIN_TRY
{
app_init();
app_main();
TRY
{
view_init();
app_init();
app_main();
}
CATCH_OTHER(e)
{}
FINALLY
{}
}
CATCH_OTHER(e)
{}
FINALLY
{}
END_TRY;
}
END_TRY;
}
9 changes: 9 additions & 0 deletions app/src/common/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,15 @@ const char *tx_parse() {

// If in swap mode, compare swap tx parameters with stored info.
if (G_swap_state.called_from_swap) {
if (G_swap_state.should_exit == 1) {
// Safety against trying to make the app sign multiple TX
// This panic quit is a failsafe that should never trigger, as the app is supposed to
// exit after the first send when started in swap mode
os_sched_exit(-1);
} else {
// We will quit the app after this transaction, whether it succeeds or fails
G_swap_state.should_exit = 1;
}
err = check_swap_conditions(&ctx_parsed_tx);
CHECK_APP_CANARY()
if (err != parser_ok) {
Expand Down
30 changes: 26 additions & 4 deletions app/src/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "base58.h"
#include "coin.h"
#include "cx.h"
#include "swap.h"
#include "zxmacros.h"
#include "ristretto.h"
#include "crypto_helper.h"
Expand All @@ -28,7 +29,7 @@

uint32_t hdPath[HDPATH_LEN_DEFAULT];

static zxerr_t crypto_extractPublicKey(key_kind_e addressKind, uint8_t *pubKey, uint16_t pubKeyLen) {
static zxerr_t crypto_extractPublicKey(key_kind_e addressKind, uint8_t *pubKey, uint16_t pubKeyLen, uint32_t *hdPath_to_use) {
if (pubKey == NULL || pubKeyLen < PK_LEN_25519) {
return zxerr_invalid_crypto_settings;
}
Expand All @@ -41,7 +42,7 @@ static zxerr_t crypto_extractPublicKey(key_kind_e addressKind, uint8_t *pubKey,
// Generate keys
CATCH_CXERROR(os_derive_bip32_with_seed_no_throw(HDW_NORMAL,
CX_CURVE_Ed25519,
hdPath,
hdPath_to_use,
HDPATH_LEN_DEFAULT,
privateKeyData,
NULL,
Expand Down Expand Up @@ -215,12 +216,13 @@ zxerr_t crypto_sign_sr25519(const uint8_t *message, size_t messageLen) {
}
#endif

zxerr_t crypto_fillAddress(key_kind_e addressKind, uint8_t *buffer, uint16_t bufferLen, uint16_t *addrResponseLen) {
// Helper function to fill a crypto address using a given hdPath
static zxerr_t crypto_fillAddress_helper(key_kind_e addressKind, uint8_t *buffer, uint16_t bufferLen, uint16_t *addrResponseLen, uint32_t *hdPath_to_use) {
if (bufferLen < PK_LEN_25519 + SS58_ADDRESS_MAX_LEN) {
return zxerr_unknown;
}
MEMZERO(buffer, bufferLen);
CHECK_ZXERR(crypto_extractPublicKey(addressKind, buffer, bufferLen))
CHECK_ZXERR(crypto_extractPublicKey(addressKind, buffer, bufferLen, hdPath_to_use))

size_t outLen = crypto_SS58EncodePubkey(buffer + PK_LEN_25519,
bufferLen - PK_LEN_25519,
Expand All @@ -233,3 +235,23 @@ zxerr_t crypto_fillAddress(key_kind_e addressKind, uint8_t *buffer, uint16_t buf
*addrResponseLen = PK_LEN_25519 + outLen;
return zxerr_ok;
}

// fill a crypto address using the global hdpath
zxerr_t crypto_fillAddress(key_kind_e addressKind, uint8_t *buffer, uint16_t bufferLen, uint16_t *addrResponseLen) {
return crypto_fillAddress_helper(addressKind, buffer, bufferLen, addrResponseLen, hdPath);
}

// fill a crypto address using a locally computed hdpath
zxerr_t crypto_fillAddress_standalone(uint8_t* params, uint8_t paramsSize, key_kind_e addressKind, uint8_t *buffer, uint16_t bufferLen, uint16_t *addrResponseLen) {
uint32_t local_hdPath[HDPATH_LEN_DEFAULT];

if (paramsSize != (sizeof(uint32_t) * HDPATH_LEN_DEFAULT)) {
return zxerr_invalid_crypto_settings;
}

for (uint32_t i = 0; i < HDPATH_LEN_DEFAULT; i++) {
CHECK_ZXERR(readU32BE(params + (i * 4), &local_hdPath[i]))
}

return crypto_fillAddress_helper(addressKind, buffer, bufferLen, addrResponseLen, local_hdPath);
}
2 changes: 2 additions & 0 deletions app/src/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ uint8_t crypto_SS58EncodePubkey(uint8_t *buffer, uint16_t buffer_len,

zxerr_t crypto_fillAddress(key_kind_e addressKind, uint8_t *buffer, uint16_t bufferLen, uint16_t *addrResponseLen);

zxerr_t crypto_fillAddress_standalone(uint8_t* params, uint8_t paramsSize, key_kind_e addressKind, uint8_t *buffer, uint16_t bufferLen, uint16_t *addrResponseLen);

zxerr_t crypto_sign_ed25519(uint8_t *signature, uint16_t signatureMaxlen, const uint8_t *message, uint16_t messageLen);

#ifdef SUPPORT_SR25519
Expand Down
Loading

0 comments on commit 44c3fb9

Please sign in to comment.