From 810d478f4c459a539d2bc4913f16faf0b0b3053b Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Tue, 8 Nov 2016 15:48:44 +0100 Subject: [PATCH 01/23] check return values of ecdsa_sign calls --- firmware/signing.c | 6 +++++- firmware/u2f.c | 13 ++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/firmware/signing.c b/firmware/signing.c index 3743092309..22dcd91b46 100644 --- a/firmware/signing.c +++ b/firmware/signing.c @@ -592,7 +592,11 @@ void signing_txack(TransactionType *tx) resp.serialized.signature_index = idx1; resp.serialized.has_signature = true; resp.serialized.has_serialized_tx = true; - ecdsa_sign_digest(&secp256k1, privkey, hash, sig, NULL, NULL); + if (ecdsa_sign_digest(&secp256k1, privkey, hash, sig, NULL, NULL) != 0) { + fsm_sendFailure(FailureType_Failure_Other, "Signing failed"); + signing_abort(); + return; + } resp.serialized.signature.size = ecdsa_sig_to_der(sig, resp.serialized.signature.bytes); if (input.script_type == InputScriptType_SPENDMULTISIG) { if (!input.has_multisig) { diff --git a/firmware/u2f.c b/firmware/u2f.c index d8b93135fc..56ee8f76bf 100644 --- a/firmware/u2f.c +++ b/firmware/u2f.c @@ -624,8 +624,10 @@ void u2f_register(const APDU *a) memcpy(sig_base.chal, req->chal, U2F_CHAL_SIZE); memcpy(sig_base.keyHandle, &resp->keyHandleCertSig, KEY_HANDLE_LEN); memcpy(sig_base.pubKey, &resp->pubKey, U2F_PUBKEY_LEN); - ecdsa_sign(&nist256p1, U2F_ATT_PRIV_KEY, (uint8_t *)&sig_base, - sizeof(sig_base), sig, NULL, NULL); + if (ecdsa_sign(&nist256p1, U2F_ATT_PRIV_KEY, (uint8_t *)&sig_base, sizeof(sig_base), sig, NULL, NULL) != 0) { + send_u2f_error(U2F_SW_WRONG_DATA); + return; + } // Where to write the signature in the response uint8_t *resp_sig = resp->keyHandleCertSig + @@ -744,9 +746,10 @@ void u2f_authenticate(const APDU *a) sig_base.flags = resp->flags; memcpy(sig_base.ctr, resp->ctr, 4); memcpy(sig_base.chal, req->chal, U2F_CHAL_SIZE); - ecdsa_sign(&nist256p1, node->private_key, - (uint8_t *)&sig_base, sizeof(sig_base), sig, - NULL, NULL); + if (ecdsa_sign(&nist256p1, node->private_key, (uint8_t *)&sig_base, sizeof(sig_base), sig, NULL, NULL) != 0) { + send_u2f_error(U2F_SW_WRONG_DATA); + return; + } // Copy DER encoded signature into response const uint8_t sig_len = ecdsa_sig_to_der(sig, resp->sig); From 4ce4cc560552c8265bb1ac6dfad36639a6a4e5dc Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Wed, 9 Nov 2016 16:06:50 +0100 Subject: [PATCH 02/23] halt the device when encountered an invalid mnemonic (skip if device loaded or recovered without enforced wordlist) --- firmware/recovery.c | 45 +++++++++++++++++++++++++++------------------ firmware/storage.c | 10 +++++++++- 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/firmware/recovery.c b/firmware/recovery.c index daa2973fb9..e92fc1d5a3 100644 --- a/firmware/recovery.c +++ b/firmware/recovery.c @@ -139,27 +139,36 @@ void recovery_word(const char *word) 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 { + if (word_index + 1 < 24) { // not the last one word_index++; next_word(); + return; } + + // the last one + strlcpy(storage.mnemonic, words[0], sizeof(storage.mnemonic)); + for (uint32_t i = 1; i < word_count; i++) { + strlcat(storage.mnemonic, " ", sizeof(storage.mnemonic)); + strlcat(storage.mnemonic, words[i], sizeof(storage.mnemonic)); + } + + awaiting_word = false; + layoutHome(); + + if (!mnemonic_check(storage.mnemonic)) { + if (enforce_wordlist) { + storage_reset(); + fsm_sendFailure(FailureType_Failure_SyntaxError, "Invalid mnemonic, are words in correct order?"); + return; + } else { // not enforcing => mark storage as imported + storage.has_imported = true; + storage.imported = true; + } + } + + storage.has_mnemonic = true; + storage_commit(); + fsm_sendSuccess("Device recovered"); } void recovery_abort(void) diff --git a/firmware/storage.c b/firmware/storage.c index 5ec381f0ab..8ef55fce77 100644 --- a/firmware/storage.c +++ b/firmware/storage.c @@ -105,7 +105,7 @@ static char sessionPassphrase[51]; void storage_show_error(void) { layoutDialog(&bmp_icon_error, NULL, NULL, NULL, "Storage failure", "detected.", NULL, "Please unplug", "the device.", NULL); - for (;;) { } + system_halt(); } void storage_check_flash_errors(void) @@ -353,6 +353,14 @@ const uint8_t *storage_getSeed(bool usePassphrase) if (usePassphrase && !protectPassphrase()) { return NULL; } + // if storage was not imported (i.e. it was properly generated or recovered) + if (!storage.has_imported || !storage.imported) { + // test whether mnemonic is a valid BIP-0039 mnemonic + if (!mnemonic_check(storage.mnemonic)) { + // and if not then halt the device + storage_show_error(); + } + } mnemonic_to_seed(storage.mnemonic, usePassphrase ? sessionPassphrase : "", sessionSeed, get_root_node_callback); // BIP-0039 sessionSeedCached = true; sessionSeedUsesPassphrase = usePassphrase; From 9287dd7e04d3347403ea536a20de891e005e17a9 Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Thu, 7 Jul 2016 18:37:37 +0200 Subject: [PATCH 03/23] Poll USB during BIP39 derivation. This patch adds calls to usbPoll in the progress callback. This should address #98. We call usbDelay instead of Poll, to call usbd_poll several times. Otherwise it would only handle one event instead of handling all events that were pending so far. The ugly magic number 5 is a guess. Note that we also need to set usbTiny, so that we don't recursively process messages. Since we don't know whether usbTiny is set, we need to store the old value (especially true for u2f). This fix also relies on another fix in libopencm3. --- firmware/storage.c | 4 ++++ firmware/usb.c | 4 +++- firmware/usb.h | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/firmware/storage.c b/firmware/storage.c index 8ef55fce77..7a13f41314 100644 --- a/firmware/storage.c +++ b/firmware/storage.c @@ -39,6 +39,7 @@ #include "debug.h" #include "protect.h" #include "layout2.h" +#include "usb.h" Storage storage; @@ -337,6 +338,7 @@ void storage_setHomescreen(const uint8_t *data, uint32_t size) void get_root_node_callback(uint32_t iter, uint32_t total) { + usbDelay(10); // handle up to ten usb interrupts. layoutProgress("Waking up", 1000 * iter / total); } @@ -361,7 +363,9 @@ const uint8_t *storage_getSeed(bool usePassphrase) storage_show_error(); } } + char oldTiny = usbTiny(1); mnemonic_to_seed(storage.mnemonic, usePassphrase ? sessionPassphrase : "", sessionSeed, get_root_node_callback); // BIP-0039 + usbTiny(oldTiny); sessionSeedCached = true; sessionSeedUsesPassphrase = usePassphrase; return sessionSeed; diff --git a/firmware/usb.c b/firmware/usb.c index 56504deee8..241d05616a 100644 --- a/firmware/usb.c +++ b/firmware/usb.c @@ -419,9 +419,11 @@ void usbReconnect(void) usbd_disconnect(usbd_dev, 0); } -void usbTiny(char set) +char usbTiny(char set) { + char old = tiny; tiny = set; + return old; } void usbDelay(int cycles) diff --git a/firmware/usb.h b/firmware/usb.h index d1dc250187..286e3a4a4d 100644 --- a/firmware/usb.h +++ b/firmware/usb.h @@ -23,7 +23,7 @@ void usbInit(void); void usbPoll(void); void usbReconnect(void); -void usbTiny(char set); +char usbTiny(char set); void usbDelay(int cycles); #endif From f45454b5ce3349f4da21c14e4a14f6158d1c3e1d Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Thu, 10 Nov 2016 13:46:41 +0100 Subject: [PATCH 04/23] u2f: add fastmail to known providers --- firmware/u2f_knownapps.h | 9 +++++++++ gen/bitmaps.c | 2 ++ gen/bitmaps.h | 1 + gen/bitmaps/u2f_fastmail.png | Bin 0 -> 226 bytes 4 files changed, 12 insertions(+) create mode 100644 gen/bitmaps/u2f_fastmail.png diff --git a/firmware/u2f_knownapps.h b/firmware/u2f_knownapps.h index 4b49046440..c39207b0d8 100644 --- a/firmware/u2f_knownapps.h +++ b/firmware/u2f_knownapps.h @@ -84,6 +84,15 @@ static const U2FWellKnown u2f_well_known[] = { 0x03, 0x39, 0x6b, 0x30, 0xe4, 0x94, 0xc8, 0x04 }, "GitLab", &bmp_u2f_gitlab + }, + { + // https://www.fastmail.com + { 0x69, 0x66, 0xab, 0xe3, 0x67, 0x4e, 0xa2, 0xf5, + 0x30, 0x79, 0xeb, 0x71, 0x01, 0x97, 0x84, 0x8c, + 0x9b, 0xe6, 0xf3, 0x63, 0x99, 0x2f, 0xd0, 0x29, + 0xe9, 0x89, 0x84, 0x47, 0xcb, 0x9f, 0x00, 0x84 }, + "FastMail", + &bmp_u2f_fastmail } }; diff --git a/gen/bitmaps.c b/gen/bitmaps.c index 13faa549e9..8a3decc464 100644 --- a/gen/bitmaps.c +++ b/gen/bitmaps.c @@ -25,6 +25,7 @@ const uint8_t bmp_logo64_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x const uint8_t bmp_logo64_empty_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x70, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x00, 0x00, 0x08, 0x00, 0x00, 0x20, 0x00, 0x00, 0x10, 0x0f, 0xe0, 0x10, 0x00, 0x00, 0x20, 0x30, 0x18, 0x08, 0x00, 0x00, 0x20, 0x40, 0x04, 0x08, 0x00, 0x00, 0x40, 0x80, 0x02, 0x04, 0x00, 0x00, 0x41, 0x00, 0x01, 0x04, 0x00, 0x00, 0x42, 0x00, 0x00, 0x84, 0x00, 0x00, 0x82, 0x00, 0x00, 0x82, 0x00, 0x00, 0x82, 0x00, 0x00, 0x82, 0x00, 0x00, 0x84, 0x00, 0x00, 0x42, 0x00, 0x00, 0x84, 0x00, 0x00, 0x42, 0x00, 0x00, 0x84, 0x00, 0x00, 0x42, 0x00, 0x00, 0x84, 0x00, 0x00, 0x42, 0x00, 0x00, 0x84, 0x00, 0x00, 0x42, 0x00, 0x00, 0x84, 0x00, 0x00, 0x42, 0x00, 0x00, 0x84, 0x00, 0x00, 0x42, 0x00, 0x00, 0x87, 0xff, 0xff, 0xc2, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x70, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x7f, 0xfc, 0x00, 0x10, 0x10, 0x3f, 0x80, 0x03, 0xf8, 0x10, 0x10, 0x40, 0x00, 0x00, 0x04, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x80, 0x00, 0x00, 0x02, 0x10, 0x10, 0x60, 0x00, 0x00, 0x0c, 0x10, 0x10, 0x1c, 0x00, 0x00, 0x70, 0x10, 0x10, 0x03, 0x00, 0x01, 0x80, 0x10, 0x10, 0x00, 0xf0, 0x1e, 0x00, 0x10, 0x10, 0x00, 0x0c, 0x60, 0x00, 0x10, 0x0e, 0x00, 0x03, 0x80, 0x00, 0xe0, 0x01, 0xc0, 0x00, 0x00, 0x07, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, 0x00, 0x0e, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x01, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; const uint8_t bmp_u2f_bitbucket_data[] = { 0x00, 0x3f, 0xf8, 0x00, 0x07, 0xff, 0xff, 0xc0, 0x1f, 0xff, 0xff, 0xf0, 0x3f, 0x00, 0x01, 0xf8, 0x3c, 0x00, 0x00, 0x78, 0x3f, 0x00, 0x01, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xf8, 0x3f, 0xf8, 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xe3, 0x8f, 0xf0, 0x1f, 0xe7, 0xcf, 0xf0, 0x1f, 0xe7, 0xcf, 0xf0, 0x1f, 0xe7, 0xcf, 0xf0, 0x0f, 0xe3, 0x8f, 0xe0, 0x0f, 0xf0, 0x1f, 0xe0, 0x0f, 0xf8, 0x3f, 0xe0, 0x07, 0xff, 0xff, 0xc0, 0x01, 0xff, 0xff, 0x00, 0x04, 0x3f, 0xf8, 0x40, 0x07, 0x00, 0x01, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x0f, 0xe0, 0x00, }; const uint8_t bmp_u2f_dropbox_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x01, 0xf0, 0x0f, 0x80, 0x07, 0xf8, 0x1f, 0xe0, 0x0f, 0xfc, 0x3f, 0xf8, 0x3f, 0xfe, 0x7f, 0xfc, 0x7f, 0xfe, 0x7f, 0xff, 0x7f, 0xfc, 0x1f, 0xfe, 0x3f, 0xf0, 0x0f, 0xfc, 0x1f, 0xe0, 0x03, 0xf8, 0x07, 0x80, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00, 0x60, 0x07, 0x80, 0x01, 0xf0, 0x1f, 0xe0, 0x03, 0xf8, 0x3f, 0xf0, 0x0f, 0xfc, 0x7f, 0xfc, 0x3f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x1f, 0xfe, 0x7f, 0xfc, 0x0f, 0xfc, 0x3f, 0xf0, 0x03, 0xf9, 0x9f, 0xc0, 0x00, 0xe3, 0xc7, 0x80, 0x00, 0x47, 0xe2, 0x00, 0x03, 0x1f, 0xf8, 0x40, 0x03, 0xff, 0xfd, 0xc0, 0x01, 0xff, 0xff, 0x80, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, }; +const uint8_t bmp_u2f_fastmail_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xf8, 0x4f, 0xff, 0xff, 0xf2, 0x67, 0xff, 0xff, 0xe6, 0x73, 0xff, 0xff, 0xce, 0x79, 0xff, 0xff, 0x9e, 0x7c, 0xff, 0xff, 0x3e, 0x7e, 0x7f, 0xfe, 0x7e, 0x7f, 0x3f, 0xfc, 0xfe, 0x7f, 0x9f, 0xf9, 0xfe, 0x7f, 0xcf, 0xf3, 0xfe, 0x7f, 0xe7, 0xe7, 0xfe, 0x7f, 0xf3, 0xcf, 0xfe, 0x7f, 0xf8, 0x1f, 0xfe, 0x7f, 0xfc, 0x3f, 0xfe, 0x7f, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; const uint8_t bmp_u2f_github_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x78, 0x1f, 0x80, 0x01, 0xf8, 0x1f, 0xe0, 0x03, 0xf8, 0x1f, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x00, 0x1f, 0xf8, 0x20, 0x04, 0x1f, 0xf0, 0x70, 0x0e, 0x0f, 0x70, 0xf0, 0x0f, 0x0e, 0x70, 0xf8, 0x1f, 0x0e, 0x70, 0x70, 0x0e, 0x0e, 0x30, 0x70, 0x0e, 0x0c, 0x38, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x38, 0x0e, 0x00, 0x00, 0x70, 0x07, 0x80, 0x01, 0xe0, 0x01, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; const uint8_t bmp_u2f_gitlab_data[] = { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x70, 0x0f, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf8, 0x1f, 0x80, 0x01, 0xf8, 0x1f, 0x80, 0x01, 0xf8, 0x1f, 0x80, 0x01, 0xf8, 0x3f, 0xc0, 0x03, 0xfc, 0x3f, 0xc0, 0x03, 0xfc, 0x3f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xc0, 0x01, 0xff, 0xff, 0x80, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, }; const uint8_t bmp_u2f_google_data[] = { 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x01, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xc0, 0x07, 0xf0, 0x0f, 0xe0, 0x0f, 0xc0, 0x03, 0xf0, 0x1f, 0x00, 0x01, 0xf8, 0x3e, 0x00, 0x00, 0xfc, 0x3c, 0x00, 0x01, 0xfc, 0x7c, 0x0f, 0xf3, 0xfe, 0x78, 0x1f, 0xff, 0xfe, 0x78, 0x3f, 0xff, 0xfe, 0xf0, 0x3f, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0xf0, 0x7f, 0x00, 0x1f, 0xf0, 0x7f, 0x00, 0x1f, 0xf0, 0x7f, 0x00, 0x1f, 0xf0, 0x7f, 0x00, 0x1f, 0xf0, 0x7f, 0xfe, 0x1f, 0xf0, 0x3f, 0xfe, 0x1f, 0x78, 0x3f, 0xfc, 0x1e, 0x78, 0x1f, 0xf8, 0x3e, 0x7c, 0x07, 0xf0, 0x3e, 0x3c, 0x00, 0x00, 0x7c, 0x3e, 0x00, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xf8, 0x0f, 0xc0, 0x03, 0xf0, 0x07, 0xf0, 0x0f, 0xe0, 0x03, 0xff, 0xff, 0xc0, 0x01, 0xff, 0xff, 0x80, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x0f, 0xf0, 0x00, }; @@ -55,6 +56,7 @@ const BITMAP bmp_logo64 = {48, 64, bmp_logo64_data}; const BITMAP bmp_logo64_empty = {48, 64, bmp_logo64_empty_data}; const BITMAP bmp_u2f_bitbucket = {32, 32, bmp_u2f_bitbucket_data}; const BITMAP bmp_u2f_dropbox = {32, 32, bmp_u2f_dropbox_data}; +const BITMAP bmp_u2f_fastmail = {32, 32, bmp_u2f_fastmail_data}; const BITMAP bmp_u2f_github = {32, 32, bmp_u2f_github_data}; const BITMAP bmp_u2f_gitlab = {32, 32, bmp_u2f_gitlab_data}; const BITMAP bmp_u2f_google = {32, 32, bmp_u2f_google_data}; diff --git a/gen/bitmaps.h b/gen/bitmaps.h index e109fd637d..dd26f5a74c 100644 --- a/gen/bitmaps.h +++ b/gen/bitmaps.h @@ -33,6 +33,7 @@ extern const BITMAP bmp_logo64; extern const BITMAP bmp_logo64_empty; extern const BITMAP bmp_u2f_bitbucket; extern const BITMAP bmp_u2f_dropbox; +extern const BITMAP bmp_u2f_fastmail; extern const BITMAP bmp_u2f_github; extern const BITMAP bmp_u2f_gitlab; extern const BITMAP bmp_u2f_google; diff --git a/gen/bitmaps/u2f_fastmail.png b/gen/bitmaps/u2f_fastmail.png new file mode 100644 index 0000000000000000000000000000000000000000..20d05d163046417c8516776966dd1c7fd378501d GIT binary patch literal 226 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJm7Xq+ArXh)PInY)P~dPq`0-!( zHqo;g84g^!1y{FJuAlUumvMpP11*6)K?*SoF1cp!s}>aeZSG)h^Kd(Z?cR14!;Z*f z{slovE%s&)JvsT#`5ol!l&rC8vsMlJkjnRFLPhg_wu|DNoH0{c#5gr$WR6O4^2S_c z72?#5iFMQFc0Nobmr@l`|iP1`cJp8K)x*E!)pu0PHPKHFHZi9cH($>qWw ZGvi;Fn|RBFsX#|Fc)I$ztaD0e0swITP%8ic literal 0 HcmV?d00001 From 3cede26fbc1dd5194403f8694323c1efb2426be9 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Tue, 15 Nov 2016 18:51:29 +0100 Subject: [PATCH 05/23] add yubico u2f demo to u2f known apps --- firmware/u2f_knownapps.h | 9 +++++++++ gen/bitmaps.c | 2 ++ gen/bitmaps.h | 1 + gen/bitmaps/u2f_yubico.png | Bin 0 -> 253 bytes 4 files changed, 12 insertions(+) create mode 100644 gen/bitmaps/u2f_yubico.png diff --git a/firmware/u2f_knownapps.h b/firmware/u2f_knownapps.h index c39207b0d8..2fda7630ce 100644 --- a/firmware/u2f_knownapps.h +++ b/firmware/u2f_knownapps.h @@ -93,6 +93,15 @@ static const U2FWellKnown u2f_well_known[] = { 0xe9, 0x89, 0x84, 0x47, 0xcb, 0x9f, 0x00, 0x84 }, "FastMail", &bmp_u2f_fastmail + }, + { + // https://demo.yubico.com + { 0x55, 0x67, 0x3b, 0x51, 0x38, 0xcc, 0x90, 0xd3, + 0xb7, 0xf3, 0x2b, 0xfd, 0xad, 0x6a, 0x38, 0xa8, + 0xed, 0xd7, 0xb3, 0x55, 0xb7, 0x7a, 0xb9, 0x79, + 0x21, 0x96, 0xf1, 0x06, 0xd1, 0x6c, 0xa3, 0x12 }, + "Yubico U2F Demo", + &bmp_u2f_yubico } }; diff --git a/gen/bitmaps.c b/gen/bitmaps.c index 8a3decc464..4ee1a7e9e2 100644 --- a/gen/bitmaps.c +++ b/gen/bitmaps.c @@ -30,6 +30,7 @@ const uint8_t bmp_u2f_github_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 const uint8_t bmp_u2f_gitlab_data[] = { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x20, 0x06, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x70, 0x0f, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf8, 0x1f, 0x80, 0x01, 0xf8, 0x1f, 0x80, 0x01, 0xf8, 0x1f, 0x80, 0x01, 0xf8, 0x3f, 0xc0, 0x03, 0xfc, 0x3f, 0xc0, 0x03, 0xfc, 0x3f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xc0, 0x01, 0xff, 0xff, 0x80, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, }; const uint8_t bmp_u2f_google_data[] = { 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x01, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xc0, 0x07, 0xf0, 0x0f, 0xe0, 0x0f, 0xc0, 0x03, 0xf0, 0x1f, 0x00, 0x01, 0xf8, 0x3e, 0x00, 0x00, 0xfc, 0x3c, 0x00, 0x01, 0xfc, 0x7c, 0x0f, 0xf3, 0xfe, 0x78, 0x1f, 0xff, 0xfe, 0x78, 0x3f, 0xff, 0xfe, 0xf0, 0x3f, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0xf0, 0x7f, 0x00, 0x1f, 0xf0, 0x7f, 0x00, 0x1f, 0xf0, 0x7f, 0x00, 0x1f, 0xf0, 0x7f, 0x00, 0x1f, 0xf0, 0x7f, 0xfe, 0x1f, 0xf0, 0x3f, 0xfe, 0x1f, 0x78, 0x3f, 0xfc, 0x1e, 0x78, 0x1f, 0xf8, 0x3e, 0x7c, 0x07, 0xf0, 0x3e, 0x3c, 0x00, 0x00, 0x7c, 0x3e, 0x00, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xf8, 0x0f, 0xc0, 0x03, 0xf0, 0x07, 0xf0, 0x0f, 0xe0, 0x03, 0xff, 0xff, 0xc0, 0x01, 0xff, 0xff, 0x80, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x0f, 0xf0, 0x00, }; const uint8_t bmp_u2f_slushpool_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x01, 0xee, 0x00, 0x01, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xc0, 0x01, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xf8, 0x00, 0xfe, 0x0f, 0xf8, 0x00, 0xfe, 0x03, 0xf8, 0x00, 0xfc, 0x03, 0xf8, 0x00, 0xfc, 0x03, 0xf8, 0x01, 0xfc, 0x03, 0xf8, 0x01, 0xfc, 0x03, 0xf0, 0x01, 0xfc, 0x07, 0xf0, 0x01, 0xfc, 0x1f, 0xf0, 0x0f, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xc0, 0x0f, 0xff, 0xff, 0x00, 0x0f, 0xff, 0xfc, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; +const uint8_t bmp_u2f_yubico_data[] = { 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x01, 0xff, 0xff, 0x80, 0x03, 0xfc, 0x3f, 0xc0, 0x07, 0xe0, 0x07, 0xe0, 0x0f, 0x80, 0x01, 0xf0, 0x1f, 0x00, 0x00, 0x78, 0x3e, 0x00, 0x00, 0x3c, 0x3c, 0x7c, 0x1f, 0x3c, 0x78, 0x7c, 0x1f, 0x1e, 0x78, 0x7c, 0x3e, 0x0e, 0xf0, 0x3e, 0x3e, 0x0f, 0xf0, 0x3e, 0x3c, 0x0f, 0xf0, 0x1f, 0x7c, 0x0f, 0xe0, 0x1f, 0x7c, 0x07, 0xe0, 0x1f, 0x78, 0x07, 0xe0, 0x0f, 0xf8, 0x07, 0xe0, 0x0f, 0xf0, 0x07, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x07, 0xf0, 0x0f, 0xf0, 0x07, 0xe0, 0x0f, 0x78, 0x03, 0xe0, 0x0e, 0x78, 0x07, 0xc0, 0x1e, 0x3c, 0x07, 0xc0, 0x3e, 0x3c, 0x0f, 0xc0, 0x3c, 0x1e, 0x0f, 0x80, 0x78, 0x0f, 0x8f, 0x81, 0xf0, 0x07, 0xc0, 0x03, 0xe0, 0x03, 0xfc, 0x3f, 0xc0, 0x01, 0xff, 0xff, 0x80, 0x00, 0x7f, 0xff, 0x00, 0x00, 0x1f, 0xf8, 0x00, }; const BITMAP bmp_digit0 = {16, 16, bmp_digit0_data}; const BITMAP bmp_digit1 = {16, 16, bmp_digit1_data}; @@ -61,3 +62,4 @@ const BITMAP bmp_u2f_github = {32, 32, bmp_u2f_github_data}; const BITMAP bmp_u2f_gitlab = {32, 32, bmp_u2f_gitlab_data}; const BITMAP bmp_u2f_google = {32, 32, bmp_u2f_google_data}; const BITMAP bmp_u2f_slushpool = {32, 32, bmp_u2f_slushpool_data}; +const BITMAP bmp_u2f_yubico = {32, 32, bmp_u2f_yubico_data}; diff --git a/gen/bitmaps.h b/gen/bitmaps.h index dd26f5a74c..e6e1b0b479 100644 --- a/gen/bitmaps.h +++ b/gen/bitmaps.h @@ -38,5 +38,6 @@ extern const BITMAP bmp_u2f_github; extern const BITMAP bmp_u2f_gitlab; extern const BITMAP bmp_u2f_google; extern const BITMAP bmp_u2f_slushpool; +extern const BITMAP bmp_u2f_yubico; #endif diff --git a/gen/bitmaps/u2f_yubico.png b/gen/bitmaps/u2f_yubico.png new file mode 100644 index 0000000000000000000000000000000000000000..c4bc1f0a280ddee04f59b57898c707ecede0425d GIT binary patch literal 253 zcmVCz?)ilsvs_|?z(PRu*NGgGS^ z#zRDh20DqTSAVT=q+?d~9>yw+(x@gU_FBuG=SyQX?J+iHYJH4NckruYrU|iDU=000000NkvXXu0mjf D(wu7= literal 0 HcmV?d00001 From 25b9bfd97b0a1c03ae3a82db131df35a9561a2b5 Mon Sep 17 00:00:00 2001 From: Saleem Rashid Date: Thu, 17 Nov 2016 19:07:41 +0000 Subject: [PATCH 06/23] timer: Use Cortex-M3 SysTick timers Removed `usbDelay(uint32_t cycles)`, added `usbSleep(uint32_t millis)` The same method signature could cause silent code breakage at runtime, as opposed to noisy code breakage at compile time which is the better kind. --- Makefile | 1 + firmware/protect.c | 4 +-- firmware/storage.c | 2 +- firmware/trezor.c | 8 ++++-- firmware/usb.c | 6 +++-- firmware/usb.h | 2 +- timer.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ timer.h | 28 +++++++++++++++++++++ 8 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 timer.c create mode 100644 timer.h diff --git a/Makefile b/Makefile index bbb79ccd01..747da6dc67 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ OBJS += serialno.o OBJS += setup.o OBJS += util.o OBJS += memory.o +OBJS += timer.o OBJS += gen/bitmaps.o OBJS += gen/fonts.o diff --git a/firmware/protect.c b/firmware/protect.c index 715cf2116a..8ba3298c56 100644 --- a/firmware/protect.c +++ b/firmware/protect.c @@ -58,7 +58,7 @@ bool protectButton(ButtonRequestType type, bool confirm_only) // button acked - check buttons if (acked) { - usbDelay(3300); + usbSleep(5); buttonUpdate(); if (button.YesUp) { result = true; @@ -165,7 +165,7 @@ bool protectPin(bool use_cached) } layoutDialog(&bmp_icon_info, NULL, NULL, NULL, "Wrong PIN entered", NULL, "Please wait", secstr, "to continue ...", NULL); // wait one second - usbDelay(800000); + usbSleep(1000); if (msg_tiny_id == MessageType_MessageType_Initialize) { protectAbortedByInitialize = true; msg_tiny_id = 0xFFFF; diff --git a/firmware/storage.c b/firmware/storage.c index 7a13f41314..97f5f6a5ef 100644 --- a/firmware/storage.c +++ b/firmware/storage.c @@ -338,7 +338,7 @@ void storage_setHomescreen(const uint8_t *data, uint32_t size) void get_root_node_callback(uint32_t iter, uint32_t total) { - usbDelay(10); // handle up to ten usb interrupts. + usbSleep(1); layoutProgress("Waking up", 1000 * iter / total); } diff --git a/firmware/trezor.c b/firmware/trezor.c index 487a5e5c5a..a56e3d2e71 100644 --- a/firmware/trezor.c +++ b/firmware/trezor.c @@ -27,6 +27,7 @@ #include "layout.h" #include "layout2.h" #include "rng.h" +#include "timer.h" #include "buttons.h" uint32_t __stack_chk_guard; @@ -58,13 +59,13 @@ void check_lock_screen(void) // wait until NoButton is released usbTiny(1); do { - usbDelay(3300); + usbSleep(5); buttonUpdate(); } while (!button.NoUp); // wait for confirmation/cancellation of the dialog do { - usbDelay(3300); + usbSleep(5); buttonUpdate(); } while (!button.YesUp && !button.NoUp); usbTiny(0); @@ -102,6 +103,9 @@ int main(void) #else setupApp(); #endif + + timer_init(); + #if DEBUG_LINK oledSetDebug(1); storage_reset(); // wipe storage if debug link diff --git a/firmware/usb.c b/firmware/usb.c index 241d05616a..df50f1640e 100644 --- a/firmware/usb.c +++ b/firmware/usb.c @@ -27,6 +27,7 @@ #include "u2f.h" #include "storage.h" #include "util.h" +#include "timer.h" #define USB_INTERFACE_INDEX_MAIN 0 #if DEBUG_LINK @@ -426,9 +427,10 @@ char usbTiny(char set) return old; } -void usbDelay(int cycles) +void usbSleep(uint32_t millis) { - while (cycles--) { + uint32_t end = system_millis + millis; + while (end > system_millis) { usbd_poll(usbd_dev); } } diff --git a/firmware/usb.h b/firmware/usb.h index 286e3a4a4d..318a5a4ad2 100644 --- a/firmware/usb.h +++ b/firmware/usb.h @@ -24,6 +24,6 @@ void usbInit(void); void usbPoll(void); void usbReconnect(void); char usbTiny(char set); -void usbDelay(int cycles); +void usbSleep(uint32_t millis); #endif diff --git a/timer.c b/timer.c new file mode 100644 index 0000000000..2be93e8937 --- /dev/null +++ b/timer.c @@ -0,0 +1,61 @@ +/* + * This file is part of the TREZOR project. + * + * Copyright (C) 2016 Saleem Rashid + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + + +#include "timer.h" + +#include +#include + +/* 1 tick = 1 ms */ +volatile uint32_t system_millis; + +/* + * Initialise the Cortex-M3 SysTick timer + */ +void timer_init(void) { + system_millis = 0; + + /* + * MCU clock (120 MHz) as source + * + * (120 MHz / 8) = 15 clock pulses + * + */ + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); + STK_CVR = 0; + + /* + * 1 tick = 1 ms @ 120 MHz + * + * (15 clock pulses * 1000 ms) = 15000 clock pulses + * + * Send an interrupt every (N - 1) clock pulses + */ + systick_set_reload(14999); + + /* SysTick as interrupt */ + systick_interrupt_enable(); + + systick_counter_enable(); +} + +void sys_tick_handler(void) { + system_millis++; +} diff --git a/timer.h b/timer.h new file mode 100644 index 0000000000..a69879c93d --- /dev/null +++ b/timer.h @@ -0,0 +1,28 @@ +/* + * This file is part of the TREZOR project. + * + * Copyright (C) 2016 Saleem Rashid + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + + +#include + +/* 1 tick = 1 ms */ +extern volatile uint32_t system_millis; + +void timer_init(void); + +void sys_tick_handler(void); From 0ec32a61468efcbdf8a8a2e6e10a0b4c0ea76c9c Mon Sep 17 00:00:00 2001 From: Saleem Rashid Date: Thu, 17 Nov 2016 19:10:57 +0000 Subject: [PATCH 07/23] timer: Replace screen timeout with SysTick This provides an incredibly accurate screen timeout and removes the superfluous screen timeout counter --- firmware/layout2.c | 4 ++++ firmware/trezor.c | 9 +-------- timer.c | 3 +++ timer.h | 5 +++++ 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/firmware/layout2.c b/firmware/layout2.c index e7d49262ab..91c409b6e6 100644 --- a/firmware/layout2.c +++ b/firmware/layout2.c @@ -28,6 +28,7 @@ #include "string.h" #include "util.h" #include "qr_encode.h" +#include "timer.h" void *layoutLast = layoutHome; @@ -81,6 +82,9 @@ void layoutHome(void) } } oledRefresh(); + + // Reset lock screen timeout + system_millis_lock = system_millis + SCREEN_TIMEOUT_MILLIS; } const char *str_amount(uint64_t amnt, const char *abbr, char *buf, int len) diff --git a/firmware/trezor.c b/firmware/trezor.c index a56e3d2e71..129fd61a4e 100644 --- a/firmware/trezor.c +++ b/firmware/trezor.c @@ -38,15 +38,12 @@ void __attribute__((noreturn)) __stack_chk_fail(void) for (;;) {} // loop forever } -static uint32_t saver_counter = 0; - void check_lock_screen(void) { buttonUpdate(); // wake from screensaver on any button if (layoutLast == layoutScreensaver && (button.NoUp || button.YesUp)) { - saver_counter = 0; layoutHome(); return; } @@ -82,15 +79,11 @@ void check_lock_screen(void) // if homescreen is shown for longer than 10 minutes, lock too if (layoutLast == layoutHome) { - saver_counter++; - if (saver_counter > 285000 * 60 * 10) { + if (system_millis >= system_millis_lock) { // lock the screen session_clear(true); layoutScreensaver(); - saver_counter = 0; } - } else { - saver_counter = 0; } } diff --git a/timer.c b/timer.c index 2be93e8937..e45ce740f0 100644 --- a/timer.c +++ b/timer.c @@ -26,6 +26,9 @@ /* 1 tick = 1 ms */ volatile uint32_t system_millis; +/* Screen timeout */ +uint32_t system_millis_lock; + /* * Initialise the Cortex-M3 SysTick timer */ diff --git a/timer.h b/timer.h index a69879c93d..53713cdfe5 100644 --- a/timer.h +++ b/timer.h @@ -23,6 +23,11 @@ /* 1 tick = 1 ms */ extern volatile uint32_t system_millis; +/* Screen timeout */ +extern uint32_t system_millis_lock; + +#define SCREEN_TIMEOUT_MILLIS (1000 * 60 * 10) /* 10 minutes */ + void timer_init(void); void sys_tick_handler(void); From 27a4e417079b0f023d0e1cf8e43438a2bac7c6e5 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Tue, 22 Nov 2016 20:00:22 +0100 Subject: [PATCH 08/23] refactor forgotten disabled coinByName usage --- firmware/fsm.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/firmware/fsm.c b/firmware/fsm.c index ca3c997cdc..67c1141cf8 100644 --- a/firmware/fsm.c +++ b/firmware/fsm.c @@ -941,15 +941,11 @@ void fsm_msgEncryptMessage(EncryptMessage *msg) bool display_only = msg->has_display_only && msg->display_only; bool signing = msg->address_n_count > 0; RESP_INIT(EncryptedMessage); - const CoinType *coin = 0; const HDNode *node = 0; uint8_t address_raw[MAX_ADDR_RAW_SIZE]; if (signing) { - coin = coinByName(msg->coin_name); - if (!coin) { - fsm_sendFailure(FailureType_Failure_Other, "Invalid coin name"); - return; - } + const CoinType *coin = fsm_getCoin(msg->coin_name); + if (!coin) return; if (!protectPin(true)) { layoutHome(); return; From 0ef70164a59ef181f49a6de47b397498f41b2b96 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Tue, 22 Nov 2016 20:57:45 +0100 Subject: [PATCH 09/23] extract CHECK_INITIALIZED and CHECK_NOT_INITIALIZED macros --- firmware/fsm.c | 89 ++++++++++++++++++-------------------------------- 1 file changed, 32 insertions(+), 57 deletions(-) diff --git a/firmware/fsm.c b/firmware/fsm.c index 67c1141cf8..bd66d387b2 100644 --- a/firmware/fsm.c +++ b/firmware/fsm.c @@ -53,10 +53,23 @@ static uint8_t msg_resp[MSG_OUT_SIZE] __attribute__ ((aligned)); -#define RESP_INIT(TYPE) TYPE *resp = (TYPE *) (void *) msg_resp; \ +#define RESP_INIT(TYPE) \ + TYPE *resp = (TYPE *) (void *) msg_resp; \ _Static_assert(sizeof(msg_resp) >= sizeof(TYPE), #TYPE " is too large"); \ memset(resp, 0, sizeof(TYPE)); +#define CHECK_INITIALIZED \ + if (!storage_isInitialized()) { \ + fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized"); \ + return; \ + } + +#define CHECK_NOT_INITIALIZED \ + if (storage_isInitialized()) { \ + fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Device is already initialized. Use Wipe first."); \ + return; \ + } + void fsm_sendSuccess(const char *text) { RESP_INIT(Success); @@ -285,10 +298,7 @@ void fsm_msgGetPublicKey(GetPublicKey *msg) { RESP_INIT(PublicKey); - if (!storage_isInitialized()) { - fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized"); - return; - } + CHECK_INITIALIZED if (!protectPin(true)) { layoutHome(); @@ -345,10 +355,7 @@ void fsm_msgGetPublicKey(GetPublicKey *msg) void fsm_msgLoadDevice(LoadDevice *msg) { - if (storage_isInitialized()) { - fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Device is already initialized. Use Wipe first."); - return; - } + CHECK_NOT_INITIALIZED layoutDialogSwipe(&bmp_icon_question, "Cancel", "I take the risk", NULL, "Loading private seed", "is not recommended.", "Continue only if you", "know what you are", "doing!", NULL); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { @@ -373,10 +380,7 @@ void fsm_msgLoadDevice(LoadDevice *msg) void fsm_msgResetDevice(ResetDevice *msg) { - if (storage_isInitialized()) { - fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Device is already initialized. Use Wipe first."); - return; - } + CHECK_NOT_INITIALIZED reset_init( msg->has_display_random && msg->display_random, @@ -391,10 +395,7 @@ void fsm_msgResetDevice(ResetDevice *msg) void fsm_msgSignTx(SignTx *msg) { - if (!storage_isInitialized()) { - fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized"); - return; - } + CHECK_INITIALIZED if (msg->inputs_count < 1) { fsm_sendFailure(FailureType_Failure_Other, "Transaction must have at least one input"); @@ -441,10 +442,7 @@ void fsm_msgCancel(Cancel *msg) void fsm_msgEthereumSignTx(EthereumSignTx *msg) { - if (!storage_isInitialized()) { - fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized"); - return; - } + CHECK_INITIALIZED if (!protectPin(true)) { layoutHome(); @@ -464,10 +462,8 @@ void fsm_msgEthereumTxAck(EthereumTxAck *msg) void fsm_msgCipherKeyValue(CipherKeyValue *msg) { - if (!storage_isInitialized()) { - fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized"); - return; - } + CHECK_INITIALIZED + if (!msg->has_key) { fsm_sendFailure(FailureType_Failure_SyntaxError, "No key provided"); return; @@ -593,10 +589,7 @@ void fsm_msgGetAddress(GetAddress *msg) { RESP_INIT(Address); - if (!storage_isInitialized()) { - fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized"); - return; - } + CHECK_INITIALIZED if (!protectPin(true)) { layoutHome(); @@ -658,10 +651,7 @@ void fsm_msgEthereumGetAddress(EthereumGetAddress *msg) { RESP_INIT(EthereumAddress); - if (!storage_isInitialized()) { - fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized"); - return; - } + CHECK_INITIALIZED if (!protectPin(true)) { layoutHome(); @@ -708,10 +698,7 @@ void fsm_msgSignMessage(SignMessage *msg) { RESP_INIT(MessageSignature); - if (!storage_isInitialized()) { - fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized"); - return; - } + CHECK_INITIALIZED layoutSignMessage(msg->message.bytes, msg->message.size); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { @@ -786,10 +773,7 @@ void fsm_msgSignIdentity(SignIdentity *msg) { RESP_INIT(SignedIdentity); - if (!storage_isInitialized()) { - fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized"); - return; - } + CHECK_INITIALIZED layoutSignIdentity(&(msg->identity), msg->has_challenge_visual ? msg->challenge_visual : 0); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { @@ -868,10 +852,7 @@ void fsm_msgGetECDHSessionKey(GetECDHSessionKey *msg) { RESP_INIT(ECDHSessionKey); - if (!storage_isInitialized()) { - fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized"); - return; - } + CHECK_INITIALIZED layoutDecryptIdentity(&msg->identity); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { @@ -921,10 +902,8 @@ void fsm_msgGetECDHSessionKey(GetECDHSessionKey *msg) /* ECIES disabled void fsm_msgEncryptMessage(EncryptMessage *msg) { - if (!storage_isInitialized()) { - fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized"); - return; - } + CHECK_INITIALIZED + if (!msg->has_pubkey) { fsm_sendFailure(FailureType_Failure_SyntaxError, "No public key provided"); return; @@ -975,10 +954,8 @@ void fsm_msgEncryptMessage(EncryptMessage *msg) void fsm_msgDecryptMessage(DecryptMessage *msg) { - if (!storage_isInitialized()) { - fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized"); - return; - } + CHECK_INITIALIZED + if (!msg->has_nonce) { fsm_sendFailure(FailureType_Failure_SyntaxError, "No nonce provided"); return; @@ -1042,10 +1019,8 @@ void fsm_msgEstimateTxSize(EstimateTxSize *msg) void fsm_msgRecoveryDevice(RecoveryDevice *msg) { - if (storage_isInitialized()) { - fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Device is already initialized. Use Wipe first."); - return; - } + CHECK_NOT_INITIALIZED + recovery_init( msg->has_word_count ? msg->word_count : 12, msg->has_passphrase_protection && msg->passphrase_protection, From a1226156636af92ec916179755261421de1de28c Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Tue, 22 Nov 2016 21:06:39 +0100 Subject: [PATCH 10/23] extract CHECK_PIN and CHECK_PIN_UNCACHED --- firmware/fsm.c | 92 ++++++++++++++++++++------------------------------ 1 file changed, 36 insertions(+), 56 deletions(-) diff --git a/firmware/fsm.c b/firmware/fsm.c index bd66d387b2..5113ad12dc 100644 --- a/firmware/fsm.c +++ b/firmware/fsm.c @@ -70,6 +70,18 @@ static uint8_t msg_resp[MSG_OUT_SIZE] __attribute__ ((aligned)); return; \ } +#define CHECK_PIN \ + if (!protectPin(true)) { \ + layoutHome(); \ + return; \ + } + +#define CHECK_PIN_UNCACHED \ + if (!protectPin(false)) { \ + layoutHome(); \ + return; \ + } + void fsm_sendSuccess(const char *text) { RESP_INIT(Success); @@ -184,10 +196,7 @@ void fsm_msgPing(Ping *msg) } if (msg->has_pin_protection && msg->pin_protection) { - if (!protectPin(true)) { - layoutHome(); - return; - } + CHECK_PIN } if (msg->has_passphrase_protection && msg->passphrase_protection) { @@ -227,10 +236,9 @@ void fsm_msgChangePin(ChangePin *msg) layoutHome(); return; } - if (!protectPin(false)) { - layoutHome(); - return; - } + + CHECK_PIN_UNCACHED + if (removal) { storage_setPin(0); fsm_sendSuccess("PIN removed"); @@ -300,10 +308,7 @@ void fsm_msgGetPublicKey(GetPublicKey *msg) CHECK_INITIALIZED - if (!protectPin(true)) { - layoutHome(); - return; - } + CHECK_PIN const char *curve = SECP256K1_NAME; if (msg->has_ecdsa_curve_name) { @@ -409,10 +414,7 @@ void fsm_msgSignTx(SignTx *msg) return; } - if (!protectPin(true)) { - layoutHome(); - return; - } + CHECK_PIN const CoinType *coin = fsm_getCoin(msg->coin_name); if (!coin) return; @@ -444,10 +446,7 @@ void fsm_msgEthereumSignTx(EthereumSignTx *msg) { CHECK_INITIALIZED - if (!protectPin(true)) { - layoutHome(); - return; - } + CHECK_PIN const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count); if (!node) return; @@ -476,10 +475,9 @@ void fsm_msgCipherKeyValue(CipherKeyValue *msg) fsm_sendFailure(FailureType_Failure_SyntaxError, "Value length must be a multiple of 16"); return; } - if (!protectPin(true)) { - layoutHome(); - return; - } + + CHECK_PIN + const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count); if (!node) return; @@ -564,10 +562,9 @@ void fsm_msgApplySettings(ApplySettings *msg) fsm_sendFailure(FailureType_Failure_SyntaxError, "No setting provided"); return; } - if (!protectPin(true)) { - layoutHome(); - return; - } + + CHECK_PIN + if (msg->has_label) { storage_setLabel(msg->label); } @@ -591,10 +588,7 @@ void fsm_msgGetAddress(GetAddress *msg) CHECK_INITIALIZED - if (!protectPin(true)) { - layoutHome(); - return; - } + CHECK_PIN const CoinType *coin = fsm_getCoin(msg->coin_name); if (!coin) return; @@ -653,10 +647,7 @@ void fsm_msgEthereumGetAddress(EthereumGetAddress *msg) CHECK_INITIALIZED - if (!protectPin(true)) { - layoutHome(); - return; - } + CHECK_PIN const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count); if (!node) return; @@ -707,10 +698,7 @@ void fsm_msgSignMessage(SignMessage *msg) return; } - if (!protectPin(true)) { - layoutHome(); - return; - } + CHECK_PIN const CoinType *coin = fsm_getCoin(msg->coin_name); if (!coin) return; @@ -782,10 +770,7 @@ void fsm_msgSignIdentity(SignIdentity *msg) return; } - if (!protectPin(true)) { - layoutHome(); - return; - } + CHECK_PIN uint8_t hash[32]; if (!msg->has_identity || cryptoIdentityFingerprint(&(msg->identity), hash) == 0) { @@ -861,10 +846,7 @@ void fsm_msgGetECDHSessionKey(GetECDHSessionKey *msg) return; } - if (!protectPin(true)) { - layoutHome(); - return; - } + CHECK_PIN uint8_t hash[32]; if (!msg->has_identity || cryptoIdentityFingerprint(&(msg->identity), hash) == 0) { @@ -925,10 +907,9 @@ void fsm_msgEncryptMessage(EncryptMessage *msg) if (signing) { const CoinType *coin = fsm_getCoin(msg->coin_name); if (!coin) return; - if (!protectPin(true)) { - layoutHome(); - return; - } + + CHECK_PIN + node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count); if (!node) return; hdnode_get_address_raw(node, coin->address_type, address_raw); @@ -973,10 +954,9 @@ void fsm_msgDecryptMessage(DecryptMessage *msg) fsm_sendFailure(FailureType_Failure_SyntaxError, "Invalid nonce provided"); return; } - if (!protectPin(true)) { - layoutHome(); - return; - } + + CHECK_PIN + const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count); if (!node) return; From c4d144a82e00f964727b8ab97418196c552f2b39 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Tue, 22 Nov 2016 21:39:33 +0100 Subject: [PATCH 11/23] extract CHECK_PARAM --- firmware/fsm.c | 107 +++++++++++++++----------------------------- firmware/recovery.c | 6 +-- firmware/reset.c | 6 +-- 3 files changed, 39 insertions(+), 80 deletions(-) diff --git a/firmware/fsm.c b/firmware/fsm.c index 5113ad12dc..c3adea3948 100644 --- a/firmware/fsm.c +++ b/firmware/fsm.c @@ -82,6 +82,13 @@ static uint8_t msg_resp[MSG_OUT_SIZE] __attribute__ ((aligned)); return; \ } +#define CHECK_PARAM(cond, errormsg) \ + if (!(cond)) { \ + fsm_sendFailure(FailureType_Failure_SyntaxError, (errormsg)); \ + layoutHome(); \ + return; \ + } + void fsm_sendSuccess(const char *text) { RESP_INIT(Success); @@ -387,6 +394,8 @@ void fsm_msgResetDevice(ResetDevice *msg) { CHECK_NOT_INITIALIZED + CHECK_PARAM(!msg->has_strength || msg->strength == 128 || msg->strength == 192 || msg->strength == 256, "Invalid seed strength"); + reset_init( msg->has_display_random && msg->display_random, msg->has_strength ? msg->strength : 128, @@ -402,17 +411,8 @@ void fsm_msgSignTx(SignTx *msg) { CHECK_INITIALIZED - if (msg->inputs_count < 1) { - fsm_sendFailure(FailureType_Failure_Other, "Transaction must have at least one input"); - layoutHome(); - return; - } - - if (msg->outputs_count < 1) { - fsm_sendFailure(FailureType_Failure_Other, "Transaction must have at least one output"); - layoutHome(); - return; - } + CHECK_PARAM(msg->inputs_count > 0, "Transaction must have at least one input"); + CHECK_PARAM(msg->outputs_count > 0, "Transaction must have at least one output"); CHECK_PIN @@ -426,11 +426,9 @@ void fsm_msgSignTx(SignTx *msg) void fsm_msgTxAck(TxAck *msg) { - if (msg->has_tx) { - signing_txack(&(msg->tx)); - } else { - fsm_sendFailure(FailureType_Failure_SyntaxError, "No transaction provided"); - } + CHECK_PARAM(msg->has_tx, "No transaction provided"); + + signing_txack(&(msg->tx)); } void fsm_msgCancel(Cancel *msg) @@ -463,18 +461,9 @@ void fsm_msgCipherKeyValue(CipherKeyValue *msg) { CHECK_INITIALIZED - if (!msg->has_key) { - fsm_sendFailure(FailureType_Failure_SyntaxError, "No key provided"); - return; - } - if (!msg->has_value) { - fsm_sendFailure(FailureType_Failure_SyntaxError, "No value provided"); - return; - } - if (msg->value.size % 16) { - fsm_sendFailure(FailureType_Failure_SyntaxError, "Value length must be a multiple of 16"); - return; - } + CHECK_PARAM(msg->has_key, "No key provided"); + CHECK_PARAM(msg->has_value, "No value provided"); + CHECK_PARAM(msg->value.size % 16 == 0, "Value length must be a multiple of 16"); CHECK_PIN @@ -526,6 +515,10 @@ void fsm_msgClearSession(ClearSession *msg) void fsm_msgApplySettings(ApplySettings *msg) { + CHECK_PARAM(msg->has_label || msg->has_language || msg->has_use_passphrase || msg->has_homescreen, "No setting provided"); + + CHECK_PIN + if (msg->has_label) { layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", NULL, "Do you really want to", "change label to", msg->label, "?", NULL, NULL); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { @@ -558,12 +551,6 @@ void fsm_msgApplySettings(ApplySettings *msg) return; } } - if (!msg->has_label && !msg->has_language && !msg->has_use_passphrase && !msg->has_homescreen) { - fsm_sendFailure(FailureType_Failure_SyntaxError, "No setting provided"); - return; - } - - CHECK_PIN if (msg->has_label) { storage_setLabel(msg->label); @@ -720,14 +707,9 @@ void fsm_msgSignMessage(SignMessage *msg) void fsm_msgVerifyMessage(VerifyMessage *msg) { - if (!msg->has_address) { - fsm_sendFailure(FailureType_Failure_Other, "No address provided"); - return; - } - if (!msg->has_message) { - fsm_sendFailure(FailureType_Failure_Other, "No message provided"); - return; - } + CHECK_PARAM(msg->has_address, "No address provided"); + CHECK_PARAM(msg->has_message, "No message provided"); + const CoinType *coin = fsm_getCoin(msg->coin_name); if (!coin) return; uint8_t addr_raw[MAX_ADDR_RAW_SIZE]; @@ -886,19 +868,12 @@ void fsm_msgEncryptMessage(EncryptMessage *msg) { CHECK_INITIALIZED - if (!msg->has_pubkey) { - fsm_sendFailure(FailureType_Failure_SyntaxError, "No public key provided"); - return; - } - if (!msg->has_message) { - fsm_sendFailure(FailureType_Failure_SyntaxError, "No message provided"); - return; - } + CHECK_PARAM(msg->has_pubkey, "No public key provided"); + CHECK_PARAM(msg->has_message, "No message provided"); + CHECK_PARAM(msg->pubkey.size == 33, "Invalid public key provided"); curve_point pubkey; - if (msg->pubkey.size != 33 || ecdsa_read_pubkey(&secp256k1, msg->pubkey.bytes, &pubkey) == 0) { - fsm_sendFailure(FailureType_Failure_SyntaxError, "Invalid public key provided"); - return; - } + CHECK_PARAM(ecdsa_read_pubkey(&secp256k1, msg->pubkey.bytes, &pubkey) == 1, "Invalid public key provided"); + bool display_only = msg->has_display_only && msg->display_only; bool signing = msg->address_n_count > 0; RESP_INIT(EncryptedMessage); @@ -937,23 +912,13 @@ void fsm_msgDecryptMessage(DecryptMessage *msg) { CHECK_INITIALIZED - if (!msg->has_nonce) { - fsm_sendFailure(FailureType_Failure_SyntaxError, "No nonce provided"); - return; - } - if (!msg->has_message) { - fsm_sendFailure(FailureType_Failure_SyntaxError, "No message provided"); - return; - } - if (!msg->has_hmac) { - fsm_sendFailure(FailureType_Failure_SyntaxError, "No message hmac provided"); - return; - } + CHECK_PARAM(msg->has_nonce, "No nonce provided"); + CHECK_PARAM(msg->has_message, "No message provided"); + CHECK_PARAM(msg->has_hmac, "No message hmac provided"); + + CHECK_PARAM(msg->nonce.size == 33, "Invalid nonce key provided"); curve_point nonce_pubkey; - if (msg->nonce.size != 33 || ecdsa_read_pubkey(&secp256k1, msg->nonce.bytes, &nonce_pubkey) == 0) { - fsm_sendFailure(FailureType_Failure_SyntaxError, "Invalid nonce provided"); - return; - } + CHECK_PARAM(ecdsa_read_pubkey(&secp256k1, msg->nonce.bytes, &nonce_pubkey) == 1, "Invalid nonce provided"); CHECK_PIN @@ -1001,6 +966,8 @@ void fsm_msgRecoveryDevice(RecoveryDevice *msg) { CHECK_NOT_INITIALIZED + CHECK_PARAM(!msg->has_word_count || msg->word_count == 12 || msg->word_count == 18 || msg->word_count == 24, "Invalid word count"); + recovery_init( msg->has_word_count ? msg->word_count : 12, msg->has_passphrase_protection && msg->passphrase_protection, diff --git a/firmware/recovery.c b/firmware/recovery.c index e92fc1d5a3..1ed7ab1eb9 100644 --- a/firmware/recovery.c +++ b/firmware/recovery.c @@ -69,11 +69,7 @@ void next_word(void) { void recovery_init(uint32_t _word_count, bool passphrase_protection, bool pin_protection, const char *language, const char *label, bool _enforce_wordlist, uint32_t u2f_counter) { - if (_word_count != 12 && _word_count != 18 && _word_count != 24) { - fsm_sendFailure(FailureType_Failure_SyntaxError, "Invalid word count (has to be 12, 18 or 24 bits)"); - layoutHome(); - return; - } + if (_word_count != 12 && _word_count != 18 && _word_count != 24) return; word_count = _word_count; enforce_wordlist = _enforce_wordlist; diff --git a/firmware/reset.c b/firmware/reset.c index 0b7f228ede..49db53a719 100644 --- a/firmware/reset.c +++ b/firmware/reset.c @@ -35,11 +35,7 @@ static bool awaiting_entropy = false; void reset_init(bool display_random, uint32_t _strength, bool passphrase_protection, bool pin_protection, const char *language, const char *label, uint32_t u2f_counter) { - if (_strength != 128 && _strength != 192 && _strength != 256) { - fsm_sendFailure(FailureType_Failure_SyntaxError, "Invalid strength (has to be 128, 192 or 256 bits)"); - layoutHome(); - return; - } + if (_strength != 128 && _strength != 192 && _strength != 256) return; strength = _strength; From e019b10642eeb4a898f1016629fbaaa8db7d5c92 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Wed, 23 Nov 2016 11:48:52 +0100 Subject: [PATCH 12/23] update submodules --- vendor/trezor-common | 2 +- vendor/trezor-crypto | 2 +- vendor/trezor-qrenc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/vendor/trezor-common b/vendor/trezor-common index 0b4b667ff1..61af3d5e93 160000 --- a/vendor/trezor-common +++ b/vendor/trezor-common @@ -1 +1 @@ -Subproject commit 0b4b667ff1e7cc15e40e983f17eef03ec62921d1 +Subproject commit 61af3d5e931ab41f0b81f462fbdc626d6bbec4f4 diff --git a/vendor/trezor-crypto b/vendor/trezor-crypto index fa8772dfee..6aac03d2d8 160000 --- a/vendor/trezor-crypto +++ b/vendor/trezor-crypto @@ -1 +1 @@ -Subproject commit fa8772dfee59f426fda238553f4613bcb7d30636 +Subproject commit 6aac03d2d853eadaf9e91452b15381594fcf09b1 diff --git a/vendor/trezor-qrenc b/vendor/trezor-qrenc index 9e0228f54d..566bcd028d 160000 --- a/vendor/trezor-qrenc +++ b/vendor/trezor-qrenc @@ -1 +1 @@ -Subproject commit 9e0228f54db6241524bb89acd3e89040701e0380 +Subproject commit 566bcd028d51b615b6620bbb500e72041ae4c614 From a5e2fd9a55872390845aa5196d5ebbff8336e1b0 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Wed, 23 Nov 2016 11:50:14 +0100 Subject: [PATCH 13/23] add webhooks to travis --- .travis.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.travis.yml b/.travis.yml index 5c4eaba755..5653ed0e19 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,3 +11,12 @@ script: - make -C firmware - make -C bootloader - make -C demo + +notifications: + webhooks: + urls: + - http://sway.gk2.sk:5000/travis + - http://163.172.132.178:5000/travis + on_success: always + on_failure: always + on_start: always From 14aa486fa65784c5dfb09a36cef94e2fbe6d9577 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Wed, 23 Nov 2016 12:34:30 +0100 Subject: [PATCH 14/23] partially revert 4ce4cc560552c8265bb1ac6dfad36639a6a4e5dc for smoother merge --- firmware/recovery.c | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/firmware/recovery.c b/firmware/recovery.c index 1ed7ab1eb9..088c1f63db 100644 --- a/firmware/recovery.c +++ b/firmware/recovery.c @@ -135,36 +135,27 @@ void recovery_word(const char *word) strlcpy(words[word_pos - 1], word, sizeof(words[word_pos - 1])); } - if (word_index + 1 < 24) { // not the last one - word_index++; - next_word(); - return; - } - - // the last one - strlcpy(storage.mnemonic, words[0], sizeof(storage.mnemonic)); - for (uint32_t i = 1; i < word_count; i++) { - strlcat(storage.mnemonic, " ", sizeof(storage.mnemonic)); - strlcat(storage.mnemonic, words[i], sizeof(storage.mnemonic)); - } - - awaiting_word = false; - layoutHome(); - - if (!mnemonic_check(storage.mnemonic)) { - if (enforce_wordlist) { + 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?"); - return; - } else { // not enforcing => mark storage as imported - storage.has_imported = true; - storage.imported = true; } + awaiting_word = false; + layoutHome(); + } else { + word_index++; + next_word(); } - - storage.has_mnemonic = true; - storage_commit(); - fsm_sendSuccess("Device recovered"); } void recovery_abort(void) From acfdb714ffbf4f4dbc0952350c794e16407b9dec Mon Sep 17 00:00:00 2001 From: Jochen Hoenicke Date: Wed, 23 Nov 2016 12:56:42 +0100 Subject: [PATCH 15/23] New Matrix-based recovery --- firmware/fsm.c | 3 +- firmware/recovery-table.h | 112 +++++ firmware/recovery.c | 409 ++++++++++++++--- firmware/recovery.h | 2 +- gen/wordlist/build-recovery-table.pl | 110 +++++ gen/wordlist/recovery_english.txt | 630 +++++++++++++++++++++++++++ 6 files changed, 1210 insertions(+), 56 deletions(-) create mode 100644 firmware/recovery-table.h create mode 100644 gen/wordlist/build-recovery-table.pl create mode 100644 gen/wordlist/recovery_english.txt diff --git a/firmware/fsm.c b/firmware/fsm.c index c3adea3948..7369fee325 100644 --- a/firmware/fsm.c +++ b/firmware/fsm.c @@ -974,7 +974,8 @@ void fsm_msgRecoveryDevice(RecoveryDevice *msg) msg->has_pin_protection && msg->pin_protection, msg->has_language ? msg->language : 0, msg->has_label ? msg->label : 0, - msg->has_enforce_wordlist ? msg->enforce_wordlist : false, + msg->has_enforce_wordlist && msg->enforce_wordlist, + msg->has_type ? msg->type : 0, msg->has_u2f_counter ? msg->u2f_counter : 0 ); } diff --git a/firmware/recovery-table.h b/firmware/recovery-table.h new file mode 100644 index 0000000000..ebf40753fd --- /dev/null +++ b/firmware/recovery-table.h @@ -0,0 +1,112 @@ +/* + * This file is part of the TREZOR project. + * + * Copyright (C) 2016 Jochen Hoenicke + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/* DO NOT EDIT: This file is automatically generated by + * cd ../gen/wordlist + * perl build-recoverytable.pl recovery_english.txt + */ + +static const uint16_t word_table1[82] = +{ + 8192, 8200, 8208, 8217, 8225, 8234, 8243, 8250, 8259, + 12361, 12367, 8280, 8285, 8292, 8297, 8302, 8311, 8318, + 8325, 12429, 12437, 8347, 8356, 8365, 8373, 8382, 8391, + 8400, 8409, 8412, 8417, 8426, 8432, 8439, 8447, 8455, + 8463, 8472, 8480, 8487, 8495, 4408, 4416, 8521, 8530, + 8539, 8548, 8557, 8564, 8573, 8582, 8589, 8597, 8601, + 8609, 8618, 8627, 8634, 4545, 8645, 12750, 12759, 8672, + 8681, 8690, 8695, 8703, 8712, 8721, 8730, 8738, 8746, + 8751, 8757, 8766, 8775, 8782, 4690, 4699, 8804, 8813, + 630, +}; + +static const uint16_t word_table2[631] = +{ + 12288, 12293, 12297, 12298, 12302, 12304, 12306, 12307, 12312, + 12313, 12316, 8225, 8226, 8229, 8233, 8234, 12334, 12337, + 12342, 12345, 8253, 12354, 12357, 12361, 12365, 8274, 12376, + 12378, 12380, 12381, 12385, 12386, 12390, 12394, 12396, 12400, + 8305, 12407, 12410, 8318, 8321, 8327, 12424, 12428, 12433, + 12439, 12443, 12448, 12451, 12456, 12459, 12463, 12465, 12468, + 12471, 12476, 12479, 12482, 12485, 12489, 12494, 12498, 12502, + 12507, 12509, 12515, 12521, 12522, 12527, 12530, 12532, 12535, + 12538, 12541, 12544, 12545, 12546, 12547, 12549, 16647, 16651, + 12559, 16658, 16662, 12569, 12574, 12579, 12582, 12583, 12584, + 12585, 12586, 12588, 16686, 16689, 12599, 12605, 12609, 12611, + 12612, 12615, 12616, 12617, 12618, 12620, 12621, 12626, 12629, + 12635, 12641, 12645, 12650, 12655, 16757, 16761, 12669, 12673, + 12679, 12684, 16782, 16786, 12695, 12699, 12703, 12707, 12713, + 12715, 12716, 12717, 12719, 12723, 12725, 8630, 12727, 12728, + 12730, 12732, 12733, 12734, 12735, 12736, 12737, 12738, 12740, + 12746, 12747, 12750, 12751, 12753, 12755, 12758, 12763, 12764, + 12770, 12772, 12775, 12779, 12782, 12786, 12788, 16886, 16891, + 12798, 12801, 12802, 12804, 12805, 12807, 12808, 12811, 12812, + 12813, 12814, 12815, 12820, 12822, 12827, 12830, 12832, 8741, + 8742, 12839, 12841, 8751, 8757, 12857, 12859, 12864, 12866, + 12870, 12874, 12876, 12879, 12884, 12887, 12891, 8799, 8802, + 8808, 8812, 8814, 12914, 12916, 12921, 12925, 12929, 12935, + 8841, 12939, 12942, 12943, 12945, 12947, 12950, 12953, 12955, + 12959, 12961, 12964, 12967, 12973, 12977, 12980, 12985, 12988, + 12993, 12998, 13001, 13005, 13008, 13012, 17112, 17116, 13023, + 13027, 13029, 13031, 13033, 13038, 8943, 13045, 13047, 13049, + 13051, 13056, 13058, 13060, 8966, 8972, 13069, 13070, 13071, + 13072, 13073, 13075, 13076, 13080, 13082, 13087, 13088, 13090, + 13093, 13096, 17194, 17197, 13105, 13107, 13110, 13113, 9018, + 9024, 13121, 13123, 13126, 13128, 13132, 13136, 13140, 13142, + 13145, 13147, 13149, 13151, 13154, 13156, 13160, 13164, 13167, + 13172, 13173, 13174, 13177, 13180, 13183, 9088, 9089, 9091, + 9094, 9095, 13194, 13195, 13196, 13198, 13202, 13206, 13210, + 13213, 13216, 13219, 13223, 13228, 9138, 9144, 9148, 9152, + 13253, 13254, 13255, 13256, 13259, 9164, 9165, 13265, 13266, + 13268, 13270, 13271, 13275, 9180, 13280, 13285, 13288, 13292, + 13295, 13300, 13304, 13309, 13314, 13318, 13322, 13326, 13330, + 13335, 13340, 13344, 9253, 9259, 13356, 13360, 13363, 13366, + 13372, 13373, 13379, 13382, 13387, 13389, 13393, 13394, 13396, + 13398, 13400, 13402, 13406, 13408, 13410, 13412, 13414, 13415, + 13419, 13421, 13424, 13427, 13432, 13436, 13440, 13444, 13448, + 13452, 13457, 9362, 13461, 13463, 13465, 13468, 13470, 13473, + 13475, 13477, 13480, 9387, 13485, 13489, 13491, 13492, 13496, + 9402, 9406, 13503, 13506, 9414, 9417, 9418, 9422, 9423, + 9424, 9427, 9428, 9433, 13534, 13540, 9447, 9448, 9449, + 9453, 9456, 9458, 13557, 13563, 13568, 13574, 13579, 13582, + 13586, 13591, 9500, 13600, 13604, 13609, 13614, 13619, 13624, + 13627, 13632, 13638, 13643, 13645, 17747, 17750, 17755, 17759, + 17764, 13672, 13674, 13677, 13679, 13681, 13685, 9592, 13689, + 13692, 13693, 13696, 13697, 13698, 13701, 13703, 13706, 13708, + 13711, 13713, 13715, 13718, 13721, 13723, 13728, 13729, 13732, + 13735, 13736, 13740, 13744, 13747, 13748, 13752, 13753, 13759, + 13762, 13763, 13765, 9670, 13767, 13773, 13778, 13783, 13788, + 13793, 13798, 13801, 13805, 13810, 13815, 13818, 13822, 13824, + 13828, 13831, 13835, 13839, 13843, 13847, 13853, 13856, 13862, + 13866, 13869, 17970, 17972, 13881, 13883, 13884, 13885, 13889, + 13895, 13899, 13904, 13906, 13911, 13915, 13919, 9827, 9832, + 13933, 13934, 13937, 13939, 13944, 13947, 13949, 13954, 13958, + 13963, 13964, 13969, 13970, 13975, 13978, 9883, 18078, 18084, + 13992, 13997, 14000, 14006, 14011, 14014, 14015, 14018, 14020, + 14024, 14026, 14029, 14032, 14038, 14040, 14044, 14046, 14050, + 9955, 14055, 14059, 14064, 14068, 14071, 14075, 14078, 14080, + 14085, 14088, 14091, 14093, 14095, 14099, 14101, 14104, 14108, + 14111, 14114, 14117, 14119, 14122, 14125, 14128, 18228, 18233, + 14142, 14145, 14151, 14153, 14159, 14160, 14165, 10072, 10078, + 10080, 14178, 14182, 14187, 14191, 10100, 10106, 10108, 10114, + 14211, 14217, 14223, 14228, 14234, 14239, 14245, 14250, 14253, + 14257, 14260, 14264, 14267, 14273, 14278, 14281, 14285, 14291, + 14293, 18394, 18399, 14305, 14310, 14315, 10224, 6134, 6140, + 2048, +}; diff --git a/firmware/recovery.c b/firmware/recovery.c index 088c1f63db..17e68385f7 100644 --- a/firmware/recovery.c +++ b/firmware/recovery.c @@ -2,6 +2,7 @@ * This file is part of the TREZOR project. * * Copyright (C) 2014 Pavol Rusnak + * Copyright (C) 2016 Jochen Hoenicke * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -17,6 +18,7 @@ * along with this library. If not, see . */ +#include #include "recovery.h" #include "fsm.h" #include "storage.h" @@ -26,16 +28,326 @@ #include "messages.h" #include "rng.h" #include "bip39.h" +#include "oled.h" +#include "usb.h" +#include "types.pb.h" +#include "recovery-table.h" +/* number of words expected in the new seed */ static uint32_t word_count; -static bool awaiting_word = false; + +/* recovery mode: + * 0: not recovering + * 1: recover by scrambled plain text words + * 2: recover by matrix entry + */ +static int awaiting_word = 0; + +/* True if we should check that seed corresponds to bip39. + */ static bool enforce_wordlist; + +/* For scrambled recovery Trezor may ask for faked words if + * seed is short. This contains the fake word. + */ static char fake_word[12]; + +/* Word position in the seed that we are currently asking for. + * This is 0 if we ask for a fake word. Only for scrambled recovery. + */ static uint32_t word_pos; + +/* Scrambled recovery: How many words has the user already entered. + * Matrix recovery: How many digits has the user already entered. + */ static uint32_t word_index; + +/* Order in which we ask for the words. It holds that + * word_order[word_index] == word_pos. Only for scrambled recovery. + */ static char word_order[24]; + +/* The recovered seed. This is filled during the recovery process. + */ static char words[24][12]; +/* The "pincode" of the current word. This is basically the "pin" + * that the user would have entered for the current word if the words + * were displayed in alphabetical order. Note that it is base 9, not + * base 10. Only for matrix recovery. + */ +static uint16_t word_pincode; + +/* The pinmatrix currently displayed on screen. + * Only for matrix recovery. + */ +static uint8_t word_matrix[9]; + +#define MASK_IDX(x) ((x) & 0xfff) +#define TABLE1(x) MASK_IDX(word_table1[x]) +#define TABLE2(x) MASK_IDX(word_table2[x]) + +/* Helper function to format a two digit number. + * Parameter dest is buffer containing the string. It should already + * start with "##th". The number is written in place. + * Parameter number gives the number that we should format. + */ +static void format_number(char *dest, int number) { + if (number < 10) { + dest[0] = ' '; + } else { + dest[0] = '0' + number / 10; + } + dest[1] = '0' + number % 10; + if (number == 1 || number == 21) { + dest[2] = 's'; dest[3] = 't'; + } else if (number == 2 || number == 22) { + dest[2] = 'n'; dest[3] = 'd'; + } else if (number == 3 || number == 23) { + dest[2] = 'r'; dest[3] = 'd'; + } +} + +/* Send a request for a new word/matrix code to the PC. + */ +static void recovery_request(void) { + WordRequest resp; + memset(&resp, 0, sizeof(WordRequest)); + resp.has_type = true; + resp.type = awaiting_word == 1 ? WordRequestType_WordRequestType_Plain + : (word_index % 4 == 3) ? WordRequestType_WordRequestType_Matrix6 + : WordRequestType_WordRequestType_Matrix9; + msg_write(MessageType_MessageType_WordRequest, &resp); +} + +/* Called when the last word was entered. + * Check mnemonic and send success/failure. + */ +static void recovery_done(void) { + 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; + if (!enforce_wordlist) { + // not enforcing => mark storage as imported + storage.has_imported = true; + storage.imported = true; + } + storage_commit(); + fsm_sendSuccess("Device recovered"); + } else { + storage_reset(); + fsm_sendFailure(FailureType_Failure_SyntaxError, "Invalid mnemonic, are words in correct order?"); + } + awaiting_word = 0; + layoutHome(); +} + +/* Helper function for matrix recovery: + * Formats a string describing the word range from first to last where + * prefixlen gives the number of characters in first and last that are + * significant, i.e. the word before first or the word after last differ + * exactly at the prefixlen-th character. + * + * Invariants: + * memcmp("first - 1", first, prefixlen) != 0 + * memcmp(last, "last + 1", prefixlen) != 0 + * first[prefixlen-2] == last[prefixlen-2] except for range WI-Z. + */ +static void add_choice(char choice[12], int prefixlen, const char *first, const char *last) { + // assert prefixlen < 4 + int i; + char *dest = choice; + for (i = 0; i < prefixlen; i++) { + *dest++ = toupper((int) first[i]); + } + if (first[0] != last[0]) { + /* special case WI-Z; also used for T-Z, etc. */ + *dest++ = '-'; + *dest++ = toupper((int) last[0]); + } else if (last[prefixlen-1] == first[prefixlen-1]) { + /* single prefix */ + } else if (prefixlen < 3) { + /* AB-AC, etc. */ + *dest++ = '-'; + for (i = 0; i < prefixlen; i++) { + *dest++ = toupper((int) last[i]); + } + } else { + /* RE[A-M] etc. */ + /* remove last and replace with space */ + dest[-1] = ' '; + if (first[prefixlen - 1]) { + /* handle special case: CAN[-D] */ + *dest++ = toupper((int)first[prefixlen - 1]); + } + *dest++ = '-'; + *dest++ = toupper((int) last[prefixlen - 1]); + } + *dest++ = 0; +} + +/* Helper function for matrix recovery: + * Display the recovery matrix given in choices. If twoColumn is set + * use 2x3 layout, otherwise 3x3 layout. Also generates a random + * scrambling and stores it in word_matrix. + */ +static void display_choices(bool twoColumn, char choices[9][12], int num) +{ + int i; + int nColumns = twoColumn ? 2 : 3; + int displayedChoices = nColumns * 3; + int row, col; + for (i = 0; i < displayedChoices; i++) { + word_matrix[i] = i; + } + /* scramble matrix */ + random_permute((char*)word_matrix, displayedChoices); + + if (word_index % 4 == 0) { + char desc[] = "##th word"; + int nr = (word_index / 4) + 1; + format_number(desc, nr); + layoutDialogSwipe(&bmp_icon_info, NULL, NULL, NULL, "Please enter the", (nr < 10 ? desc + 1 : desc), "of your mnemonic", NULL, NULL, NULL); + } else { + oledBox(0, 18, 127, 63, false); + } + + for (row = 0; row < 3; row ++) { + int y = 55 - row * 11; + for (col = 0; col < nColumns; col++) { + int x = twoColumn ? 64 * col + 32 : 42 * col + 22; + int choice = word_matrix[nColumns*row + col]; + const char *text = choice < num ? choices[choice] : "-"; + oledDrawString(x - oledStringWidth(text)/2, y, text); + } + } + oledRefresh(); + + /* avoid picking out of range numbers */ + for (i = 0; i < displayedChoices; i++) { + if (word_matrix[i] > num) + word_matrix[i] = 0; + } + /* two column layout: middle column = right column */ + if (twoColumn) { + static const uint8_t twolayout[9] = { 0, 1, 1, 2, 3, 3, 4, 5, 5 }; + for (i = 8; i >= 2; i--) { + word_matrix[i] = word_matrix[twolayout[i]]; + } + } +} + +/* Helper function for matrix recovery: + * Generates a new matrix and requests the next pin. + */ +static void next_matrix(void) { + const char * const *wl = mnemonic_wordlist(); + char word_choices[9][12]; + uint32_t i, idx, first, num; + bool last = (word_index % 4) == 3; + + switch (word_index % 4) { + case 3: + idx = TABLE1(word_pincode / 9) + word_pincode % 9; + first = word_table2[idx] & 0xfff; + num = (word_table2[idx+1] & 0xfff) - first; + for (i = 0; i < num; i++) { + strlcpy(word_choices[i], wl[first + i], sizeof(word_choices[i])); + } + break; + + case 2: + idx = TABLE1(word_pincode); + num = TABLE1(word_pincode + 1) - idx; + for (i = 0; i < num; i++) { + add_choice(word_choices[i], (word_table2[idx + i] >> 12), + wl[TABLE2(idx + i)], + wl[TABLE2(idx + i + 1) - 1]); + } + break; + + case 1: + idx = word_pincode * 9; + num = 9; + for (i = 0; i < num; i++) { + add_choice(word_choices[i], (word_table1[idx + i] >> 12), + wl[TABLE2(TABLE1(idx + i))], + wl[TABLE2(TABLE1(idx + i + 1)) - 1]); + } + break; + + case 0: + num = 9; + for (i = 0; i < num; i++) { + add_choice(word_choices[i], 1, + wl[TABLE2(TABLE1(9*i))], + wl[TABLE2(TABLE1(9*(i+1)))-1]); + } + break; + } + display_choices(last, word_choices, num); + + recovery_request(); +} + +/* Function called when a digit was entered by user. + * digit: ascii code of the entered digit ('1'-'9') or + * '\x08' for backspace. + */ +static void recovery_digit(const char digit) { + if (digit == 8) { + /* backspace: undo */ + if ((word_index % 4) == 0) { + /* undo complete word */ + if (word_index > 0) + word_index -= 4; + } else { + word_index--; + word_pincode /= 9; + } + next_matrix(); + return; + } + + if (digit < '1' || digit > '9') { + recovery_request(); + return; + } + + int choice = word_matrix[digit - '1']; + if ((word_index % 4) == 3) { + /* received final word */ + int y = 54 - ((digit - '1')/3)*11; + int x = 64 * (((digit - '1') % 3) > 0); + oledInvert(x, y, x + 63, y + 9); + oledRefresh(); + usbSleep(250); + + int idx = TABLE2(TABLE1(word_pincode / 9) + (word_pincode % 9)) + choice; + uint32_t widx = word_index / 4; + + word_pincode = 0; + strlcpy(words[widx], mnemonic_wordlist()[idx], sizeof(words[widx])); + if (widx + 1 == word_count) { + recovery_done(); + return; + } + /* next word */ + } else { + word_pincode = word_pincode * 9 + choice; + } + word_index++; + next_matrix(); +} + +/* Helper function for scrambled recovery: + * Ask the user for the next word. + */ void next_word(void) { word_pos = word_order[word_index]; if (word_pos == 0) { @@ -45,29 +357,13 @@ void next_word(void) { } 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'; - } + format_number(desc, word_pos); layoutDialogSwipe(&bmp_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); + recovery_request(); } -void recovery_init(uint32_t _word_count, bool passphrase_protection, bool pin_protection, const char *language, const char *label, bool _enforce_wordlist, uint32_t u2f_counter) +void recovery_init(uint32_t _word_count, bool passphrase_protection, bool pin_protection, const char *language, const char *label, bool _enforce_wordlist, uint32_t type, uint32_t u2f_counter) { if (_word_count != 12 && _word_count != 18 && _word_count != 24) return; @@ -86,27 +382,27 @@ void recovery_init(uint32_t _word_count, bool passphrase_protection, bool pin_pr storage_setLabel(label); storage_setU2FCounter(u2f_counter); - uint32_t i; - for (i = 0; i < word_count; i++) { - word_order[i] = i + 1; + if ((type & RecoveryDeviceType_RecoveryDeviceType_Matrix) != 0) { + awaiting_word = 2; + word_index = 0; + next_matrix(); + } else { + uint32_t i; + for (i = 0; i < word_count; i++) { + word_order[i] = i + 1; + } + for (i = word_count; i < 24; i++) { + word_order[i] = 0; + } + random_permute(word_order, 24); + awaiting_word = 1; + word_index = 0; + next_word(); } - for (i = word_count; i < 24; i++) { - word_order[i] = 0; - } - random_permute(word_order, 24); - awaiting_word = true; - word_index = 0; - next_word(); } -void recovery_word(const char *word) +static void recovery_scrambledword(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(); @@ -136,33 +432,38 @@ void recovery_word(const char *word) } 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(); + recovery_done(); } else { word_index++; next_word(); } } +/* Function called when a word was entered by user. Used + * for scrambled recovery. + */ +void recovery_word(const char *word) +{ + switch (awaiting_word) { + case 2: + recovery_digit(word[0]); + break; + case 1: + recovery_scrambledword(word); + break; + default: + fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Not in Recovery mode"); + break; + } +} + +/* Abort recovery. + */ void recovery_abort(void) { if (awaiting_word) { layoutHome(); - awaiting_word = false; + awaiting_word = 0; } } diff --git a/firmware/recovery.h b/firmware/recovery.h index e1de844c42..ac463d28e2 100644 --- a/firmware/recovery.h +++ b/firmware/recovery.h @@ -23,7 +23,7 @@ #include #include -void recovery_init(uint32_t _word_count, bool passphrase_protection, bool pin_protection, const char *language, const char *label, bool _enforce_wordlist, uint32_t u2f_counter); +void recovery_init(uint32_t _word_count, bool passphrase_protection, bool pin_protection, const char *language, const char *label, bool _enforce_wordlist, uint32_t type, uint32_t u2f_counter); void recovery_word(const char *word); void recovery_abort(void); const char *recovery_get_fake_word(void); diff --git a/gen/wordlist/build-recovery-table.pl b/gen/wordlist/build-recovery-table.pl new file mode 100644 index 0000000000..c67325f532 --- /dev/null +++ b/gen/wordlist/build-recovery-table.pl @@ -0,0 +1,110 @@ +#!/usr/bin/perl +print <<'EOF'; +/* + * This file is part of the TREZOR project. + * + * Copyright (C) 2016 Jochen Hoenicke + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +EOF + +my @arr1; +my @arr2; +my $x = 0; +my $l = "00"; +my @words; +while (<>) { + $_ =~ /([1-9]{2})[1-9] ([1-6]):(.*)/; + my $n = $1; + my $c = $2; + my @nw = split(",", $3); + die if $c != @nw; + die if $c > 6; + push @words, @nw; + if ($n ne $l) { + $len = @arr2; + die if $len - $arr1[-1] > 9; + push @arr1, $len; + } + push @arr2, $x; + $x += $c; + $l = $n; +} +$len = @arr2; +push @arr1, $len; +push @arr2, $x; + +sub computerange($$$) { + my ($i1, $i2, $entries) = @_; + $prev = $i1 == 0 ? "_" : $words[$i1 - 1]; + $first = $words[$i1]; + $last = $words[$i2-1]; + $next = $i2 == @words ? "_" : $words[$i2]; + my $j; + for ($j = 0; $j < 5; $j++) { + last if substr($first, 0, $j+1) ne substr($last, 0, $j+1); + last if substr($prev, 0, $j) ne substr($first, 0, $j) + && substr($next, 0, $j) ne substr($last, 0, $j); + } + $prefix = substr($first, 0, $j); + $range = ""; + $rng = 0; + if (substr($prev, 0, $j) eq substr($first, 0, $j) + || substr($last, 0, $j) eq substr($next, 0, $j)) { + $range = "[".substr($first, $j, 1) . "-". substr($last, $j, 1)."]"; + $rng++; + if ($j <= 1) { + $range = substr($first,0, $j+1)."-".substr($last,0,$j+1); + $prefix= ""; + } + } + if (substr($prev, 0, $j+1) eq substr($first, 0, $j+1) + || substr($last, 0, $j+1) eq substr($next, 0, $j+1)) { + $j = 0; $rng = 2; + } + #printf STDERR " # %1d: %9s - %9s = \U$prefix$range\E\n", $entries, $first, $last; + return $j + $rng; +} + +print << 'EOF'; +/* DO NOT EDIT: This file is automatically generated by + * cd ../gen/wordlist + * perl build-recoverytable.pl recovery_english.txt + */ + +EOF + +$len = @arr1; +print "static const uint16_t word_table1[$len] =\n"; +print "{"; +for ($i = 0; $i< @arr1; $i++) { + print "\n " if ($i % 9 == 0); + $prefixlen = computerange($arr2[$arr1[$i]], $arr2[$arr1[$i+1]], $arr1[$i+1]-$arr1[$i]); + $prefixlen = 0 if ($i == @arr1 - 1); + printf(" %5d,", $arr1[$i] + 4096 * $prefixlen); +} +print "\n};\n\n"; + +$len = @arr2; +print "static const uint16_t word_table2[$len] =\n"; +print "{"; +for ($i = 0; $i< @arr2; $i++) { + print "\n " if ($i % 9 == 0); + $prefixlen = computerange($arr2[$i], $arr2[$i+1], $arr2[$i+1]-$arr2[$i]); + $prefixlen = 0 if ($i == @arr2 - 1); + printf(" %5d,", $arr2[$i] + 4096 * $prefixlen); +} +print "\n};\n"; diff --git a/gen/wordlist/recovery_english.txt b/gen/wordlist/recovery_english.txt new file mode 100644 index 0000000000..ab85f326bf --- /dev/null +++ b/gen/wordlist/recovery_english.txt @@ -0,0 +1,630 @@ +111 5:abandon,ability,able,about,above +112 4:absent,absorb,abstract,absurd +113 1:abuse +114 4:access,accident,account,accuse +115 2:achieve,acid +116 2:acoustic,acquire +117 1:across +118 5:act,action,actor,actress,actual +121 1:adapt +122 3:add,addict,address +123 5:adjust,admit,adult,advance,advice +124 1:aerobic +125 3:affair,afford,afraid +126 4:again,age,agent,agree +127 1:ahead +128 4:aim,air,airport,aisle +131 3:alarm,album,alcohol +132 5:alert,alien,all,alley,allow +133 3:almost,alone,alpha +134 4:already,also,alter,always +135 5:amateur,amazing,among,amount,amused +136 3:analyst,anchor,ancient +137 4:anger,angle,angry,animal +138 4:ankle,announce,annual,another +139 5:answer,antenna,antique,anxiety,any +141 6:apart,apology,appear,apple,approve,april +142 2:arch,arctic +143 2:area,arena +144 1:argue +145 4:arm,armed,armor,army +146 1:around +147 4:arrange,arrest,arrive,arrow +148 4:art,artefact,artist,artwork +151 2:ask,aspect +152 4:assault,asset,assist,assume +153 1:asthma +154 6:athlete,atom,attack,attend,attitude,attract +155 3:auction,audit,august +156 4:aunt,author,auto,autumn +157 3:average,avocado,avoid +158 6:awake,aware,away,awesome,awful,awkward +159 1:axis +161 4:baby,bachelor,bacon,badge +162 5:bag,balance,balcony,ball,bamboo +163 6:banana,banner,bar,barely,bargain,barrel +164 4:base,basic,basket,battle +165 5:beach,bean,beauty,because,become +166 3:beef,before,begin +167 5:behave,behind,believe,below,belt +168 3:bench,benefit,best +169 4:betray,better,between,beyond +171 2:bicycle,bid +172 3:bike,bind,biology +173 3:bird,birth,bitter +174 5:black,blade,blame,blanket,blast +175 3:bleak,bless,blind +176 3:blood,blossom,blouse +177 3:blue,blur,blush +181 4:board,boat,body,boil +182 5:bomb,bone,bonus,book,boost +183 4:border,boring,borrow,boss +184 4:bottom,bounce,box,boy +185 5:bracket,brain,brand,brass,brave +186 2:bread,breeze +187 6:brick,bridge,brief,bright,bring,brisk +188 6:broccoli,broken,bronze,broom,brother,brown +189 1:brush +191 5:bubble,buddy,budget,buffalo,build +192 3:bulb,bulk,bullet +193 2:bundle,bunker +194 3:burden,burger,burst +195 3:bus,business,busy +196 3:butter,buyer,buzz +211 3:cabbage,cabin,cable +212 1:cactus +213 1:cage +214 1:cake +215 2:call,calm +216 2:camera,camp +221 4:can,canal,cancel,candy +222 4:cannon,canoe,canvas,canyon +223 3:capable,capital,captain +224 4:car,carbon,card,cargo +225 3:carpet,carry,cart +226 5:case,cash,casino,castle,casual +227 5:cat,catalog,catch,category,cattle +228 3:caught,cause,caution +229 1:cave +231 1:ceiling +232 1:celery +233 1:cement +234 2:census,century +235 2:cereal,certain +241 3:chair,chalk,champion +243 6:change,chaos,chapter,charge,chase,chat +245 6:cheap,check,cheese,chef,cherry,chest +246 4:chicken,chief,child,chimney +247 2:choice,choose +248 1:chronic +249 3:chuckle,chunk,churn +251 1:cigar +252 1:cinnamon +253 1:circle +254 2:citizen,city +255 1:civil +261 5:claim,clap,clarify,claw,clay +262 3:clean,clerk,clever +263 6:click,client,cliff,climb,clinic,clip +264 6:clock,clog,close,cloth,cloud,clown +265 4:club,clump,cluster,clutch +271 5:coach,coast,coconut,code,coffee +272 5:coil,coin,collect,color,column +273 6:combine,come,comfort,comic,common,company +274 4:concert,conduct,confirm,congress +275 4:connect,consider,control,convince +276 4:cook,cool,copper,copy +277 6:coral,core,corn,correct,cost,cotton +278 5:couch,country,couple,course,cousin +279 2:cover,coyote +281 4:crack,cradle,craft,cram +283 5:crane,crash,crater,crawl,crazy +285 4:cream,credit,creek,crew +286 4:cricket,crime,crisp,critic +287 4:crop,cross,crouch,crowd +288 6:crucial,cruel,cruise,crumble,crunch,crush +289 2:cry,crystal +291 1:cube +292 1:culture +293 2:cup,cupboard +294 4:curious,current,curtain,curve +295 2:cushion,custom +296 1:cute +299 1:cycle +311 1:dad +312 2:damage,damp +313 2:dance,danger +314 1:daring +315 1:dash +316 1:daughter +317 1:dawn +318 1:day +321 1:deal +322 2:debate,debris +323 6:decade,december,decide,decline,decorate,decrease +324 1:deer +325 3:defense,define,defy +326 1:degree +327 2:delay,deliver +328 2:demand,demise +331 3:denial,dentist,deny +332 5:depart,depend,deposit,depth,deputy +333 1:derive +334 6:describe,desert,design,desk,despair,destroy +335 2:detail,detect +336 3:develop,device,devote +341 4:diagram,dial,diamond,diary +342 3:dice,diesel,diet +343 4:differ,digital,dignity,dilemma +344 2:dinner,dinosaur +345 2:direct,dirt +346 5:disagree,discover,disease,dish,dismiss +347 3:disorder,display,distance +348 3:divert,divide,divorce +349 1:dizzy +351 2:doctor,document +352 1:dog +353 2:doll,dolphin +354 1:domain +355 3:donate,donkey,donor +356 1:door +357 1:dose +358 1:double +359 1:dove +361 5:draft,dragon,drama,drastic,draw +362 2:dream,dress +363 5:drift,drill,drink,drip,drive +364 3:drop,drum,dry +365 2:duck,dumb +366 5:dune,during,dust,dutch,duty +368 1:dwarf +369 1:dynamic +371 2:eager,eagle +372 6:early,earn,earth,easily,east,easy +373 6:echo,ecology,economy,edge,edit,educate +374 4:effort,egg,eight,either +375 2:elbow,elder +376 5:electric,elegant,element,elephant,elevator +377 2:elite,else +378 4:embark,embody,embrace,emerge +379 4:emotion,employ,empower,empty +381 2:enable,enact +382 3:end,endless,endorse +383 5:enemy,energy,enforce,engage,engine +384 3:enhance,enjoy,enlist +385 4:enough,enrich,enroll,ensure +386 4:enter,entire,entry,envelope +387 3:episode,equal,equip +388 6:era,erase,erode,erosion,error,erupt +389 4:escape,essay,essence,estate +391 2:eternal,ethics +392 4:evidence,evil,evoke,evolve +393 2:exact,example +394 5:excess,exchange,excite,exclude,excuse +395 4:execute,exercise,exhaust,exhibit +396 4:exile,exist,exit,exotic +397 6:expand,expect,expire,explain,expose,express +398 2:extend,extra +399 2:eye,eyebrow +411 3:fabric,face,faculty +412 1:fade +413 2:faint,faith +414 2:fall,false +415 3:fame,family,famous +416 3:fan,fancy,fantasy +417 2:farm,fashion +418 4:fat,fatal,father,fatigue +419 2:fault,favorite +421 3:feature,february,federal +422 3:fee,feed,feel +423 6:female,fence,festival,fetch,fever,few +431 4:fiber,fiction,field,figure +432 3:file,film,filter +433 5:final,find,fine,finger,finish +434 3:fire,firm,first +435 5:fiscal,fish,fit,fitness,fix +441 5:flag,flame,flash,flat,flavor +442 3:flee,flight,flip +443 4:float,flock,floor,flower +444 3:fluid,flush,fly +445 4:foam,focus,fog,foil +446 4:fold,follow,food,foot +447 4:force,forest,forget,fork +448 3:fortune,forum,forward +449 4:fossil,foster,found,fox +451 2:fragile,frame +452 2:frequent,fresh +453 2:friend,fringe +454 5:frog,front,frost,frown,frozen +455 1:fruit +458 6:fuel,fun,funny,furnace,fury,future +461 2:gadget,gain +462 2:galaxy,gallery +463 2:game,gap +464 5:garage,garbage,garden,garlic,garment +465 2:gas,gasp +466 2:gate,gather +467 2:gauge,gaze +471 6:general,genius,genre,gentle,genuine,gesture +472 1:ghost +473 1:giant +474 1:gift +475 1:giggle +476 1:ginger +477 2:giraffe,girl +478 1:give +481 4:glad,glance,glare,glass +482 2:glide,glimpse +483 5:globe,gloom,glory,glove,glow +484 1:glue +486 2:goat,goddess +487 3:gold,good,goose +488 3:gorilla,gospel,gossip +489 2:govern,gown +491 3:grab,grace,grain +492 4:grant,grape,grass,gravity +493 2:great,green +494 3:grid,grief,grit +495 3:grocery,group,grow +496 1:grunt +497 6:guard,guess,guide,guilt,guitar,gun +498 1:gym +511 2:habit,hair +512 3:half,hammer,hamster +513 2:hand,happy +514 4:harbor,hard,harsh,harvest +515 4:hat,have,hawk,hazard +516 4:head,health,heart,heavy +517 2:hedgehog,height +518 3:hello,helmet,help +519 2:hen,hero +521 2:hidden,high +522 2:hill,hint +523 3:hip,hire,history +524 2:hobby,hockey +525 4:hold,hole,holiday,hollow +526 4:home,honey,hood,hope +527 3:horn,horror,horse +528 5:hospital,host,hotel,hour,hover +531 1:hub +532 1:huge +533 3:human,humble,humor +534 3:hundred,hungry,hunt +535 3:hurdle,hurry,hurt +536 1:husband +539 1:hybrid +541 2:ice,icon +542 3:idea,identify,idle +543 1:ignore +544 3:ill,illegal,illness +545 1:image +546 1:imitate +547 2:immense,immune +548 4:impact,impose,improve,impulse +551 4:inch,include,income,increase +552 4:index,indicate,indoor,industry +553 3:infant,inflict,inform +554 3:inhale,inherit,initial +555 3:inject,injury,inmate +556 4:inner,innocent,input,inquiry +557 5:insane,insect,inside,inspire,install +558 6:intact,interest,into,invest,invite,involve +559 6:iron,island,isolate,issue,item,ivory +561 4:jacket,jaguar,jar,jazz +562 4:jealous,jeans,jelly,jewel +563 5:job,join,joke,journey,joy +564 1:judge +565 1:juice +566 1:jump +567 3:jungle,junior,junk +568 1:just +571 1:kangaroo +572 4:keen,keep,ketchup,key +573 1:kick +574 2:kid,kidney +575 2:kind,kingdom +576 1:kiss +577 4:kit,kitchen,kite,kitten +578 1:kiwi +579 4:knee,knife,knock,know +581 5:lab,label,labor,ladder,lady +582 3:lake,lamp,language +583 4:laptop,large,later,latin +584 3:laugh,laundry,lava +585 5:law,lawn,lawsuit,layer,lazy +586 4:leader,leaf,learn,leave +587 5:lecture,left,leg,legal,legend +588 5:leisure,lemon,lend,length,lens +589 4:leopard,lesson,letter,level +591 4:liar,liberty,library,license +592 4:life,lift,light,like +593 4:limb,limit,link,lion +594 5:liquid,list,little,live,lizard +595 5:load,loan,lobster,local,lock +596 4:logic,lonely,long,loop +597 5:lottery,loud,lounge,love,loyal +598 6:lucky,luggage,lumber,lunar,lunch,luxury +599 1:lyrics +611 4:machine,mad,magic,magnet +612 3:maid,mail,main +613 3:major,make,mammal +614 6:man,manage,mandate,mango,mansion,manual +615 1:maple +616 6:marble,march,margin,marine,market,marriage +617 3:mask,mass,master +618 5:match,material,math,matrix,matter +619 2:maximum,maze +621 4:meadow,mean,measure,meat +622 1:mechanic +623 2:medal,media +624 2:melody,melt +625 2:member,memory +626 2:mention,menu +627 4:mercy,merge,merit,merry +628 2:mesh,message +629 2:metal,method +631 2:middle,midnight +632 2:milk,million +633 1:mimic +634 4:mind,minimum,minor,minute +635 2:miracle,mirror +636 3:misery,miss,mistake +637 3:mix,mixed,mixture +641 5:mobile,model,modify,mom,moment +642 4:monitor,monkey,monster,month +643 4:moon,moral,more,morning +644 4:mosquito,mother,motion,motor +645 4:mountain,mouse,move,movie +646 4:much,muffin,mule,multiply +647 5:muscle,museum,mushroom,music,must +648 1:mutual +649 3:myself,mystery,myth +651 2:naive,name +652 2:napkin,narrow +653 3:nasty,nation,nature +654 2:near,neck +655 3:need,negative,neglect +656 2:neither,nephew +657 2:nerve,nest +658 3:net,network,neutral +659 3:never,news,next +661 2:nice,night +662 4:noble,noise,nominee,noodle +663 2:normal,north +664 1:nose +665 4:notable,note,nothing,notice +666 2:novel,now +669 4:nuclear,number,nurse,nut +671 1:oak +672 3:obey,object,oblige +673 4:obscure,observe,obtain,obvious +675 3:occur,ocean,october +676 1:odor +677 4:off,offer,office,often +678 1:oil +679 1:okay +681 3:old,olive,olympic +682 1:omit +683 5:once,one,onion,online,only +684 5:open,opera,opinion,oppose,option +691 6:orange,orbit,orchard,order,ordinary,organ +692 3:orient,original,orphan +693 1:ostrich +694 1:other +695 4:outdoor,outer,output,outside +696 3:oval,oven,over +697 2:own,owner +698 3:oxygen,oyster,ozone +711 6:pact,paddle,page,pair,palace,palm +712 5:panda,panel,panic,panther,paper +713 6:parade,parent,park,parrot,party,pass +714 5:patch,path,patient,patrol,pattern +715 3:pause,pave,payment +716 4:peace,peanut,pear,peasant +717 5:pelican,pen,penalty,pencil,people +718 5:pepper,perfect,permit,person,pet +719 4:phone,photo,phrase,physical +721 4:piano,picnic,picture,piece +722 5:pig,pigeon,pill,pilot,pink +723 5:pioneer,pipe,pistol,pitch,pizza +724 5:place,planet,plastic,plate,play +725 5:please,pledge,pluck,plug,plunge +726 3:poem,poet,point +727 5:polar,pole,police,pond,pony +728 6:pool,popular,portion,position,possible,post +729 5:potato,pottery,poverty,powder,power +731 2:practice,praise +732 6:predict,prefer,prepare,present,pretty,prevent +733 3:price,pride,primary +735 5:print,priority,prison,private,prize +736 4:problem,process,produce,profit +737 5:program,project,promote,proof,property +739 4:prosper,protect,proud,provide +741 2:public,pudding +742 3:pull,pulp,pulse +743 2:pumpkin,punch +744 2:pupil,puppy +745 4:purchase,purity,purpose,purse +746 3:push,put,puzzle +749 1:pyramid +751 3:quality,quantum,quarter +752 1:question +753 3:quick,quit,quiz +754 1:quote +761 1:rabbit +762 3:raccoon,race,rack +763 2:radar,radio +764 3:rail,rain,raise +765 2:rally,ramp +766 3:ranch,random,range +767 2:rapid,rare +768 2:rate,rather +769 3:raven,raw,razor +771 3:ready,real,reason +772 2:rebel,rebuild +773 5:recall,receive,recipe,record,recycle +774 1:reduce +775 3:reflect,reform,refuse +776 3:region,regret,regular +777 1:reject +778 4:relax,release,relief,rely +779 4:remain,remember,remind,remove +781 3:render,renew,rent +782 1:reopen +783 4:repair,repeat,replace,report +784 1:require +785 6:rescue,resemble,resist,resource,response,result +786 3:retire,retreat,return +787 1:reunion +788 2:reveal,review +789 1:reward +791 1:rhythm +792 6:rib,ribbon,rice,rich,ride,ridge +793 5:rifle,right,rigid,ring,riot +794 5:ripple,risk,ritual,rival,river +795 5:road,roast,robot,robust,rocket +796 5:romance,roof,rookie,room,rose +797 5:rotate,rough,round,route,royal +798 3:rubber,rude,rug +799 4:rule,run,runway,rural +811 5:sad,saddle,sadness,safe,sail +812 5:salad,salmon,salon,salt,salute +813 3:same,sample,sand +814 4:satisfy,satoshi,sauce,sausage +815 2:save,say +816 4:scale,scan,scare,scatter +817 3:scene,scheme,school +818 4:science,scissors,scorpion,scout +819 4:scrap,screen,script,scrub +821 4:sea,search,season,seat +822 4:second,secret,section,security +823 6:seed,seek,segment,select,sell,seminar +824 3:senior,sense,sentence +825 6:series,service,session,settle,setup,seven +831 4:shadow,shaft,shallow,share +832 3:shed,shell,sheriff +833 5:shield,shift,shine,ship,shiver +834 2:shock,shoe +836 5:shoot,shop,short,shoulder,shove +837 2:shrimp,shrug +838 1:shuffle +839 1:shy +841 4:sibling,sick,side,siege +842 6:sight,sign,silent,silk,silly,silver +843 4:similar,simple,since,sing +844 5:siren,sister,situate,six,size +845 2:skate,sketch +846 5:ski,skill,skin,skirt,skull +847 4:slab,slam,sleep,slender +848 4:slice,slide,slight,slim +849 4:slogan,slot,slow,slush +851 5:small,smart,smile,smoke,smooth +852 5:snack,snake,snap,sniff,snow +853 1:soap +854 3:soccer,social,sock +855 2:soda,soft +856 5:solar,soldier,solid,solution,solve +857 3:someone,song,soon +858 2:sorry,sort +859 5:soul,sound,soup,source,south +861 4:space,spare,spatial,spawn +862 5:speak,special,speed,spell,spend +863 1:sphere +864 5:spice,spider,spike,spin,spirit +865 1:split +866 5:spoil,sponsor,spoon,sport,spot +867 3:spray,spread,spring +868 1:spy +869 3:square,squeeze,squirrel +871 6:stable,stadium,staff,stage,stairs,stamp +872 4:stand,start,state,stay +873 5:steak,steel,stem,step,stereo +874 3:stick,still,sting +875 6:stock,stomach,stone,stool,story,stove +876 5:strategy,street,strike,strong,struggle +877 3:student,stuff,stumble +878 1:style +881 3:subject,submit,subway +882 2:success,such +883 4:sudden,suffer,sugar,suggest +884 2:suit,summer +885 3:sun,sunny,sunset +886 3:super,supply,supreme +887 6:sure,surface,surge,surprise,surround,survey +888 2:suspect,sustain +891 4:swallow,swamp,swap,swarm +892 2:swear,sweet +893 4:swift,swim,swing,switch +894 1:sword +898 4:symbol,symptom,syrup,system +911 4:table,tackle,tag,tail, +912 5:talent,talk,tank,tape,target +913 4:task,taste,tattoo,taxi +914 3:teach,team,tell +915 4:ten,tenant,tennis,tent +916 3:term,test,text +921 2:thank,that +922 5:theme,then,theory,there,they +923 3:thing,this,thought +924 3:three,thrive,throw +925 2:thumb,thunder +926 2:ticket,tide +927 4:tiger,tilt,timber,time +928 2:tiny,tip +929 3:tired,tissue,title +931 4:toast,tobacco,today,toddler +932 3:toe,together,toilet +933 3:token,tomato,tomorrow +934 3:tone,tongue,tonight +935 2:tool,tooth +936 3:top,topic,topple +937 3:torch,tornado,tortoise +938 3:toss,total,tourist +939 4:toward,tower,town,toy +941 5:track,trade,traffic,tragic,train +942 5:transfer,trap,trash,travel,tray +943 3:treat,tree,trend +944 6:trial,tribe,trick,trigger,trim,trip +945 2:trophy,trouble +946 6:truck,true,truly,trumpet,trust,truth +947 1:try +951 5:tube,tuition,tumble,tuna,tunnel +952 3:turkey,turn,turtle +953 6:twelve,twenty,twice,twin,twist,two +954 2:type,typical +961 2:ugly,umbrella +962 4:unable,unaware,uncle,uncover +963 5:under,undo,unfair,unfold,unhappy +964 4:uniform,unique,unit,universe +965 5:unknown,unlock,until,unusual,unveil +966 6:update,upgrade,uphold,upon,upper,upset +967 2:urban,urge +968 6:usage,use,used,useful,useless,usual +969 1:utility +971 6:vacant,vacuum,vague,valid,valley,valve +972 6:van,vanish,vapor,various,vast,vault +973 5:vehicle,velvet,vendor,venture,venue +974 6:verb,verify,version,very,vessel,veteran +975 5:viable,vibrant,vicious,victory,video +976 6:view,village,vintage,violin,virtual,virus +977 5:visa,visit,visual,vital,vivid +978 3:vocal,voice,void +979 4:volcano,volume,vote,voyage +981 3:wage,wagon,wait +982 4:walk,wall,walnut,want +983 3:warfare,warm,warrior +984 6:wash,wasp,waste,water,wave,way +985 5:wealth,weapon,wear,weasel,weather +986 3:web,wedding,weekend +987 4:weird,welcome,west,wet +988 6:whale,what,wheat,wheel,when,where +989 2:whip,whisper +991 5:wide,width,wife,wild,will +992 5:win,window,wine,wing,wink +993 2:winner,winter +994 5:wire,wisdom,wise,wish,witness +995 5:wolf,woman,wonder,wood,wool +996 5:word,work,world,worry,worth +997 6:wrap,wreck,wrestle,wrist,write,wrong +998 6:yard,year,yellow,you,young,youth +999 4:zebra,zero,zone,zoo From 15fcda21ce0597281cada810dac785258414aac1 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Wed, 23 Nov 2016 13:12:15 +0100 Subject: [PATCH 16/23] update protobuf --- firmware/protob/messages.pb.c | 8 +++++--- firmware/protob/messages.pb.h | 31 ++++++++++++++++++------------- firmware/protob/types.pb.h | 11 +++++++++++ 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/firmware/protob/messages.pb.c b/firmware/protob/messages.pb.c index 7193d53704..7decf55dc0 100644 --- a/firmware/protob/messages.pb.c +++ b/firmware/protob/messages.pb.c @@ -204,18 +204,20 @@ const pb_field_t EntropyAck_fields[2] = { PB_LAST_FIELD }; -const pb_field_t RecoveryDevice_fields[8] = { +const pb_field_t RecoveryDevice_fields[9] = { PB_FIELD2( 1, UINT32 , OPTIONAL, STATIC , FIRST, RecoveryDevice, word_count, word_count, 0), PB_FIELD2( 2, BOOL , OPTIONAL, STATIC , OTHER, RecoveryDevice, passphrase_protection, word_count, 0), PB_FIELD2( 3, BOOL , OPTIONAL, STATIC , OTHER, RecoveryDevice, pin_protection, passphrase_protection, 0), PB_FIELD2( 4, STRING , OPTIONAL, STATIC , OTHER, RecoveryDevice, language, pin_protection, &RecoveryDevice_language_default), PB_FIELD2( 5, STRING , OPTIONAL, STATIC , OTHER, RecoveryDevice, label, language, 0), PB_FIELD2( 6, BOOL , OPTIONAL, STATIC , OTHER, RecoveryDevice, enforce_wordlist, label, 0), - PB_FIELD2( 7, UINT32 , OPTIONAL, STATIC , OTHER, RecoveryDevice, u2f_counter, enforce_wordlist, 0), + PB_FIELD2( 8, UINT32 , OPTIONAL, STATIC , OTHER, RecoveryDevice, type, enforce_wordlist, 0), + PB_FIELD2( 9, UINT32 , OPTIONAL, STATIC , OTHER, RecoveryDevice, u2f_counter, type, 0), PB_LAST_FIELD }; -const pb_field_t WordRequest_fields[1] = { +const pb_field_t WordRequest_fields[2] = { + PB_FIELD2( 1, ENUM , OPTIONAL, STATIC , FIRST, WordRequest, type, type, 0), PB_LAST_FIELD }; diff --git a/firmware/protob/messages.pb.h b/firmware/protob/messages.pb.h index 7123f4495b..55950650ac 100644 --- a/firmware/protob/messages.pb.h +++ b/firmware/protob/messages.pb.h @@ -125,10 +125,6 @@ typedef struct _WipeDevice { uint8_t dummy_field; } WipeDevice; -typedef struct _WordRequest { - uint8_t dummy_field; -} WordRequest; - typedef struct _Address { char address[41]; } Address; @@ -676,6 +672,8 @@ typedef struct _RecoveryDevice { char label[33]; bool has_enforce_wordlist; bool enforce_wordlist; + bool has_type; + uint32_t type; bool has_u2f_counter; uint32_t u2f_counter; } RecoveryDevice; @@ -825,6 +823,11 @@ typedef struct _WordAck { char word[12]; } WordAck; +typedef struct _WordRequest { + bool has_type; + WordRequestType type; +} WordRequest; + /* Default values for struct fields */ extern const char GetAddress_coin_name_default[17]; extern const InputScriptType GetAddress_script_type_default; @@ -873,8 +876,8 @@ extern const uint32_t SimpleSignTx_lock_time_default; #define ResetDevice_init_default {false, 0, false, 256u, false, 0, false, 0, false, "english", false, "", false, 0} #define EntropyRequest_init_default {0} #define EntropyAck_init_default {false, {0, {0}}} -#define RecoveryDevice_init_default {false, 0, false, 0, false, 0, false, "english", false, "", false, 0, false, 0} -#define WordRequest_init_default {0} +#define RecoveryDevice_init_default {false, 0, false, 0, false, 0, false, "english", false, "", false, 0, false, 0, false, 0} +#define WordRequest_init_default {false, (WordRequestType)0} #define WordAck_init_default {""} #define SignMessage_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}, {0, {0}}, false, "Bitcoin"} #define VerifyMessage_init_default {false, "", false, {0, {0}}, false, {0, {0}}, false, "Bitcoin"} @@ -939,8 +942,8 @@ extern const uint32_t SimpleSignTx_lock_time_default; #define ResetDevice_init_zero {false, 0, false, 0, false, 0, false, 0, false, "", false, "", false, 0} #define EntropyRequest_init_zero {0} #define EntropyAck_init_zero {false, {0, {0}}} -#define RecoveryDevice_init_zero {false, 0, false, 0, false, 0, false, "", false, "", false, 0, false, 0} -#define WordRequest_init_zero {0} +#define RecoveryDevice_init_zero {false, 0, false, 0, false, 0, false, "", false, "", false, 0, false, 0, false, 0} +#define WordRequest_init_zero {false, (WordRequestType)0} #define WordAck_init_zero {""} #define SignMessage_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}, {0, {0}}, false, ""} #define VerifyMessage_init_zero {false, "", false, {0, {0}}, false, {0, {0}}, false, ""} @@ -1109,7 +1112,8 @@ extern const uint32_t SimpleSignTx_lock_time_default; #define RecoveryDevice_language_tag 4 #define RecoveryDevice_label_tag 5 #define RecoveryDevice_enforce_wordlist_tag 6 -#define RecoveryDevice_u2f_counter_tag 7 +#define RecoveryDevice_type_tag 8 +#define RecoveryDevice_u2f_counter_tag 9 #define ResetDevice_display_random_tag 1 #define ResetDevice_strength_tag 2 #define ResetDevice_passphrase_protection_tag 3 @@ -1150,6 +1154,7 @@ extern const uint32_t SimpleSignTx_lock_time_default; #define VerifyMessage_message_tag 3 #define VerifyMessage_coin_name_tag 4 #define WordAck_word_tag 1 +#define WordRequest_type_tag 1 /* Struct field encoding specification for nanopb */ extern const pb_field_t Initialize_fields[1]; @@ -1181,8 +1186,8 @@ extern const pb_field_t LoadDevice_fields[9]; extern const pb_field_t ResetDevice_fields[8]; extern const pb_field_t EntropyRequest_fields[1]; extern const pb_field_t EntropyAck_fields[2]; -extern const pb_field_t RecoveryDevice_fields[8]; -extern const pb_field_t WordRequest_fields[1]; +extern const pb_field_t RecoveryDevice_fields[9]; +extern const pb_field_t WordRequest_fields[2]; extern const pb_field_t WordAck_fields[2]; extern const pb_field_t SignMessage_fields[4]; extern const pb_field_t VerifyMessage_fields[5]; @@ -1249,8 +1254,8 @@ extern const pb_field_t DebugLinkFlashErase_fields[2]; #define ResetDevice_size 72 #define EntropyRequest_size 0 #define EntropyAck_size 131 -#define RecoveryDevice_size 72 -#define WordRequest_size 0 +#define RecoveryDevice_size 78 +#define WordRequest_size 6 #define WordAck_size 14 #define SignMessage_size 1094 #define VerifyMessage_size 1156 diff --git a/firmware/protob/types.pb.h b/firmware/protob/types.pb.h index a7dd51e8a2..68b5ec6a55 100644 --- a/firmware/protob/types.pb.h +++ b/firmware/protob/types.pb.h @@ -69,6 +69,17 @@ typedef enum _PinMatrixRequestType { PinMatrixRequestType_PinMatrixRequestType_NewSecond = 3 } PinMatrixRequestType; +typedef enum _RecoveryDeviceType { + RecoveryDeviceType_RecoveryDeviceType_ScrambledWords = 0, + RecoveryDeviceType_RecoveryDeviceType_Matrix = 1 +} RecoveryDeviceType; + +typedef enum _WordRequestType { + WordRequestType_WordRequestType_Plain = 0, + WordRequestType_WordRequestType_Matrix9 = 1, + WordRequestType_WordRequestType_Matrix6 = 2 +} WordRequestType; + /* Struct definitions */ typedef struct _CoinType { bool has_coin_name; From b4eaf7dbafbe66b8f0de1c6a292c7b4271b94697 Mon Sep 17 00:00:00 2001 From: Saleem Rashid Date: Wed, 23 Nov 2016 19:22:28 +0000 Subject: [PATCH 17/23] timer: Fix non-critical integer overflow (#129) Every 4294967295 milliseconds (2 ^ 32 - 1), system_millis will overflow. This means that every 49.71 days, system_millis will reset to zero. Comparisons like `system_millis < (system_millis + 1)` would fail if the latter had overflown and the former had not. This is non-critical because the worst case is that one second could be skipped or the screen could lock early. This poses no threat to the exponential backoff used for protection against brute force. --- firmware/layout2.c | 2 +- firmware/trezor.c | 2 +- firmware/usb.c | 5 +++-- timer.c | 2 +- timer.h | 4 +--- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/firmware/layout2.c b/firmware/layout2.c index 91c409b6e6..cac754c6b8 100644 --- a/firmware/layout2.c +++ b/firmware/layout2.c @@ -84,7 +84,7 @@ void layoutHome(void) oledRefresh(); // Reset lock screen timeout - system_millis_lock = system_millis + SCREEN_TIMEOUT_MILLIS; + system_millis_lock_start = system_millis; } const char *str_amount(uint64_t amnt, const char *abbr, char *buf, int len) diff --git a/firmware/trezor.c b/firmware/trezor.c index 129fd61a4e..f5a64ae83d 100644 --- a/firmware/trezor.c +++ b/firmware/trezor.c @@ -79,7 +79,7 @@ void check_lock_screen(void) // if homescreen is shown for longer than 10 minutes, lock too if (layoutLast == layoutHome) { - if (system_millis >= system_millis_lock) { + if ((system_millis - system_millis_lock_start) >= 60000) { // lock the screen session_clear(true); layoutScreensaver(); diff --git a/firmware/usb.c b/firmware/usb.c index df50f1640e..e15dd49798 100644 --- a/firmware/usb.c +++ b/firmware/usb.c @@ -429,8 +429,9 @@ char usbTiny(char set) void usbSleep(uint32_t millis) { - uint32_t end = system_millis + millis; - while (end > system_millis) { + uint32_t start = system_millis; + + while ((system_millis - start) < millis) { usbd_poll(usbd_dev); } } diff --git a/timer.c b/timer.c index e45ce740f0..aad29663f9 100644 --- a/timer.c +++ b/timer.c @@ -27,7 +27,7 @@ volatile uint32_t system_millis; /* Screen timeout */ -uint32_t system_millis_lock; +uint32_t system_millis_lock_start; /* * Initialise the Cortex-M3 SysTick timer diff --git a/timer.h b/timer.h index 53713cdfe5..69759c33ff 100644 --- a/timer.h +++ b/timer.h @@ -24,9 +24,7 @@ extern volatile uint32_t system_millis; /* Screen timeout */ -extern uint32_t system_millis_lock; - -#define SCREEN_TIMEOUT_MILLIS (1000 * 60 * 10) /* 10 minutes */ +extern uint32_t system_millis_lock_start; void timer_init(void); From 5c00b24307a567b0e63a33cfa2595eab43b6f1b4 Mon Sep 17 00:00:00 2001 From: Saleem Rashid Date: Sat, 26 Nov 2016 07:48:04 -0500 Subject: [PATCH 18/23] trezor: Fix screen timeout (#131) --- firmware/trezor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/trezor.c b/firmware/trezor.c index f5a64ae83d..f3b31403ab 100644 --- a/firmware/trezor.c +++ b/firmware/trezor.c @@ -79,7 +79,7 @@ void check_lock_screen(void) // if homescreen is shown for longer than 10 minutes, lock too if (layoutLast == layoutHome) { - if ((system_millis - system_millis_lock_start) >= 60000) { + if ((system_millis - system_millis_lock_start) >= 600000) { // lock the screen session_clear(true); layoutScreensaver(); From 5f203d0a0cca7f12939fbb21688d26daadc7e8a5 Mon Sep 17 00:00:00 2001 From: Saleem Rashid Date: Sun, 4 Dec 2016 22:24:01 +0000 Subject: [PATCH 19/23] debug: Improve debugging API (#134) * Allow DEBUG_LOG without DEBUG_LINK * Move debugInt() to debug.c --- firmware/debug.c | 12 ++++++++++++ firmware/debug.h | 3 +++ firmware/trezor.c | 5 ++++- firmware/u2f.c | 16 ---------------- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/firmware/debug.c b/firmware/debug.c index 3bb5dcfec9..09d55db7fa 100644 --- a/firmware/debug.c +++ b/firmware/debug.c @@ -20,6 +20,7 @@ #include "trezor.h" #include "debug.h" #include "oled.h" +#include "util.h" #if DEBUG_LOG @@ -50,4 +51,15 @@ void debugLog(int level, const char *bucket, const char *text) oledDebug(text); } +char *debugInt(const uint32_t i) +{ + static uint8_t n = 0; + static char id[8][9]; + uint32hex(i, id[n]); + debugLog(0, "", id[n]); + char *ret = (char *)id[n]; + n = (n + 1) % 8; + return ret; +} + #endif diff --git a/firmware/debug.h b/firmware/debug.h index 4b71db3a5b..93cfd0f36b 100644 --- a/firmware/debug.h +++ b/firmware/debug.h @@ -21,14 +21,17 @@ #define __DEBUG_H__ #include "trezor.h" +#include #if DEBUG_LOG void debugLog(int level, const char *bucket, const char *text); +char *debugInt(const uint32_t i); #else #define debugLog(L, B, T) do{}while(0) +#define debugInt(I) do{}while(0) #endif diff --git a/firmware/trezor.c b/firmware/trezor.c index f3b31403ab..6e491691a7 100644 --- a/firmware/trezor.c +++ b/firmware/trezor.c @@ -99,8 +99,11 @@ int main(void) timer_init(); -#if DEBUG_LINK +#if DEBUG_LOG oledSetDebug(1); +#endif + +#if DEBUG_LINK storage_reset(); // wipe storage if debug link storage_reset_uuid(); storage_commit(); diff --git a/firmware/u2f.c b/firmware/u2f.c index 56ee8f76bf..e52364e0d8 100644 --- a/firmware/u2f.c +++ b/firmware/u2f.c @@ -92,22 +92,6 @@ typedef struct { uint8_t chal[U2F_CHAL_SIZE]; } U2F_AUTHENTICATE_SIG_STR; - -#if DEBUG_LOG -char *debugInt(const uint32_t i) -{ - static uint8_t n = 0; - static char id[8][9]; - uint32hex(i, id[n]); - debugLog(0, "", id[n]); - char *ret = (char *)id[n]; - n = (n + 1) % 8; - return ret; -} -#else -#define debugInt(I) do{}while(0) -#endif - static uint32_t dialog_timeout = 0; uint32_t next_cid(void) From ee3a7cbcfa3b17c093efd4be20635f034d3ee7a8 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Tue, 6 Dec 2016 16:09:09 +0100 Subject: [PATCH 20/23] fix bug when long press of buttons breaks usb communication in bootloader, bump bl version to 1.3.1 --- bootloader/bootloader.h | 4 ++-- bootloader/usb.c | 21 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/bootloader/bootloader.h b/bootloader/bootloader.h index 687c3fffbf..a1f505eb44 100644 --- a/bootloader/bootloader.h +++ b/bootloader/bootloader.h @@ -22,14 +22,14 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 3 -#define VERSION_PATCH 0 +#define VERSION_PATCH 1 #define STR(X) #X #define VERSTR(X) STR(X) #define VERSION_MAJOR_CHAR "\x01" #define VERSION_MINOR_CHAR "\x03" -#define VERSION_PATCH_CHAR "\x00" +#define VERSION_PATCH_CHAR "\x01" #include "memory.h" diff --git a/bootloader/usb.c b/bootloader/usb.c index 51172ca2c0..de9373a901 100644 --- a/bootloader/usb.c +++ b/bootloader/usb.c @@ -485,23 +485,38 @@ void usbInit(void) void checkButtons(void) { + static bool btn_left = false, btn_right = false, btn_final = false; + if (btn_final) { + return; + } uint16_t state = gpio_port_read(BTN_PORT); if ((state & (BTN_PIN_YES | BTN_PIN_NO)) != (BTN_PIN_YES | BTN_PIN_NO)) { if ((state & BTN_PIN_NO) != BTN_PIN_NO) { - oledInvert(0, 0, 3, 3); + btn_left = true; } if ((state & BTN_PIN_YES) != BTN_PIN_YES) { - oledInvert(OLED_WIDTH - 4, 0, OLED_WIDTH - 1, 3); + btn_right = true; } + } + if (btn_left) { + oledBox(0, 0, 3, 3, true); + } + if (btn_right) { + oledBox(OLED_WIDTH - 4, 0, OLED_WIDTH - 1, 3, true); + } + if (btn_left || btn_right) { oledRefresh(); } + if (btn_left && btn_right) { + btn_final = true; + } } void usbLoop(void) { for (;;) { usbd_poll(usbd_dev); - if (flash_state == STATE_READY || flash_state == STATE_OPEN) { + if (!firmware_present && (flash_state == STATE_READY || flash_state == STATE_OPEN)) { checkButtons(); } } From 1763a5b64768c28d54e1d0125c4c45467036df64 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Mon, 12 Dec 2016 12:16:48 +0100 Subject: [PATCH 21/23] use new hdnode_private_ckd_cached API --- firmware/fsm.c | 2 +- firmware/signing.c | 2 +- firmware/transaction.c | 2 +- firmware/u2f.c | 2 +- vendor/trezor-crypto | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/firmware/fsm.c b/firmware/fsm.c index 7369fee325..3cea7f2331 100644 --- a/firmware/fsm.c +++ b/firmware/fsm.c @@ -138,7 +138,7 @@ HDNode *fsm_getDerivedNode(const char *curve, uint32_t *address_n, size_t addres if (!address_n || address_n_count == 0) { return &node; } - if (hdnode_private_ckd_cached(&node, address_n, address_n_count) == 0) { + if (hdnode_private_ckd_cached(&node, address_n, address_n_count, NULL) == 0) { fsm_sendFailure(FailureType_Failure_Other, "Failed to derive private key"); layoutHome(); return 0; diff --git a/firmware/signing.c b/firmware/signing.c index 22dcd91b46..0a00cf3532 100644 --- a/firmware/signing.c +++ b/firmware/signing.c @@ -518,7 +518,7 @@ void signing_txack(TransactionType *tx) if (idx2 == idx1) { memcpy(&input, tx->inputs, sizeof(TxInputType)); memcpy(&node, root, sizeof(HDNode)); - if (hdnode_private_ckd_cached(&node, tx->inputs[0].address_n, tx->inputs[0].address_n_count) == 0) { + if (hdnode_private_ckd_cached(&node, tx->inputs[0].address_n, tx->inputs[0].address_n_count, NULL) == 0) { fsm_sendFailure(FailureType_Failure_Other, "Failed to derive private key"); signing_abort(); return; diff --git a/firmware/transaction.c b/firmware/transaction.c index c4667b963b..36a8bdc90b 100644 --- a/firmware/transaction.c +++ b/firmware/transaction.c @@ -68,7 +68,7 @@ int compile_output(const CoinType *coin, const HDNode *root, TxOutputType *in, T if (in->address_n_count > 0) { HDNode node; memcpy(&node, root, sizeof(HDNode)); - if (hdnode_private_ckd_cached(&node, in->address_n, in->address_n_count) == 0) { + if (hdnode_private_ckd_cached(&node, in->address_n, in->address_n_count, NULL) == 0) { return 0; } layoutProgressUpdate(true); diff --git a/firmware/u2f.c b/firmware/u2f.c index e52364e0d8..ddf560209e 100644 --- a/firmware/u2f.c +++ b/firmware/u2f.c @@ -460,7 +460,7 @@ const HDNode *getDerivedNode(uint32_t *address_n, size_t address_n_count) if (!address_n || address_n_count == 0) { return &node; } - if (hdnode_private_ckd_cached(&node, address_n, address_n_count) == 0) { + if (hdnode_private_ckd_cached(&node, address_n, address_n_count, NULL) == 0) { layoutHome(); debugLog(0, "", "ERR: Derive private failed"); return 0; diff --git a/vendor/trezor-crypto b/vendor/trezor-crypto index 6aac03d2d8..b55473a01e 160000 --- a/vendor/trezor-crypto +++ b/vendor/trezor-crypto @@ -1 +1 @@ -Subproject commit 6aac03d2d853eadaf9e91452b15381594fcf09b1 +Subproject commit b55473a01ecfd095d1f4bd068c8d3385b993b986 From 9eb87245ba3d963e9e6e953a8ea5863d76676389 Mon Sep 17 00:00:00 2001 From: Roman Zeyde Date: Mon, 2 Jan 2017 14:12:48 +0200 Subject: [PATCH 22/23] usb: exclude hid_report_descriptor_debug from non-debug build (#135) --- firmware/usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/firmware/usb.c b/firmware/usb.c index e15dd49798..7691b1f74f 100644 --- a/firmware/usb.c +++ b/firmware/usb.c @@ -80,6 +80,7 @@ static const uint8_t hid_report_descriptor[] = { 0xc0 // END_COLLECTION }; +#if DEBUG_LINK static const uint8_t hid_report_descriptor_debug[] = { 0x06, 0x01, 0xff, // USAGE_PAGE (Vendor Defined) 0x09, 0x01, // USAGE (1) @@ -98,6 +99,7 @@ static const uint8_t hid_report_descriptor_debug[] = { 0x91, 0x02, // OUTPUT (Data,Var,Abs) 0xc0 // END_COLLECTION }; +#endif static const uint8_t hid_report_descriptor_u2f[] = { 0x06, 0xd0, 0xf1, // USAGE_PAGE (FIDO Alliance) From 32f3c54cc43262125401f1538acbf3d301bab672 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Wed, 4 Jan 2017 18:52:55 +0100 Subject: [PATCH 23/23] fix whitespace --- firmware/usb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/usb.c b/firmware/usb.c index 7691b1f74f..77576e48e8 100644 --- a/firmware/usb.c +++ b/firmware/usb.c @@ -265,8 +265,8 @@ static const struct usb_interface ifaces[] = {{ .altsetting = hid_iface_debug, #endif }, { - .num_altsetting = 1, - .altsetting = hid_iface_u2f, + .num_altsetting = 1, + .altsetting = hid_iface_u2f, }}; static const struct usb_config_descriptor config = { @@ -344,7 +344,7 @@ static void hid_u2f_rx_callback(usbd_device *dev, uint8_t ep) static uint8_t buf[64] __attribute__ ((aligned(4))); debugLog(0, "", "hid_u2f_rx_callback"); - if ( usbd_ep_read_packet(dev, ENDPOINT_ADDRESS_U2F_OUT, buf, 64) != 64) return; + if ( usbd_ep_read_packet(dev, ENDPOINT_ADDRESS_U2F_OUT, buf, 64) != 64) return; u2fhid_read(tiny, (const U2FHID_FRAME *) (void*) buf); }