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

Fix issues found by sonarcloud #45

Draft
wants to merge 10 commits into
base: develop
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion .github/workflows/lint-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,4 @@ jobs:
# Use Config file when the github action supports it
builtin: clear,rare
check_filenames: true
skip: ./libsol,./tests
skip: ./libsol/printer_test.c,./tests/Cargo.lock
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ APP_LOAD_PARAMS += $(COMMON_LOAD_PARAMS)

APPNAME = "Solana"
APPVERSION_M = 1
APPVERSION_N = 3
APPVERSION_N = 4
APPVERSION_P = 0
APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)"
APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)-swap"

ifeq ($(TARGET_NAME),TARGET_NANOS)
ICONNAME=icons/nanos_app_solana.gif
Expand Down
3 changes: 2 additions & 1 deletion doc/api.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Solana application : Common Technical Specifications

## 1.3.0
## 1.4.0

- Add SIGN SOLANA OFF-CHAIN MESSAGE
- Add compatibility with the Exchange Application to SWAP, FUND, or SELL SOL tokens

## About

Expand Down
2 changes: 1 addition & 1 deletion libsol/message_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <assert.h>
#include <stdio.h>

// Disable clang format for this file to keep clear buffer formating
// Disable clang format for this file to keep clear buffer formatting
/* clang-format off */

void test_process_message_body_ok() {
Expand Down
11 changes: 7 additions & 4 deletions libsol/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"\xff" \
"solana offchain"

#define OFFCHAIN_MESSAGE_SIGNING_DOMAIN_LEN (sizeof(OFFCHAIN_MESSAGE_SIGNING_DOMAIN) - 1)

static int check_buffer_length(Parser* parser, size_t num) {
return parser->buffer_length < num ? 1 : 0;
}
Expand Down Expand Up @@ -130,13 +132,14 @@ int parse_message_header(Parser* parser, MessageHeader* header) {
}

int parse_offchain_message_header(Parser* parser, OffchainMessageHeader* header) {
const size_t domain_len = strlen(OFFCHAIN_MESSAGE_SIGNING_DOMAIN);
BAIL_IF(check_buffer_length(parser, domain_len));
BAIL_IF(check_buffer_length(parser, OFFCHAIN_MESSAGE_SIGNING_DOMAIN_LEN));
int res;
if ((res = memcmp(OFFCHAIN_MESSAGE_SIGNING_DOMAIN, parser->buffer, domain_len)) != 0) {
if ((res = memcmp(OFFCHAIN_MESSAGE_SIGNING_DOMAIN,
parser->buffer,
OFFCHAIN_MESSAGE_SIGNING_DOMAIN_LEN)) != 0) {
return res;
}
advance(parser, domain_len);
advance(parser, OFFCHAIN_MESSAGE_SIGNING_DOMAIN_LEN);

BAIL_IF(parse_u8(parser, &header->version));
BAIL_IF(parse_u8(parser, &header->format));
Expand Down
4 changes: 3 additions & 1 deletion src/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ typedef enum InstructionCode {
InsSignOffchainMessage = 0x07
} InstructionCode;

extern volatile bool G_called_from_swap;

// display stepped screens
extern unsigned int ux_step;
extern unsigned int ux_step_count;
Expand Down Expand Up @@ -84,4 +86,4 @@ typedef struct internalStorage_t {

extern const internalStorage_t N_storage_real;
#define N_storage (*(volatile internalStorage_t*) PIC(&N_storage_real))
#endif
#endif
101 changes: 94 additions & 7 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,15 @@
#include "apdu.h"
#include "menu.h"

// Swap feature
#include "swap_lib_calls.h"
#include "handle_swap_sign_transaction.h"
#include "handle_get_printable_amount.h"
#include "handle_check_address.h"

ApduCommand G_command;
unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B];
volatile bool G_called_from_swap;

static void reset_main_globals(void) {
MEMCLEAR(G_command);
Expand All @@ -41,8 +48,10 @@ void handleApdu(volatile unsigned int *flags, volatile unsigned int *tx, int rx)

const int ret = apdu_handle_message(G_io_apdu_buffer, rx, &G_command);
if (ret != 0) {
MEMCLEAR(G_command);
THROW(ret);
}

if (G_command.state == ApduStatePayloadInProgress) {
THROW(ApduReplySuccess);
}
Expand Down Expand Up @@ -119,6 +128,7 @@ void app_main(void) {
THROW(ApduReplySdkExceptionIoReset);
}
CATCH_OTHER(e) {
G_called_from_swap = false;
switch (e & 0xF000) {
case 0x6000:
sw = e;
Expand Down Expand Up @@ -260,13 +270,8 @@ void nv_app_state_init() {
}
}

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

// ensure exception will work as planned
os_boot();

void coin_main(void) {
G_called_from_swap = false;
for (;;) {
UX_INIT();

Expand Down Expand Up @@ -307,5 +312,87 @@ __attribute__((section(".boot"))) int main(void) {
END_TRY;
}
app_exit();
}

static void start_app_from_lib(void) {
G_called_from_swap = true;
UX_INIT();
io_seproxyhal_init();
nv_app_state_init();
USB_power(0);
USB_power(1);
#ifdef HAVE_BLE
// Erase globals that may inherit values from exchange
MEMCLEAR(G_io_asynch_ux_callback);
// grab the current plane mode setting
G_io_app.plane_mode = os_setting_get(OS_SETTING_PLANEMODE, NULL, 0);
BLE_power(0, NULL);
BLE_power(1, "Nano X");
#endif // HAVE_BLE
app_main();
}

static void library_main_helper(libargs_t *args) {
check_api_level(CX_COMPAT_APILEVEL);
switch (args->command) {
case CHECK_ADDRESS:
// ensure result is zero if an exception is thrown
args->check_address->result = 0;
args->check_address->result = handle_check_address(args->check_address);
break;
case SIGN_TRANSACTION:
if (copy_transaction_parameters(args->create_transaction)) {
// never returns
start_app_from_lib();
}
break;
case GET_PRINTABLE_AMOUNT:
handle_get_printable_amount(args->get_printable_amount);
break;
default:
break;
}
}

static void library_main(libargs_t *args) {
volatile bool end = false;
/* This loop ensures that library_main_helper and os_lib_end are called
* within a try context, even if an exception is thrown */
while (1) {
BEGIN_TRY {
TRY {
if (!end) {
library_main_helper(args);
}
os_lib_end();
}
FINALLY {
end = true;
}
}
END_TRY;
}
}

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

// ensure exception will work as planned
os_boot();

if (arg0 == 0) {
// called from dashboard as standalone app
coin_main();
} else {
// Called as library from another app
libargs_t *args = (libargs_t *) arg0;
if (args->id == 0x100) {
library_main(args);
} else {
app_exit();
}
}

return 0;
}
107 changes: 69 additions & 38 deletions src/signMessage.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,7 @@
#include "globals.h"
#include "apdu.h"

static uint8_t set_result_sign_message() {
uint8_t signature[SIGNATURE_LENGTH];
cx_ecfp_private_key_t privateKey;
BEGIN_TRY {
TRY {
get_private_key_with_seed(&privateKey,
G_command.derivation_path,
G_command.derivation_path_length);
cx_eddsa_sign(&privateKey,
CX_LAST,
CX_SHA512,
G_command.message,
G_command.message_length,
NULL,
0,
signature,
SIGNATURE_LENGTH,
NULL);
memcpy(G_io_apdu_buffer, signature, SIGNATURE_LENGTH);
}
CATCH_OTHER(e) {
THROW(e);
}
FINALLY {
MEMCLEAR(privateKey);
}
}
END_TRY;
return SIGNATURE_LENGTH;
}
#include "handle_swap_sign_transaction.h"

static void send_result_sign_message(void) {
sendResponse(set_result_sign_message(), true);
Expand Down Expand Up @@ -137,6 +108,12 @@ void handle_sign_message_parse_message(volatile unsigned int *tx) {
//*tx = set_result_sign_message();
// THROW(ApduReplySuccess);
UNUSED(tx);
}

if ((G_command.non_confirm || G_called_from_swap) &&
!(G_command.non_confirm && G_called_from_swap)) {
// User validation bypass requested NOT in swap context
// Or user validation requested while in swap context
THROW(ApduReplySdkNotSupported);
}

Expand Down Expand Up @@ -168,22 +145,76 @@ void handle_sign_message_parse_message(volatile unsigned int *tx) {
}
}

static bool check_swap_validity(const SummaryItemKind_t kinds[MAX_TRANSACTION_SUMMARY_ITEMS],
size_t num_summary_steps) {
bool amount_ok = false;
bool recipient_ok = false;
bool fee_payer_ok = false;
if (num_summary_steps != 3) {
PRINTF("3 steps expected for transaction in swap context, not %u\n", num_summary_steps);
return false;
}
for (size_t i = 0; i < num_summary_steps; ++i) {
transaction_summary_display_item(i, DisplayFlagNone | DisplayFlagLongPubkeys);
PRINTF("G_transaction_summary_title = %s\n", G_transaction_summary_title);
PRINTF("G_transaction_summary_text = %s\n", G_transaction_summary_text);
switch (kinds[i]) {
case SummaryItemAmount:
if (strcmp(G_transaction_summary_title, "Transfer") == 0) {
amount_ok = check_swap_amount(G_transaction_summary_text);
} else {
PRINTF("Refused field '%s'\n", G_transaction_summary_title);
return false;
}
break;
case SummaryItemPubkey:
if (strcmp(G_transaction_summary_title, "Recipient") == 0) {
recipient_ok = check_swap_recipient(G_transaction_summary_text);
} else if (strcmp(G_transaction_summary_title, "Fee payer") == 0) {
fee_payer_ok = check_swap_fee_payer(G_transaction_summary_text);
} else {
PRINTF("Refused field '%s'\n", G_transaction_summary_title);
return false;
}
break;
default:
PRINTF("Refused kind '%u'\n", SummaryItemAmount);
return false;
}
}
return amount_ok && recipient_ok && fee_payer_ok;
}

void handle_sign_message_ui(volatile unsigned int *flags) {
// Display the transaction summary
SummaryItemKind_t summary_step_kinds[MAX_TRANSACTION_SUMMARY_ITEMS];
size_t num_summary_steps = 0;
if (transaction_summary_finalize(summary_step_kinds, &num_summary_steps) == 0) {
size_t num_flow_steps = 0;
// If we are in swap context, do not redisplay the message data
// Instead, ensure they are identitical with what was previously displayed
if (G_called_from_swap) {
if (check_swap_validity(summary_step_kinds, num_summary_steps)) {
send_result_sign_message();
// Quit app, we are in limited mode and our work is done
os_sched_exit(0);
} else {
PRINTF("Refused blind signing incorrect Swap transaction\n");
THROW(ApduReplySolanaSummaryFinalizeFailed);
}
} else {
MEMCLEAR(flow_steps);
size_t num_flow_steps = 0;

for (size_t i = 0; i < num_summary_steps; i++) {
flow_steps[num_flow_steps++] = &ux_summary_step;
}
for (size_t i = 0; i < num_summary_steps; i++) {
flow_steps[num_flow_steps++] = &ux_summary_step;
}

flow_steps[num_flow_steps++] = &ux_approve_step;
flow_steps[num_flow_steps++] = &ux_reject_step;
flow_steps[num_flow_steps++] = FLOW_END_STEP;
flow_steps[num_flow_steps++] = &ux_approve_step;
flow_steps[num_flow_steps++] = &ux_reject_step;
flow_steps[num_flow_steps++] = FLOW_END_STEP;

ux_flow_init(0, flow_steps, NULL);
ux_flow_init(0, flow_steps, NULL);
}
} else {
THROW(ApduReplySolanaSummaryFinalizeFailed);
}
Expand Down
31 changes: 0 additions & 31 deletions src/signOffchainMessage.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,37 +76,6 @@ static bool is_data_ascii(const uint8_t *data, size_t length) {
return true;
}

static uint8_t set_result_sign_message() {
uint8_t signature[SIGNATURE_LENGTH];
cx_ecfp_private_key_t privateKey;
BEGIN_TRY {
TRY {
get_private_key_with_seed(&privateKey,
G_command.derivation_path,
G_command.derivation_path_length);
cx_eddsa_sign(&privateKey,
CX_LAST,
CX_SHA512,
G_command.message,
G_command.message_length,
NULL,
0,
signature,
SIGNATURE_LENGTH,
NULL);
memcpy(G_io_apdu_buffer, signature, SIGNATURE_LENGTH);
}
CATCH_OTHER(e) {
THROW(e);
}
FINALLY {
MEMCLEAR(privateKey);
}
}
END_TRY;
return SIGNATURE_LENGTH;
}

//////////////////////////////////////////////////////////////////////

UX_STEP_NOCB(ux_sign_msg_text_step,
Expand Down
Loading