const char *words_from_data(const uint8_t *data, int len) { if (len > 32) return NULL; int mlen = len * 3 / 4; static char mnemo[24 * 10]; const char *const *wordlist = mnemonic_wordlist(); int i, j, idx; char *p = mnemo; for (i = 0; i < mlen; i++) { idx = 0; for (j = 0; j < 11; j++) { idx <<= 1; idx += (data[(i * 11 + j) / 8] & (1 << (7 - ((i * 11 + j) % 8)))) > 0; } strcpy(p, wordlist[idx]); p += strlen(wordlist[idx]); *p = (i < mlen - 1) ? ' ' : 0; p++; } return mnemo; }
void next_word(void) { word_pos = word_order[word_index]; if (word_pos == 0) { const char * const *wl = mnemonic_wordlist(); strlcpy(fake_word, wl[random_uniform(2048)], sizeof(fake_word)); layoutDialogSwipe(DIALOG_ICON_INFO, NULL, NULL, NULL, "Please enter the word", NULL, fake_word, NULL, "on your computer", NULL); } else { fake_word[0] = 0; char desc[] = "##th word"; if (word_pos < 10) { desc[0] = ' '; } else { desc[0] = '0' + word_pos / 10; } desc[1] = '0' + word_pos % 10; if (word_pos == 1 || word_pos == 21) { desc[2] = 's'; desc[3] = 't'; } else if (word_pos == 2 || word_pos == 22) { desc[2] = 'n'; desc[3] = 'd'; } else if (word_pos == 3 || word_pos == 23) { desc[2] = 'r'; desc[3] = 'd'; } layoutDialogSwipe(DIALOG_ICON_INFO, NULL, NULL, NULL, "Please enter the", NULL, (word_pos < 10 ? desc + 1 : desc), NULL, "of your mnemonic", NULL); } WordRequest resp; memset(&resp, 0, sizeof(WordRequest)); msg_write(MessageType_MessageType_WordRequest, &resp); }
void recovery_word(const char *word) { if (!awaiting_word) { fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Not in Recovery mode"); layoutHome(); return; } if (word_pos == 0) { // fake word if (strcmp(word, fake_word) != 0) { storage_reset(); fsm_sendFailure(FailureType_Failure_SyntaxError, "Wrong word retyped"); layoutHome(); return; } } else { // real word if (enforce_wordlist) { // check if word is valid const char * const *wl = mnemonic_wordlist(); bool found = false; while (*wl) { if (strcmp(word, *wl) == 0) { found = true; break; } wl++; } if (!found) { storage_reset(); fsm_sendFailure(FailureType_Failure_SyntaxError, "Word not found in a wordlist"); layoutHome(); return; } } strlcpy(words[word_pos - 1], word, sizeof(words[word_pos - 1])); } if (word_index + 1 == 24) { // last one uint32_t i; strlcpy(storage.mnemonic, words[0], sizeof(storage.mnemonic)); for (i = 1; i < word_count; i++) { strlcat(storage.mnemonic, " ", sizeof(storage.mnemonic)); strlcat(storage.mnemonic, words[i], sizeof(storage.mnemonic)); } if (!enforce_wordlist || mnemonic_check(storage.mnemonic)) { storage.has_mnemonic = true; storage_commit(); fsm_sendSuccess("Device recovered"); } else { storage_reset(); fsm_sendFailure(FailureType_Failure_SyntaxError, "Invalid mnemonic, are words in correct order?"); } awaiting_word = false; layoutHome(); } else { word_index++; next_word(); } }
void next_word(void) { word_pos = word_order[word_index]; char title_formatted[SMALL_STR_BUF]; char body_formatted[MEDIUM_STR_BUF]; /* Form title */ /* snprintf: 24 + 10 (%u) + 1 (NULL) = 35 */ snprintf(title_formatted, SMALL_STR_BUF, "Device Recovery Step %lu/24", (unsigned long)(word_index + 1)); if (word_pos == 0) { const char * const *wl = mnemonic_wordlist(); strlcpy(fake_word, wl[random_uniform(2048)], sizeof(fake_word)); /* Format body for fake word */ /* snprintf: 18 + 12 (fake_word) + 1 (NULL) = 31 */ snprintf(body_formatted, MEDIUM_STR_BUF, "Enter the word \"%s\".", fake_word); layout_standard_notification(title_formatted, body_formatted, NOTIFICATION_RECOVERY); } else { fake_word[0] = 0; char desc[] = "th word"; if (word_pos == 1 || word_pos == 21) { desc[0] = 's'; desc[1] = 't'; } else if (word_pos == 2 || word_pos == 22) { desc[0] = 'n'; desc[1] = 'd'; } else if (word_pos == 3 || word_pos == 23) { desc[0] = 'r'; desc[1] = 'd'; } /* Format body for real word */ /* snprintf: 37 + 10 (%u) + 8 (desc) + 1 (NULL) = 56 */ snprintf(body_formatted, MEDIUM_STR_BUF, "Enter the %lu%s of your recovery sentence.", (unsigned long)word_pos, desc); layout_standard_notification(title_formatted, body_formatted, NOTIFICATION_RECOVERY); } WordRequest resp; memset(&resp, 0, sizeof(WordRequest)); msg_write(MessageType_MessageType_WordRequest, &resp); }
void recovery_word(const char *word) { if (!awaiting_word) { fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Not in Recovery mode"); go_home(); return; } if (word_pos == 0) { // fake word if (strcmp(word, fake_word) != 0) { storage_reset(); fsm_sendFailure(FailureType_Failure_SyntaxError, "Wrong word retyped"); go_home(); return; } } else { // real word if (enforce_wordlist) { // check if word is valid const char * const *wl = mnemonic_wordlist(); bool found = false; while (*wl) { if (strcmp(word, *wl) == 0) { found = true; break; } wl++; } if (!found) { storage_reset(); fsm_sendFailure(FailureType_Failure_SyntaxError, "Word not found in a wordlist"); go_home(); return; } } strlcpy(words[word_pos - 1], word, sizeof(words[word_pos - 1])); } if (word_index + 1 == 24) { // last one storage_set_mnemonic_from_words((const char (*)[])words, word_count); if (!enforce_wordlist || mnemonic_check(storage_get_shadow_mnemonic())) { storage_commit(); fsm_sendSuccess("Device recovered"); } else { storage_reset(); fsm_sendFailure(FailureType_Failure_SyntaxError, "Invalid mnemonic, are words in correct order?"); } awaiting_word = false; go_home(); } else { word_index++; next_word(); } }