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

Version v0.7.0: Improve Blind Signing behavior #16

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Blind signing: Implement the ability to sign transactions that cannot be decoded

## [0.6.9] - 2024-01-23

### Added
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ APPNAME = "Aptos"

# Application version
APPVERSION_M = 0
APPVERSION_N = 6
APPVERSION_P = 9
APPVERSION_N = 7
APPVERSION_P = 0
APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)"

# Application source files
Expand Down
18 changes: 10 additions & 8 deletions src/handler/sign_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ int handler_sign_tx(buffer_t *cdata, uint8_t chunk, bool more) {
G_context.req_type = REQUEST_UNDEFINED;
return io_send_sw(SW_BAD_STATE);
}
if (G_context.state == STATE_PARSED || G_context.state == STATE_APPROVED) {
if (G_context.state == STATE_PARSED || G_context.state == STATE_APPROVED ||
G_context.state == STATE_CONTINUE_UNPARSED) {
// should not get here, double check, context should already be reset
return io_send_sw(SW_BAD_STATE);
}
Expand Down Expand Up @@ -96,15 +97,16 @@ int handler_sign_tx(buffer_t *cdata, uint8_t chunk, bool more) {

parser_status_e status = transaction_deserialize(&buf, &G_context.tx_info.transaction);
PRINTF("Parsing status: %d.\n", status);
if (status != PARSING_OK) {
// reset the context to prevent sending the "last" chunk multiple times
G_context.req_type = REQUEST_UNDEFINED;
return io_send_sw(SW_TX_PARSING_FAIL);
}

G_context.state = STATE_PARSED;
int ui_status = 0;
if (status == PARSING_OK) {
G_context.state = STATE_PARSED;
ui_status = ui_display_transaction();
} else {
G_context.state = STATE_CONTINUE_UNPARSED;
ui_status = ui_display_unparsed_transaction();
}

int ui_status = ui_display_transaction();
G_context.req_type = REQUEST_UNDEFINED; // all the work is done, reset the context
return ui_status;
}
Expand Down
7 changes: 4 additions & 3 deletions src/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ typedef enum {
* Enumeration with parsing state.
*/
typedef enum {
STATE_NONE, /// No state
STATE_PARSED, /// Transaction data parsed
STATE_APPROVED /// Transaction data approved
STATE_NONE, /// No state
STATE_PARSED, /// Transaction data parsed
STATE_CONTINUE_UNPARSED, /// Transaction data parsed
STATE_APPROVED /// Transaction data approved
} state_e;

/**
Expand Down
5 changes: 5 additions & 0 deletions src/ui/action/validate.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,8 @@ void validate_transaction(bool choice) {
io_send_sw(SW_DENY);
}
}

void reject_unparsed_transaction(void) {
G_context.state = STATE_NONE;
io_send_sw(SW_TX_PARSING_FAIL);
}
2 changes: 2 additions & 0 deletions src/ui/action/validate.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ void validate_pubkey(bool choice);
*
*/
void validate_transaction(bool choice);

void reject_unparsed_transaction(void);
72 changes: 72 additions & 0 deletions src/ui/bagl_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ UX_STEP_NOCB(ux_display_blind_sign_banner_step,
"enabled in Settings",
});
#endif
// Step with continue button
UX_STEP_CB(ux_display_continue_step,
pb,
(*g_validate_callback)(true),
{
&C_icon_validate_14,
"Continue",
});
// Step with approve button
UX_STEP_CB(ux_display_approve_step,
pb,
Expand Down Expand Up @@ -170,6 +178,29 @@ int ui_display_address() {
return ret;
}

#ifdef TARGET_NANOS
UX_STEP_NOCB(ux_display_decode_fail_step,
bnnn_paging,
{
.title = "Info",
.text = "Unable to display transaction data",
});
#else
UX_STEP_NOCB(ux_display_decode_fail_step,
pnn,
{
&C_icon_warning,
"Unable to display",
"transaction data",
});
#endif
UX_STEP_NOCB(ux_display_details_step,
pnn,
{
&C_icon_eye,
"Details",
"Unavailable",
});
// Step with icon and text
UX_STEP_NOCB(ux_display_blind_warn_step,
pnn,
Expand Down Expand Up @@ -258,6 +289,26 @@ UX_STEP_NOCB(ux_display_gas_fee_step,
.text = g_gas_fee,
});

// FLOW to display uparsed transaction information:
// #1 screen : "Unable to display transaction data"
// #2 screen : continue button
// #3 screen : reject button
UX_FLOW(ux_display_warn_uparsed_tx_flow,
&ux_display_decode_fail_step,
&ux_display_continue_step,
&ux_display_reject_step);

// FLOW to display message that transaction details are unavailable:
// #1 screen : warning icon + "Blind Signing"
// #2 screen : eye icon + "Details Unavailable"
// #3 screen : approve button
// #4 screen : reject button
UX_FLOW(ux_display_uparsed_tx_flow,
&ux_display_blind_warn_step,
&ux_display_details_step,
&ux_display_approve_step,
&ux_display_reject_step);

// FLOW to display default transaction information:
// #1 screen : warning icon + "Blind Signing"
// #2 screen : eye icon + "Review Transaction"
Expand Down Expand Up @@ -366,6 +417,27 @@ UX_FLOW(ux_display_tx_coin_transfer_flow,
&ux_display_approve_step,
&ux_display_reject_step);

static void ui_action_continue_unparsed_transaction(bool choice) {
if (choice) {
g_validate_callback = &ui_action_validate_transaction;
ui_flow_verified_display(ux_display_uparsed_tx_flow);
} else {
reject_unparsed_transaction();
ui_menu_main();
}
}

int ui_display_unparsed_transaction() {
const int ret = ui_prepare_unparsed_transaction();
if (ret == UI_PREPARED) {
g_validate_callback = &ui_action_continue_unparsed_transaction;
ui_flow_display(ux_display_warn_uparsed_tx_flow);
return 0;
}

return ret;
}

int ui_display_transaction() {
g_validate_callback = &ui_action_validate_transaction;

Expand Down
9 changes: 9 additions & 0 deletions src/ui/common_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,15 @@ int ui_prepare_transaction() {
return UI_PREPARED;
}

int ui_prepare_unparsed_transaction() {
if (G_context.req_type != CONFIRM_TRANSACTION || G_context.state != STATE_CONTINUE_UNPARSED) {
G_context.state = STATE_NONE;
return io_send_sw(SW_BAD_STATE);
}

return UI_PREPARED;
}

int ui_prepare_entry_function() {
entry_function_payload_t *function = &G_context.tx_info.transaction.payload.entry_function;
char function_module_id_address_hex[67] = {0};
Expand Down
3 changes: 3 additions & 0 deletions src/ui/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ int ui_prepare_address(void);
int ui_display_transaction(void);
int ui_prepare_transaction(void);

int ui_display_unparsed_transaction(void);
int ui_prepare_unparsed_transaction(void);

int ui_display_message(void);
int ui_display_raw_message(void);

Expand Down
72 changes: 56 additions & 16 deletions src/ui/nbgl_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,29 @@ nbgl_layoutTagValueList_t pairList;
nbgl_pageInfoLongPress_t infoLongPress;

static void blind_sign_continue() {
nbgl_useCaseReviewStart(blind_sign_ctx.icon,
blind_sign_ctx.review_title,
blind_sign_ctx.review_sub_title,
blind_sign_ctx.reject_text,
blind_sign_ctx.continue_callback,
blind_sign_ctx.reject_callback);
if (blind_sign_ctx.continue_callback) {
nbgl_useCaseReviewStart(blind_sign_ctx.icon,
blind_sign_ctx.review_title,
blind_sign_ctx.review_sub_title,
blind_sign_ctx.reject_text,
blind_sign_ctx.continue_callback,
blind_sign_ctx.reject_callback);
} else if (blind_sign_ctx.choice_callback) {
pairList.nbMaxLinesForValue = 0;
pairList.nbPairs = 0;
pairList.pairs = pairs;

infoLongPress.icon = &C_aptos_logo_64px;
infoLongPress.text = blind_sign_ctx.long_press_title;
infoLongPress.longPressText = blind_sign_ctx.long_press_button_text;

nbgl_useCaseStaticReview(&pairList,
&infoLongPress,
blind_sign_ctx.reject_text,
blind_sign_ctx.choice_callback);
} else {
PRINTF("Invalid blind signing context\n");
}
}

static void blind_sign_info() {
Expand All @@ -65,6 +82,19 @@ static void blind_sign_choice(bool enable) {
}
}

static void blind_sign_init_choice() {
if (N_storage.settings.allow_blind_signing) {
blind_sign_info();
} else {
nbgl_useCaseChoice(&C_round_warning_64px,
"Enable blind signing to\nauthorize this\noperation",
NULL,
"Enable blind signing",
blind_sign_ctx.reject_text,
blind_sign_choice);
}
}

void nbgl_useCaseReviewVerify(const nbgl_icon_details_t *icon,
const char *review_title,
const char *review_sub_title,
Expand All @@ -77,16 +107,26 @@ void nbgl_useCaseReviewVerify(const nbgl_icon_details_t *icon,
blind_sign_ctx.reject_text = reject_text;
blind_sign_ctx.continue_callback = continue_callback;
blind_sign_ctx.reject_callback = reject_callback;
if (N_storage.settings.allow_blind_signing) {
blind_sign_info();
} else {
nbgl_useCaseChoice(&C_round_warning_64px,
"Enable blind signing to\nauthorize this\noperation",
NULL,
"Enable blind signing",
reject_text,
blind_sign_choice);
}
blind_sign_ctx.choice_callback = NULL;

blind_sign_init_choice();
}

void nbgl_useCaseStaticReviewVerify(const nbgl_icon_details_t *icon,
const char *long_press_title,
const char *long_press_button_text,
const char *reject_text,
nbgl_choiceCallback_t choice_callback,
nbgl_callback_t reject_callback) {
blind_sign_ctx.icon = icon;
blind_sign_ctx.long_press_title = long_press_title;
blind_sign_ctx.long_press_button_text = long_press_button_text;
blind_sign_ctx.reject_text = reject_text;
blind_sign_ctx.continue_callback = NULL;
blind_sign_ctx.reject_callback = reject_callback;
blind_sign_ctx.choice_callback = choice_callback;

blind_sign_init_choice();
}

#endif
18 changes: 16 additions & 2 deletions src/ui/nbgl_display.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ extern nbgl_pageInfoLongPress_t infoLongPress;

typedef struct use_case_review_ctx_s {
const nbgl_icon_details_t *icon;
const char *review_title;
const char *review_sub_title;
union {
const char *review_title;
const char *long_press_title;
};
union {
const char *review_sub_title;
const char *long_press_button_text;
};
const char *reject_text;
nbgl_callback_t continue_callback;
nbgl_callback_t reject_callback;
nbgl_choiceCallback_t choice_callback;
} use_case_review_ctx_t;

void nbgl_useCaseReviewVerify(const nbgl_icon_details_t *icon,
Expand All @@ -21,3 +28,10 @@ void nbgl_useCaseReviewVerify(const nbgl_icon_details_t *icon,
const char *reject_text,
nbgl_callback_t continue_callback,
nbgl_callback_t reject_callback);

void nbgl_useCaseStaticReviewVerify(const nbgl_icon_details_t *icon,
const char *long_press_title,
const char *long_press_button_text,
const char *reject_text,
nbgl_choiceCallback_t choice_callback,
nbgl_callback_t reject_callback);
Loading
Loading