Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Applications started for signing now return to Exchange #115

Merged
merged 2 commits into from
Jun 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 35 additions & 17 deletions include/swap_lib_calls.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
#ifndef SWAP_LIB_CALLS
#define SWAP_LIB_CALLS
#pragma once

/* This file is the shared API between Exchange and the apps started in Library mode for Exchange
*
* DO NOT MODIFY THIS FILE IN APPLICATIONS OTHER THAN EXCHANGE
* On modification in Exchange, forward the changes to all applications supporting Exchange
*/

#include "stdbool.h"
#include "stdint.h"

#define RUN_APPLICATION 1

Expand All @@ -24,12 +30,12 @@
// structure that should be send to specific coin application to get address
typedef struct check_address_parameters_s {
// IN
unsigned char *coin_configuration;
unsigned char coin_configuration_length;
uint8_t *coin_configuration;
uint8_t coin_configuration_length;
// serialized path, segwit, version prefix, hash used, dictionary etc.
// fields and serialization format depends on spesific coin app
unsigned char *address_parameters;
unsigned char address_parameters_length;
uint8_t *address_parameters;
uint8_t address_parameters_length;
char *address_to_check;
char *extra_id_to_check;
// OUT
Expand All @@ -39,24 +45,36 @@ typedef struct check_address_parameters_s {
// structure that should be send to specific coin application to get printable amount
typedef struct get_printable_amount_parameters_s {
// IN
unsigned char *coin_configuration;
unsigned char coin_configuration_length;
unsigned char *amount;
unsigned char amount_length;
uint8_t *coin_configuration;
uint8_t coin_configuration_length;
uint8_t *amount;
uint8_t amount_length;
bool is_fee;
// OUT
char printable_amount[MAX_PRINTABLE_AMOUNT_SIZE];
} get_printable_amount_parameters_t;

typedef struct create_transaction_parameters_s {
unsigned char *coin_configuration;
unsigned char coin_configuration_length;
unsigned char *amount;
unsigned char amount_length;
unsigned char *fee_amount;
unsigned char fee_amount_length;
// IN
uint8_t *coin_configuration;
uint8_t coin_configuration_length;
uint8_t *amount;
uint8_t amount_length;
uint8_t *fee_amount;
uint8_t fee_amount_length;
char *destination_address;
char *destination_address_extra_id;
// OUT
uint8_t result;
} create_transaction_parameters_t;

#endif
typedef struct libargs_s {
unsigned int id;
unsigned int command;
unsigned int unused;
union {
check_address_parameters_t *check_address;
create_transaction_parameters_t *create_transaction;
get_printable_amount_parameters_t *get_printable_amount;
};
} libargs_t;
80 changes: 44 additions & 36 deletions src/currency_lib_calls.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,40 +41,40 @@ int get_printable_amount(buf_t *coin_config,
char *printable_amount,
unsigned char printable_amount_size,
bool is_fee) {
static unsigned int libcall_params[5];
static get_printable_amount_parameters_t lib_input_params = {0};
lib_input_params.coin_configuration = coin_config->bytes;
lib_input_params.coin_configuration_length = coin_config->size;
lib_input_params.amount = amount;
lib_input_params.amount_length = amount_size;
lib_input_params.is_fee = is_fee;
unsigned int libcall_params[5];
get_printable_amount_parameters_t lib_in_out_params;
memset(&lib_in_out_params, 0, sizeof(lib_in_out_params));

lib_in_out_params.coin_configuration = coin_config->bytes;
lib_in_out_params.coin_configuration_length = coin_config->size;
lib_in_out_params.amount = amount;
lib_in_out_params.amount_length = amount_size;
lib_in_out_params.is_fee = is_fee;

libcall_params[0] = (unsigned int) application_name;
libcall_params[1] = 0x100;
libcall_params[2] = GET_PRINTABLE_AMOUNT;
libcall_params[3] = 0;
libcall_params[4] = (unsigned int) &lib_input_params;
PRINTF("Address of printable_amount %d\n", lib_input_params.printable_amount);
memset(lib_input_params.printable_amount, 0, sizeof(lib_input_params.printable_amount));
// Speculos workaround
// io_seproxyhal_general_status();
PRINTF("Calling coin %s as library, for command GET_PRINTABLE_AMOUNT\n", libcall_params[0]);
libcall_params[4] = (unsigned int) &lib_in_out_params;

PRINTF("Exchange will call '%s' as library for GET_PRINTABLE_AMOUNT\n", application_name);
os_lib_call(libcall_params);
PRINTF("Back in Exchange, the app finished the library command GET_PRINTABLE_AMOUNT\n");

// the lib application should have something for us to display
if (lib_input_params.printable_amount[0] == '\0') {
if (lib_in_out_params.printable_amount[0] == '\0') {
PRINTF("Error: Printable amount should exist\n");
return -1;
}
// result should be null terminated string, so we need to have at least one 0
if (lib_input_params.printable_amount[sizeof(lib_input_params.printable_amount) - 1] != '\0') {
if (lib_in_out_params.printable_amount[sizeof(lib_in_out_params.printable_amount) - 1] !=
'\0') {
PRINTF("Error: Printable amount should be null-terminated\n");
return -1;
}
if (strlen(lib_input_params.printable_amount) >= printable_amount_size) {
PRINTF("Error: Printable amount is too big to fit into input buffer\n");
return -1;
}
strncpy(printable_amount, lib_input_params.printable_amount, printable_amount_size);
printable_amount[printable_amount_size - 1] = '\x00';
strlcpy(printable_amount, lib_in_out_params.printable_amount, printable_amount_size);
PRINTF("Returned printable_amount '%s'\n", printable_amount);

return 0;
}

Expand All @@ -83,42 +83,50 @@ int check_address(buf_t *coin_config,
char *application_name,
char *address_to_check,
char *address_extra_to_check) {
static unsigned int libcall_params[5];
static check_address_parameters_t lib_in_out_params = {0};
unsigned int libcall_params[5];
check_address_parameters_t lib_in_out_params;
memset(&lib_in_out_params, 0, sizeof(lib_in_out_params));

lib_in_out_params.coin_configuration = coin_config->bytes;
lib_in_out_params.coin_configuration_length = coin_config->size;
lib_in_out_params.address_parameters = address_parameters->bytes;
lib_in_out_params.address_parameters_length = address_parameters->size;
lib_in_out_params.address_to_check = address_to_check;
lib_in_out_params.extra_id_to_check = address_extra_to_check;

libcall_params[0] = (unsigned int) application_name;
libcall_params[1] = 0x100;
libcall_params[2] = CHECK_ADDRESS;
libcall_params[3] = 0;
libcall_params[4] = (unsigned int) &lib_in_out_params;
PRINTF("I am calling %s to check address\n", application_name);
PRINTF("I am going to check address %s\n", lib_in_out_params.address_to_check);
// Speculos workaround
// io_seproxyhal_general_status();
PRINTF("Calling coin %s as library, for command CHECK_ADDRESS\n", libcall_params[0]);

PRINTF("Exchange will call '%s' as library for CHECK_ADDRESS\n", application_name);
PRINTF("The address to check '%s'\n", lib_in_out_params.address_to_check);
os_lib_call(libcall_params);
// PRINTF("Debug data sent by library %.*H\n", 20, lib_in_out_params.address_to_check);
PRINTF("I am back\n");
PRINTF("Back in Exchange, the app finished the library command CHECK_ADDRESS\n");
PRINTF("Returned code %d\n", lib_in_out_params.result);

return lib_in_out_params.result;
}

void create_payin_transaction(char *application_name,
create_transaction_parameters_t *lib_in_out_params) {
int create_payin_transaction(char *application_name,
create_transaction_parameters_t *lib_in_out_params) {
unsigned int libcall_params[5];

lib_in_out_params->result = 0;

libcall_params[0] = (unsigned int) application_name;
libcall_params[1] = 0x100;
libcall_params[2] = SIGN_TRANSACTION;
libcall_params[3] = 0;
libcall_params[4] = (unsigned int) lib_in_out_params;
PRINTF("Calling %s app\n", application_name);

PRINTF("Exchange will call '%s' as library for SIGN_TRANSACTION\n", application_name);
USB_power(0);
PRINTF("Calling coin %s as library, for command SIGN_TRANSACTION\n", libcall_params[0]);
os_lib_call(libcall_params);
USB_power(0);
USB_power(1);
// From now our BSS is corrupted and unusable. Return to main loop start ASAP
PRINTF("Back in Exchange, the app finished the library command SIGN_TRANSACTION\n");
PRINTF("Returned code %d\n", lib_in_out_params->result);

return lib_in_out_params->result;
}
7 changes: 2 additions & 5 deletions src/currency_lib_calls.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#ifndef _SOURCE_CURRENCY_LIB_CALLS_H_
#define _SOURCE_CURRENCY_LIB_CALLS_H_
#pragma once

#include "swap_lib_calls.h"
#include "buffer.h"
Expand All @@ -12,8 +11,6 @@ int check_address(buf_t *coin_config,
char *address_to_check,
char *address_extra_id_to_check);

void create_payin_transaction(char *application_name, create_transaction_parameters_t *params);

int get_printable_amount(buf_t *coin_config,
char *application_name,
unsigned char *amount,
Expand All @@ -22,4 +19,4 @@ int get_printable_amount(buf_t *coin_config,
unsigned char printable_amount_size,
bool is_fee);

#endif // _SOURCE_CURRENCY_LIB_CALLS_H_
int create_payin_transaction(char *application_name, create_transaction_parameters_t *params);
16 changes: 15 additions & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,16 @@ void app_main(void) {
},
};

if (dispatch_command(&cmd) < 0) return; // some non recoverable error happened
if (dispatch_command(&cmd) < 0) {
// some non recoverable error happened
return;
}

if (G_swap_ctx.state == SIGN_FINISHED) {
// We are back from an app started in signing mode, our globals are corrupted
// Force a return to the main function in order to trigger a full clean restart
return;
}

if (G_swap_ctx.state == INITIAL_STATE) {
ui_idle();
Expand All @@ -90,6 +99,11 @@ __attribute__((section(".boot"))) int main(__attribute__((unused)) int arg0) {
os_boot();

for (;;) {
// Fully reset the global space, as it may be corrupted if we come back from an app started
// for signing
PRINTF("Exchange new cycle, reset BSS\n");
os_explicit_zero_BSS_segment();

UX_INIT();

BEGIN_TRY {
Expand Down
7 changes: 5 additions & 2 deletions src/start_signing_transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "io.h"

int start_signing_transaction(const command_t *cmd) {
int ret = 0;
G_io_apdu_buffer[0] = 0x90;
G_io_apdu_buffer[1] = 0x00;
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
Expand Down Expand Up @@ -39,7 +40,9 @@ int start_signing_transaction(const command_t *cmd) {
lib_in_out_params.destination_address_extra_id = G_swap_ctx.fund_transaction_extra_id;
}

create_payin_transaction(G_swap_ctx.payin_binary_name, &lib_in_out_params);
ret = create_payin_transaction(G_swap_ctx.payin_binary_name, &lib_in_out_params);
// Write G_swap_ctx.state AFTER coming back to exchange to avoid erasure by the app
G_swap_ctx.state = SIGN_FINISHED;

return 0;
return ret;
}
6 changes: 2 additions & 4 deletions src/states.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#ifndef _STATES_H_
#define _STATES_H_
#pragma once

typedef enum {
INITIAL_STATE = 0,
Expand All @@ -11,7 +10,6 @@ typedef enum {
TO_ADDR_CHECKED = 6,
WAITING_USER_VALIDATION = 7,
WAITING_SIGNING = 8,
SIGN_FINISHED = 9,
STATE_UPPER_BOUND
} state_e;

#endif //_STATES_H_
Binary file removed test/python/lib_binaries/libraries_binaries.zip
Binary file not shown.