Skip to content

Commit

Permalink
Merge branch 'master' into alpha
Browse files Browse the repository at this point in the history
  • Loading branch information
keepkeyjon committed Jan 29, 2019
2 parents c321b68 + b21db5b commit 0e963e6
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 131 deletions.
19 changes: 19 additions & 0 deletions lib/board/font.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,21 @@ static const uint8_t image_font_sadface_9x10[9 * 10] =
};
static const CharacterImage sadface_9x10 = { image_font_sadface_9x10, 9, 10};

static const uint8_t image_font_segwit_12x10[12 * 10] =
{
0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00,
0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff,
0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff,
};
static const CharacterImage segwit_12x10 = { image_font_segwit_12x10, 12, 10};

static const uint8_t image_data_pin_font_0x31[48] =
{
0xff, 0x00, 0x00, 0x00,
Expand Down Expand Up @@ -1658,6 +1673,8 @@ static const CharacterImage title_font_0x7e = { image_data_title_font_0x7e, 7, 1

static const Character title_font_array[] =
{
/* SegWit logo */
{0x01, &segwit_12x10},

/* Character: ' ' */
{0x20, &title_font_0x20},
Expand Down Expand Up @@ -3379,6 +3396,8 @@ static const CharacterImage body_font_0x7e = { image_data_body_font_0x7e, 7, 10}

static const Character body_font_array[] =
{
/* SegWit logo */
{0x01, &segwit_12x10},

/* Character: ' ' */
{0x20, &body_font_0x20},
Expand Down
42 changes: 35 additions & 7 deletions lib/firmware/coins.c
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,30 @@ void coin_amnt_to_str(const CoinType *coin, uint64_t amnt, char *buf, int len)
}
}

static const char *account_prefix(const CoinType *coin,
const uint32_t *address_n,
size_t address_n_count,
bool whole_account) {
if (!coin->has_segwit || !coin->segwit)
return "";

if (address_n_count < (whole_account ? 3 : 5))
return NULL;

uint32_t purpose = address_n[address_n_count - (whole_account ? 3 : 5)];

if (purpose == (0x80000000 | 44))
return "";

if (purpose == (0x80000000 | 49))
return "\x01 ";

if (purpose == (0x80000000 | 84))
return "\x01 ";

return NULL;
}

bool bip32_node_to_string(char *node_str, size_t len, const CoinType *coin,
const uint32_t *address_n, size_t address_n_count,
bool whole_account, bool allow_change)
Expand Down Expand Up @@ -379,22 +403,26 @@ bool bip32_node_to_string(char *node_str, size_t len, const CoinType *coin,
!isSLIP48)
return false;

const char *prefix = account_prefix(coin, address_n, address_n_count, whole_account);
if (!prefix)
return false;

// If it is a token, we still refer to the destination as an Ethereum account.
bool is_token = coin->has_contract_address;
const char *coin_name = is_token ? "Ethereum" : coin->coin_name;

if (whole_account || isEthereumLike(coin_name)) {
snprintf(node_str, len, "%s Account #%" PRIu32, coin_name,
snprintf(node_str, len, "%s%s Account #%" PRIu32, prefix, coin_name,
address_n[2] & 0x7fffffff);
} else if (coin_isSLIP48(coin, address_n, address_n_count, SLIP48_owner)) {
snprintf(node_str, len, "%s Account #%" PRIu32 " @owner key #%" PRIu32,
coin_name, address_n[3] & 0x7fffffff, address_n[4] & 0x7fffffff);
snprintf(node_str, len, "%s%s Account #%" PRIu32 " @owner key #%" PRIu32,
prefix, coin_name, address_n[3] & 0x7fffffff, address_n[4] & 0x7fffffff);
} else if (coin_isSLIP48(coin, address_n, address_n_count, SLIP48_active)) {
snprintf(node_str, len, "%s Account #%" PRIu32 " @active key #%" PRIu32,
coin_name, address_n[3] & 0x7fffffff, address_n[4] & 0x7fffffff);
snprintf(node_str, len, "%s%s Account #%" PRIu32 " @active key #%" PRIu32,
prefix, coin_name, address_n[3] & 0x7fffffff, address_n[4] & 0x7fffffff);
} else {
snprintf(node_str, len, "%s Account #%" PRIu32 "\nAddress #%" PRIu32,
coin_name, address_n[2] & 0x7fffffff, address_n[4]);
snprintf(node_str, len, "%s%s Account #%" PRIu32 "\nAddress #%" PRIu32,
prefix, coin_name, address_n[2] & 0x7fffffff, address_n[4]);
}

return true;
Expand Down
12 changes: 4 additions & 8 deletions lib/firmware/fsm_msg_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -514,16 +514,12 @@ void fsm_msgWordAck(WordAck *msg)

void fsm_msgCharacterAck(CharacterAck *msg)
{
if(msg->has_delete && msg->del)
{
if (msg->has_delete && msg->del) {
recovery_delete_character();
}
else if(msg->has_done && msg->done)
{
} else if(msg->has_done && msg->done) {
recovery_cipher_finalize();
}
else
{
} else {
msg->character[1] = '\0';
recovery_character(msg->character);
}
}
Expand Down
149 changes: 80 additions & 69 deletions lib/firmware/recovery_cipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#include <string.h>
#include <stdio.h>

#define MAX_UNCYPHERED_WORDS (3)

static bool enforce_wordlist;
static bool awaiting_character;
static CONFIDENTIAL char mnemonic[MNEMONIC_BUF];
Expand All @@ -47,6 +49,12 @@ static void format_current_word(char *current_word, bool auto_completed);
static uint32_t get_current_word_pos(void);
static void get_current_word(char *current_word);

static void recovery_abort(void) {
awaiting_character = false;
memzero(mnemonic, sizeof(mnemonic));
memzero(cipher, sizeof(cipher));
}

/// Formats the passed word to show position in mnemonic as well as characters
/// left.
///
Expand Down Expand Up @@ -217,6 +225,7 @@ void recovery_cipher_init(bool passphrase_protection, bool pin_protection,
{
if (pin_protection) {
if (!change_pin()) {
recovery_abort();
fsm_sendFailure(FailureType_Failure_ActionCancelled, "PINs do not match");
layoutHome();
return;
Expand Down Expand Up @@ -259,52 +268,44 @@ void next_character(void)
get_current_word(current_word);

/* Words should never be longer than 4 characters */
if (strlen(current_word) > 4)
{
if (strlen(current_word) > 4) {
memzero(current_word, sizeof(current_word));
awaiting_character = false;
layoutHome();

storage_reset();
recovery_abort();
fsm_sendFailure(FailureType_Failure_SyntaxError, "Words were not entered correctly.");
layoutHome();
return;
}
else
{
CharacterRequest resp;
memset(&resp, 0, sizeof(CharacterRequest));

resp.word_pos = get_current_word_pos();
resp.character_pos = strlen(current_word);
CharacterRequest resp;
memset(&resp, 0, sizeof(CharacterRequest));

msg_write(MessageType_MessageType_CharacterRequest, &resp);

/* Attempt to auto complete if we have at least 3 characters */
bool auto_completed = false;
if (strlen(current_word) >= 3)
{
auto_completed = attempt_auto_complete(current_word);
}
resp.word_pos = get_current_word_pos();
resp.character_pos = strlen(current_word);

#if DEBUG_LINK
msg_write(MessageType_MessageType_CharacterRequest, &resp);

if(auto_completed)
{
strlcpy(auto_completed_word, current_word, CURRENT_WORD_BUF);
}
else
{
auto_completed_word[0] = '\0';
}
/* Attempt to auto complete if we have at least 3 characters */
bool auto_completed = false;
if (strlen(current_word) >= 3) {
auto_completed = attempt_auto_complete(current_word);
}

#if DEBUG_LINK
if (auto_completed) {
strlcpy(auto_completed_word, current_word, CURRENT_WORD_BUF);
} else {
auto_completed_word[0] = '\0';
}
#endif

/* Format current word and display it along with cipher */
format_current_word(current_word, auto_completed);
/* Format current word and display it along with cipher */
format_current_word(current_word, auto_completed);

/* Show cipher and partial word */
layout_cipher(current_word, cipher);
memzero(current_word, sizeof(current_word));
}
/* Show cipher and partial word */
layout_cipher(current_word, cipher);
memzero(current_word, sizeof(current_word));
}

/*
Expand All @@ -317,56 +318,66 @@ void next_character(void)
*/
void recovery_character(const char *character)
{
if (!awaiting_character) {
recovery_abort();
fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Not in Recovery mode");
layoutHome();
return;
}

char decoded_character[2] = " ", *pos;

if(strlen(mnemonic) + 1 > MNEMONIC_BUF - 1)
{
if (strlen(mnemonic) + 1 > MNEMONIC_BUF - 1) {
recovery_abort();
fsm_sendFailure(FailureType_Failure_UnexpectedMessage,
"Too many characters attempted during recovery");
layoutHome();
goto finished;
return;
}
else if(awaiting_character)
{

pos = strchr(cipher, character[0]);
char *pos = strchr(cipher, character[0]);

if(character[0] != ' ' &&
pos == NULL) /* If not a space and not a legitmate cipher character, send failure */
{

awaiting_character = false;
fsm_sendFailure(FailureType_Failure_SyntaxError, "Character must be from a to z");
layoutHome();
goto finished;
// If not a space and not a legitmate cipher character, send failure.
if (character[0] != ' ' && pos == NULL) {
recovery_abort();
fsm_sendFailure(FailureType_Failure_SyntaxError, "Character must be from a to z");
layoutHome();
return;
}

}
else if(character[0] !=
' ') /* Decode character using cipher if not space */
{
// Count of words we think the user has entered without using the cipher:
static int uncyphered_word_count = 0;
static CONFIDENTIAL char ciphered_word[12];

decoded_character[0] = english_alphabet[(int)(pos - cipher)];
if (!mnemonic[0]) {
uncyphered_word_count = 0;
memzero(ciphered_word, sizeof(ciphered_word));
}

char decoded_character[2] = " ";
if (character[0] != ' ') {
strlcat(ciphered_word, character, sizeof(ciphered_word));

// Check & bail if the user is entering their seed without using the
// cipher. Note that for each word, this can give false positives about
// ~0.4% of the time (2048/26^4).
if (enforce_wordlist && 4 <= strlen(ciphered_word) &&
attempt_auto_complete(ciphered_word) &&
MAX_UNCYPHERED_WORDS < uncyphered_word_count++) {
recovery_abort();
fsm_sendFailure(FailureType_Failure_SyntaxError, "Words were not entered correctly.");
layoutHome();
return;
}

// concat to mnemonic
strlcat(mnemonic, decoded_character, MNEMONIC_BUF);

next_character();

// Decode character using cipher if not space
decoded_character[0] = english_alphabet[(int)(pos - cipher)];
} else {
memzero(ciphered_word, sizeof(ciphered_word));
}
else
{

fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Not in Recovery mode");
layoutHome();
goto finished;

}
// concat to mnemonic
strlcat(mnemonic, decoded_character, MNEMONIC_BUF);

finished:
return;
next_character();
}

/*
Expand Down Expand Up @@ -444,7 +455,7 @@ void recovery_cipher_finalize(void)
"Invalid mnemonic, are words in correct order?");
}

awaiting_character = false;
recovery_abort();
layoutHome();
}

Expand Down
Loading

0 comments on commit 0e963e6

Please sign in to comment.