Skip to content

Commit

Permalink
pin: allow user to abandon PIN entry by going 'back' from first digit
Browse files Browse the repository at this point in the history
In general this will abandon/cancel the action requiring the PIN.
NOTE: in this case an externally-prompted 'auth_user' request will
receive the 'USER_CANCELLED' error (as opposed to a 'false' result).
  • Loading branch information
JamieDriver committed Jun 25, 2024
1 parent 42efa85 commit e39515b
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 62 deletions.
22 changes: 15 additions & 7 deletions jade_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import sys
import logging
from jadepy import JadeAPI
from jadepy import JadeAPI, JadeError

LOGGING = True

Expand Down Expand Up @@ -62,9 +62,17 @@ def http_request_fn(params):
# Note: this requires a pinserver to be running
# The network to use is deduced from the version-info
network = 'testnet' if verinfo.get('JADE_NETWORKS') == 'TEST' else 'mainnet'
while jade.auth_user(network, http_request_fn) is not True:
print('Error - please try again')

# Just a couple of test calls that mimic what gdk-logon does
print(jade.get_xpub(network, []))
print(jade.sign_message([1195487518], 'greenaddress.it login ABCDE'))
try:
while jade.auth_user(network, http_request_fn) is not True:
print('Error - please try again')
except JadeError as e:
if e.code == JadeError.USER_CANCELLED:
print('User abandoned PIN entry')
network = None
else:
raise

if network:
# Just a couple of test calls that mimic what gdk-logon does
print(jade.get_xpub(network, []))
print(jade.sign_message([1195487518], 'greenaddress.it login ABCDE'))
31 changes: 22 additions & 9 deletions main/process/auth_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,12 @@ static bool get_pin_get_aeskey(jade_process_t* process, const char* title, uint8

// In a debug unattended ci build, use hardcoded pin after a short delay
#ifndef CONFIG_DEBUG_UNATTENDED_CI
run_pin_entry_loop(&pin_insert);
if (!run_pin_entry_loop(&pin_insert)) {
// User abandoned entering pin
jade_process_reject_message(process, CBOR_RPC_USER_CANCELLED, "User abandonded pin entry", NULL);
SENSITIVE_POP(&pin_insert);
return false;
}
#else
vTaskDelay(CONFIG_DEBUG_UNATTENDED_CI_TIMEOUT_MS / portTICK_PERIOD_MS);
const uint8_t testpin[sizeof(pin_insert.pin)] = { 0, 1, 2, 3, 4, 5 };
Expand Down Expand Up @@ -121,11 +126,18 @@ static bool set_pin_get_aeskey(jade_process_t* process, const char* title, uint8
SENSITIVE_PUSH(&pin_insert, sizeof(pin_insert_t));

while (true) {
reset_pin(&pin_insert, title);

// If getting PIN via QRs, free gui memory before attempting QR roundtrip
gui_set_current_activity_ex(pin_insert.activity, process->ctx.source == SOURCE_INTERNAL);

#ifndef CONFIG_DEBUG_UNATTENDED_CI
run_pin_entry_loop(&pin_insert);
if (!run_pin_entry_loop(&pin_insert)) {
// User abandoned setting new pin
jade_process_reject_message(process, CBOR_RPC_USER_CANCELLED, "User abandoned setting new PIN", NULL);
SENSITIVE_POP(&pin_insert);
return false;
}
#else
vTaskDelay(CONFIG_DEBUG_UNATTENDED_CI_TIMEOUT_MS / portTICK_PERIOD_MS);
const uint8_t testpin[sizeof(pin_insert.pin)] = { 0, 1, 2, 3, 4, 5 };
Expand All @@ -137,7 +149,10 @@ static bool set_pin_get_aeskey(jade_process_t* process, const char* title, uint8
reset_pin(&pin_insert, "Confirm PIN");

#ifndef CONFIG_DEBUG_UNATTENDED_CI
run_pin_entry_loop(&pin_insert);
if (!run_pin_entry_loop(&pin_insert)) {
// User abandoned second input - back to first ...
continue;
}
#else
vTaskDelay(CONFIG_DEBUG_UNATTENDED_CI_TIMEOUT_MS / portTICK_PERIOD_MS);
memcpy(pin_insert.pin, testpin, sizeof(testpin));
Expand All @@ -153,12 +168,11 @@ static bool set_pin_get_aeskey(jade_process_t* process, const char* title, uint8
// Pins mismatch - try again
const char* message[] = { "Pin mismatch,", "please try again." };
if (!await_continueback_activity(NULL, message, 2, true, NULL)) {
// Abandon
jade_process_reject_message(process, CBOR_RPC_USER_CANCELLED, "User failed to set new PIN", NULL);
// Abandon setting new pin
jade_process_reject_message(process, CBOR_RPC_USER_CANCELLED, "User abandoned setting new PIN", NULL);
SENSITIVE_POP(&pin_insert);
return false;
}
reset_pin(&pin_insert, title);
}
}
SENSITIVE_POP(&pin_insert);
Expand Down Expand Up @@ -189,9 +203,8 @@ static bool get_pin_load_keys(jade_process_t* process, const bool suppress_pin_c
// Do the pinserver 'getpin' process
const char* unlock_pin_msg = suppress_pin_change_confirmation ? "Enter Current PIN" : "Unlock Jade";
if (!get_pin_get_aeskey(process, unlock_pin_msg, pin, sizeof(pin), aeskey, sizeof(aeskey))) {
// Server or networking/connection error
// User abandoned entering PIN, or some sort of server or networking/connection error
// NOTE: reply message will have already been sent
JADE_LOGE("Failed to get aeskey from pinserver");
goto cleanup;
}

Expand Down Expand Up @@ -293,7 +306,7 @@ static bool set_pin_save_keys(jade_process_t* process)

// Do the pinserver 'setpin' process
if (!set_pin_get_aeskey(process, "Enter New PIN", pin, sizeof(pin), aeskey, sizeof(aeskey))) {
// Server or networking/connection error
// User abandoned entering PIN, or some sort of server or networking/connection error
// NOTE: reply message will have already been sent
goto cleanup;
}
Expand Down
19 changes: 15 additions & 4 deletions main/process/dashboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,11 @@ static void offer_jade_reset(void)
JADE_ASSERT(sizeof(num) == sizeof(pin_insert.pin));

gui_set_current_activity(pin_insert.activity);
run_pin_entry_loop(&pin_insert);
if (!run_pin_entry_loop(&pin_insert)) {
// User abandoned pin entry - continue to boot screen
JADE_LOGI("User confirmation abandoned, not wiping data.");
return;
}

format_pin(pinstr, sizeof(pinstr), pin_insert.pin, sizeof(pin_insert.pin));
JADE_LOGI("User entered: %s", pinstr);
Expand Down Expand Up @@ -1199,17 +1203,25 @@ static void set_wallet_erase_pin(void)
JADE_ASSERT(pin_insert.activity);

while (true) {
reset_pin(&pin_insert, "Wallet-Erase PIN");
gui_set_current_activity(pin_insert.activity);

run_pin_entry_loop(&pin_insert);
if (!run_pin_entry_loop(&pin_insert)) {
// User abandoned pin entry
JADE_LOGI("User abandoned setting wallet erase PIN");
break;
}

// This is the first pin, copy it and clear screen fields
uint8_t pin[sizeof(pin_insert.pin)];
memcpy(pin, pin_insert.pin, sizeof(pin));
reset_pin(&pin_insert, "Confirm Erase PIN");

// Ask user to re-enter PIN
run_pin_entry_loop(&pin_insert);
if (!run_pin_entry_loop(&pin_insert)) {
// User abandoned second input - back to first ...
continue;
}

// Check that the two pins are the same
JADE_LOGD("Checking pins match");
Expand All @@ -1224,7 +1236,6 @@ static void set_wallet_erase_pin(void)
// Abandon
break;
}
reset_pin(&pin_insert, "Wallet-Erase PIN");
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion main/ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ void run_keyboard_entry_loop(keyboard_entry_t* kb_entry);

// Functions for pin entry
void make_pin_insert_activity(pin_insert_t* pin_insert, const char* title, const char* message);
void run_pin_entry_loop(pin_insert_t* pin_insert);
bool run_pin_entry_loop(pin_insert_t* pin_insert);
void reset_pin(pin_insert_t* pin_insert, const char* title);

// Generic progress-bar
Expand Down
67 changes: 26 additions & 41 deletions main/ui/pin.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ void make_pin_insert_activity(pin_insert_t* pin_insert, const char* title, const
static bool next_selected_digit(pin_insert_t* pin_insert)
{
JADE_ASSERT(pin_insert);
JADE_ASSERT(pin_insert->selected_digit < PIN_SIZE);

// make sure the '<' is not selected
JADE_ASSERT(pin_insert->current_selected_value < 10);
Expand All @@ -123,28 +124,30 @@ static bool next_selected_digit(pin_insert_t* pin_insert)
// set the status and update the ui
pin_insert->digit_status[pin_insert->selected_digit] = SET;
update_digit_node(pin_insert, pin_insert->selected_digit);

pin_insert->selected_digit++;
pin_insert->current_selected_value = get_random_pin_digit();

// finally reached the last digit
// reached the last digit - cannot select next, return false
if (pin_insert->selected_digit >= PIN_SIZE) {
return true;
return false;
}

// set the status and update the ui
pin_insert->digit_status[pin_insert->selected_digit] = SELECTED;

pin_insert->current_selected_value = get_random_pin_digit();
update_digit_node(pin_insert, pin_insert->selected_digit);

return false;
return true;
}

static void prev_selected_digit(pin_insert_t* pin_insert)
static bool prev_selected_digit(pin_insert_t* pin_insert)
{
JADE_ASSERT(pin_insert);
JADE_ASSERT(pin_insert->selected_digit < PIN_SIZE);

// at the first digit - cannot select previous, return false
if (pin_insert->selected_digit == 0) {
return;
return false;
}

// set the status and update the ui
Expand All @@ -157,34 +160,13 @@ static void prev_selected_digit(pin_insert_t* pin_insert)
// set the status and update the ui
pin_insert->digit_status[pin_insert->selected_digit] = SELECTED;
update_digit_node(pin_insert, pin_insert->selected_digit);
}

static void next_value(pin_insert_t* pin_insert)
{
JADE_ASSERT(pin_insert);

// Do not show '<' on first pin digit
const uint8_t digit_value_ceiling = pin_insert->selected_digit == 0 ? NUM_PIN_VALUES : NUM_PIN_CHARS;
pin_insert->current_selected_value = (pin_insert->current_selected_value + 1) % digit_value_ceiling;

// TODO: skip < if selected_digit == 0
update_digit_node(pin_insert, pin_insert->selected_digit);
return true;
}

static void prev_value(pin_insert_t* pin_insert)
{
JADE_ASSERT(pin_insert);

// Do not show '<' on first pin digit
const uint8_t digit_value_ceiling = pin_insert->selected_digit == 0 ? NUM_PIN_VALUES : NUM_PIN_CHARS;
pin_insert->current_selected_value
= (digit_value_ceiling + pin_insert->current_selected_value - 1) % digit_value_ceiling;

// TODO: skip < if selected_digit == 0
update_digit_node(pin_insert, pin_insert->selected_digit);
}

void run_pin_entry_loop(pin_insert_t* pin_insert)
// Returns true if pin entry completes and pin_insert->pin is valid,
// and false if pin entry abandoned and pin_insert->pin is not to be used.
bool run_pin_entry_loop(pin_insert_t* pin_insert)
{
JADE_ASSERT(pin_insert);
JADE_ASSERT(pin_insert->activity);
Expand All @@ -196,22 +178,25 @@ void run_pin_entry_loop(pin_insert_t* pin_insert)

switch (ev_id) {
case GUI_WHEEL_LEFT_EVENT:
prev_value(pin_insert);
pin_insert->current_selected_value
= (pin_insert->current_selected_value + NUM_PIN_CHARS - 1) % NUM_PIN_CHARS;
update_digit_node(pin_insert, pin_insert->selected_digit);
break;
case GUI_WHEEL_RIGHT_EVENT:
next_value(pin_insert);
pin_insert->current_selected_value = (pin_insert->current_selected_value + 1) % NUM_PIN_CHARS;
update_digit_node(pin_insert, pin_insert->selected_digit);
break;

default:
if (ev_id == gui_get_click_event()) {
if (get_pin_value(pin_insert->current_selected_value) == CHAR_BACKSPACE) {
prev_selected_digit(pin_insert);
continue;
}

// Returns true when click on last digit
if (next_selected_digit(pin_insert)) {
return;
if (!prev_selected_digit(pin_insert)) {
// Returns false when click 'backspace' on first digit (cannot move to previous)
return false; // pin entry abandoned
}
} else if (!next_selected_digit(pin_insert)) {
// Returns false when click number on last digit (cannot move to next)
return true; // pin entry complete
}
}
}
Expand Down

0 comments on commit e39515b

Please sign in to comment.