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

NBGL porting: improve EIP191 #586

Closed
Closed
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 src/common_ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ void ui_confirm_parameter(void);
void app_quit(void);

// EIP-191
void ui_191_start(void);
void ui_191_start(uint32_t msg_size);
void ui_191_switch_to_message(void);
void ui_191_switch_to_message_end(void);
void ui_191_switch_to_sign(void);
Expand Down
3 changes: 2 additions & 1 deletion src_bagl/ui_flow_signMessage.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ UX_FLOW(ux_191_flow,
&ux_191_step_sign,
&ux_191_step_cancel);

void ui_191_start(void) {
void ui_191_start(uint32_t msg_size) {
UNUSED(msg_size);
ux_flow_init(0, ux_191_flow, NULL);
ui_pos = UI_191_POS_REVIEW;
}
Expand Down
4 changes: 3 additions & 1 deletion src_features/signMessage/cmd_signMessage.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "common_ui.h"

static uint8_t processed_size;
static uint32_t msg_size;
static struct {
sign_message_state sign_state : 1;
bool ui_started : 1;
Expand Down Expand Up @@ -202,8 +203,8 @@ static void feed_display(void) {
if ((remaining_ui_buffer_length() == 0) ||
(tmpCtx.messageSigningContext.remainingLength == 0)) {
if (!states.ui_started) {
ui_191_start();
states.ui_started = true;
ui_191_start(msg_size);
} else {
ui_191_switch_to_message();
}
Expand Down Expand Up @@ -235,6 +236,7 @@ bool handleSignPersonalMessage(uint8_t p1,
if ((data = first_apdu_data(data, &length)) == NULL) {
return false;
}
msg_size = tmpCtx.messageSigningContext.remainingLength;
processed_size = data - payload;
} else if (p1 != P1_MORE) {
PRINTF("Error: Unexpected P1 (%u)!\n", p1);
Expand Down
180 changes: 70 additions & 110 deletions src_nbgl/ui_sign_message.c
Original file line number Diff line number Diff line change
@@ -1,31 +1,23 @@
#include <nbgl_page.h>
#include "shared_context.h"
#include "ui_callbacks.h"
#include "ui_nbgl.h"
#include "sign_message.h"
#include "glyphs.h"
#include "nbgl_use_case.h"
#include "common_ui.h"
#include "ui_message_signing.h"
#include "ui_signing.h"
#include "ledger_assert.h"
#include "mem.h"

#define TEXT_REVIEW_EIP191 REVIEW(TEXT_MESSAGE)
#define TEXT_SIGN_EIP191 SIGN(TEXT_MESSAGE)

typedef enum {
UI_191_ACTION_IDLE = 0,
UI_191_ACTION_ADVANCE_IN_MESSAGE,
UI_191_ACTION_GO_TO_SIGN
} e_ui_191_action;

static e_ui_191_action g_action;
#define MAX_PAIRS 10

static bool skip_message;

static nbgl_contentTagValue_t pair;
static nbgl_contentTagValue_t pairs[MAX_PAIRS];
static nbgl_contentTagValueList_t tagValueList;

static uint32_t eip191MessageIdx = 0;
static uint32_t stringsTmpTmpIdx = 0;
static uint32_t message_size = 0;
static char *full_message = NULL;

static void reject_message(void) {
io_seproxyhal_touch_signMessage_cancel();
Expand All @@ -35,121 +27,89 @@ static void sign_message(void) {
io_seproxyhal_touch_signMessage_ok();
}

static bool display_message(nbgl_pageContent_t *content) {
uint16_t len = 0;
bool reached;

if (g_action == UI_191_ACTION_ADVANCE_IN_MESSAGE) {
strncpy(g_stax_shared_buffer + eip191MessageIdx,
strings.tmp.tmp + stringsTmpTmpIdx,
SHARED_BUFFER_SIZE - eip191MessageIdx);
reached = nbgl_getTextMaxLenInNbLines(LARGE_MEDIUM_FONT,
(char *) g_stax_shared_buffer,
SCREEN_WIDTH - (2 * BORDER_MARGIN),
NB_MAX_LINES_IN_REVIEW,
#if (API_LEVEL == 0 || API_LEVEL >= 14)
&len,
false);
#else
&len);
#endif

stringsTmpTmpIdx = len - eip191MessageIdx;
eip191MessageIdx = len;
g_stax_shared_buffer[eip191MessageIdx] = '\0';

if (!reached && eip191MessageIdx < SHARED_BUFFER_SIZE) {
stringsTmpTmpIdx = 0;
question_switcher();

if (g_action != UI_191_ACTION_GO_TO_SIGN) {
return false;
}
} else if (reached || eip191MessageIdx == SHARED_BUFFER_SIZE) {
eip191MessageIdx = 0;
}
}

pair.value = g_stax_shared_buffer;
pair.item = "Message";
content->type = TAG_VALUE_LIST;
content->tagValueList.nbPairs = 1;
content->tagValueList.pairs = &pair;
content->tagValueList.smallCaseForValue = false;
content->tagValueList.nbMaxLinesForValue = NB_MAX_LINES_IN_REVIEW;
content->tagValueList.wrapping = false;

if ((g_action != UI_191_ACTION_IDLE) && (stringsTmpTmpIdx >= strlen(strings.tmp.tmp))) {
// Fetch the next content to display into strings.tmp.tmp buffer.
stringsTmpTmpIdx = 0;
question_switcher();
}
return true;
}

static bool display_sign(nbgl_pageContent_t *content) {
bool ret = false;

if (g_position != UI_SIGNING_POSITION_SIGN) {
content->type = INFO_LONG_PRESS, content->infoLongPress.icon = &C_Review_64px;
content->infoLongPress.text = TEXT_SIGN_EIP191;
content->infoLongPress.longPressText = SIGN_BUTTON;
g_position = UI_SIGNING_POSITION_SIGN;
ret = true;
}
return ret;
}

static bool nav_callback(uint8_t page, nbgl_pageContent_t *content) {
bool ret = true;

if (page == LAST_PAGE_FOR_REVIEW) { // was skipped
skip_message = true;
skip_rest_of_message();
}
if ((g_action != UI_191_ACTION_GO_TO_SIGN) && (g_position != UI_SIGNING_POSITION_SIGN)) {
if (skip_message) {
// do not refresh when this callback triggers after user validation
ret = false;
} else {
ret = display_message(content);
}
static void ui_191_finish_cb(bool confirm) {
if (confirm) {
nbgl_useCaseReviewStatus(STATUS_TYPE_MESSAGE_SIGNED, sign_message);
} else {
// the last page must contain a long press button
ret = display_sign(content);
nbgl_useCaseReviewStatus(STATUS_TYPE_MESSAGE_REJECTED, reject_message);
}
return ret;
}

static void continue_review(void) {
nbgl_useCaseForwardOnlyReview(REJECT_BUTTON, NULL, nav_callback, ui_message_review_choice);
static void getTagValues(void) {
uint16_t len = 0;
uint16_t nbPairs = 0;
uint16_t index = 0;

// Get Max len per page
nbgl_getTextMaxLenInNbLines(LARGE_MEDIUM_FONT,
full_message,
SCREEN_WIDTH - (2 * BORDER_MARGIN),
NB_MAX_LINES_IN_REVIEW,
&len,
false);
// init the messages for Tag/Value
do {
LEDGER_ASSERT(nbPairs < MAX_PAIRS,
"Too many pages required (%d / %d)!\n",
nbPairs,
MAX_PAIRS);
pairs[nbPairs].value = &full_message[index];
pairs[nbPairs].item = "Message";
// Shift message to insert '\0' byte to separate the sub-strings
// ex: string=ABCDEFGHIJKLMNO, len=5 -> ABCDE\0FGHIJ\0KLMNO
index += len;
memmove(&full_message[index + 1], &full_message[index], strlen(&full_message[index]));
full_message[index] = 0;
index++;
nbPairs++;
} while (strlen(&full_message[index]) > 0);

tagValueList.nbPairs = nbPairs;
tagValueList.pairs = pairs;
tagValueList.smallCaseForValue = false;
tagValueList.nbMaxLinesForValue = NB_MAX_LINES_IN_REVIEW;
tagValueList.wrapping = false;
}

void ui_191_start(void) {
void ui_191_start(uint32_t msg_size) {
g_position = UI_SIGNING_POSITION_START;

skip_message = false;
eip191MessageIdx = 0;
stringsTmpTmpIdx = 0;

ui_message_start(TEXT_REVIEW_EIP191, &ui_191_switch_to_message, &sign_message, &reject_message);
// Add more bytes to insert '\0' bytes to split into different messages
msg_size += MAX_PAIRS;
full_message = mem_alloc(msg_size);
LEDGER_ASSERT(full_message, "No suffisant memory!\n");
message_size = msg_size;
full_message[0] = 0;
// Loop until the whole message is received
do {
strlcat(full_message, strings.tmp.tmp, message_size);
continue_displaying_message();
} while (strlen(strings.tmp.tmp));
// Get and initialise the Tag/Value pairs
getTagValues();
// Start the review
nbgl_useCaseReview(TYPE_MESSAGE,
&tagValueList,
&C_Review_64px,
TEXT_REVIEW_EIP191,
NULL,
TEXT_SIGN_EIP191,
ui_191_finish_cb);
}

void ui_191_switch_to_message(void) {
g_position = UI_SIGNING_POSITION_REVIEW;
g_action = UI_191_ACTION_ADVANCE_IN_MESSAGE;
// No question mechanism on Stax:
// Message is already displayed
continue_review();
}

void ui_191_switch_to_sign(void) {
g_action = UI_191_ACTION_GO_TO_SIGN;
// Next nav_callback callback must display
// the hold to approve screen
if (skip_message) {
continue_review(); // to force screen refresh
}
// if (skip_message) {
// continue_review(); // to force screen refresh
// }
}

void ui_191_switch_to_question(void) {
Expand Down
Loading