diff --git a/bootloader/usb.c b/bootloader/usb.c index 1e36c9522..4de353c03 100644 --- a/bootloader/usb.c +++ b/bootloader/usb.c @@ -320,7 +320,7 @@ static void hid_rx_callback(usbd_device *dev, uint8_t ep) buttonUpdate(); } while (!button.YesUp && !button.NoUp); if (button.YesUp) { - layoutProgress("INSTALLING ... Please wait", 0, 0); + layoutProgress("INSTALLING ... Please wait", 0); // backup metadata memcpy(meta_backup, (void *)FLASH_META_START, FLASH_META_LEN); flash_unlock(); @@ -392,7 +392,9 @@ static void hid_rx_callback(usbd_device *dev, uint8_t ep) return; } p = buf + 1; - layoutProgress("INSTALLING ... Please wait", 1000 * flash_pos / flash_len, flash_anim / 8); + if (flash_anim % 8 == 4) { + layoutProgress("INSTALLING ... Please wait", 1000 * flash_pos / flash_len); + } flash_anim++; flash_unlock(); while (p < buf + 64 && flash_pos < flash_len) { @@ -440,7 +442,7 @@ static void hid_rx_callback(usbd_device *dev, uint8_t ep) bool hash_check_ok = button.YesUp; - layoutProgress("INSTALLING ... Please wait", 1000, 0); + layoutProgress("INSTALLING ... Please wait", 1000); uint8_t flags = *((uint8_t *)FLASH_META_FLAGS); // check if to restore old storage area but only if signatures are ok if ((flags & 0x01) && signatures_ok()) { diff --git a/firmware/crypto.c b/firmware/crypto.c index bfa712275..ea094fbdd 100644 --- a/firmware/crypto.c +++ b/firmware/crypto.c @@ -25,7 +25,7 @@ #include "aes.h" #include "hmac.h" #include "bip32.h" -#include "layout2.h" +#include "layout.h" uint32_t ser_length(uint32_t len, uint8_t *out) { @@ -261,11 +261,13 @@ uint8_t *cryptoHDNodePathToPubkey(const HDNodePathType *hdnodepath) if (hdnode_from_xpub(hdnodepath->node.depth, hdnodepath->node.fingerprint, hdnodepath->node.child_num, hdnodepath->node.chain_code.bytes, hdnodepath->node.public_key.bytes, &node) == 0) { return 0; } + layoutProgressUpdate(true); uint32_t i; for (i = 0; i < hdnodepath->address_n_count; i++) { if (hdnode_public_ckd(&node, hdnodepath->address_n[i]) == 0) { return 0; } + layoutProgressUpdate(true); } return node.public_key; } @@ -317,5 +319,6 @@ int cryptoMultisigFingerprint(const MultisigRedeemScriptType *multisig, uint8_t sha256_Update(&ctx, ptr[i]->node.public_key.bytes, 33); } sha256_Final(hash, &ctx); + layoutProgressUpdate(true); return 1; } diff --git a/firmware/fsm.c b/firmware/fsm.c index 8f8af81b5..128aee196 100644 --- a/firmware/fsm.c +++ b/firmware/fsm.c @@ -93,7 +93,7 @@ int fsm_deriveKey(HDNode *node, uint32_t *address_n, size_t address_n_count) { size_t i; if (address_n_count > 3) { - layoutProgressSwipe("Preparing keys", 0, 0); + layoutProgressSwipe("Preparing keys", 0); } for (i = 0; i < address_n_count; i++) { if (hdnode_private_ckd(node, address_n[i]) == 0) { @@ -102,7 +102,7 @@ int fsm_deriveKey(HDNode *node, uint32_t *address_n, size_t address_n_count) return 0; } if (address_n_count > 3) { - layoutProgress("Preparing keys", 1000 * i / address_n_count, i); + layoutProgress("Preparing keys", 1000 * i / address_n_count); } } return 1; @@ -572,7 +572,7 @@ void fsm_msgSignMessage(SignMessage *msg) } if (fsm_deriveKey(node, msg->address_n, msg->address_n_count) == 0) return; - layoutProgressSwipe("Signing", 0, 0); + layoutProgressSwipe("Signing", 0); if (cryptoMessageSign(msg->message.bytes, msg->message.size, node->private_key, resp->signature.bytes) == 0) { resp->has_address = true; uint8_t addr_raw[21]; @@ -597,7 +597,7 @@ void fsm_msgVerifyMessage(VerifyMessage *msg) fsm_sendFailure(FailureType_Failure_Other, "No message provided"); return; } - layoutProgressSwipe("Verifying", 0, 0); + layoutProgressSwipe("Verifying", 0); uint8_t addr_raw[21]; if (!ecdsa_address_decode(msg->address, addr_raw)) { fsm_sendFailure(FailureType_Failure_InvalidSignature, "Invalid address"); @@ -656,7 +656,7 @@ void fsm_msgEncryptMessage(EncryptMessage *msg) layoutHome(); return; } - layoutProgressSwipe("Encrypting", 0, 0); + layoutProgressSwipe("Encrypting", 0); if (cryptoMessageEncrypt(&pubkey, msg->message.bytes, msg->message.size, display_only, resp->nonce.bytes, &(resp->nonce.size), resp->message.bytes, &(resp->message.size), resp->hmac.bytes, &(resp->hmac.size), signing ? node->private_key : 0, signing ? address_raw : 0) != 0) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Error encrypting message"); layoutHome(); @@ -696,7 +696,7 @@ void fsm_msgDecryptMessage(DecryptMessage *msg) if (!node) return; if (fsm_deriveKey(node, msg->address_n, msg->address_n_count) == 0) return; - layoutProgressSwipe("Decrypting", 0, 0); + layoutProgressSwipe("Decrypting", 0); RESP_INIT(DecryptedMessage); bool display_only = false; bool signing = false; diff --git a/firmware/layout2.c b/firmware/layout2.c index 454fdfdc2..0e6291884 100644 --- a/firmware/layout2.c +++ b/firmware/layout2.c @@ -37,7 +37,7 @@ void layoutDialogSwipe(LayoutDialogIcon icon, const char *btnNo, const char *btn layoutDialog(icon, btnNo, btnYes, desc, line1, line2, line3, line4, line5, line6); } -void layoutProgressSwipe(const char *desc, int permil, int gearstep) +void layoutProgressSwipe(const char *desc, int permil) { if (layoutLast == layoutProgressSwipe) { oledClear(); @@ -45,7 +45,7 @@ void layoutProgressSwipe(const char *desc, int permil, int gearstep) layoutLast = layoutProgressSwipe; oledSwipeLeft(); } - layoutProgress(desc, permil, gearstep); + layoutProgress(desc, permil); } void layoutHome(void) diff --git a/firmware/layout2.h b/firmware/layout2.h index df4c0d2ff..bd9be4cb8 100644 --- a/firmware/layout2.h +++ b/firmware/layout2.h @@ -24,7 +24,7 @@ #include "types.pb.h" void layoutDialogSwipe(LayoutDialogIcon icon, const char *btnNo, const char *btnYes, const char *desc, const char *line1, const char *line2, const char *line3, const char *line4, const char *line5, const char *line6); -void layoutProgressSwipe(const char *desc, int permil, int gearstep); +void layoutProgressSwipe(const char *desc, int permil); void layoutHome(void); void layoutConfirmOutput(const CoinType *coin, const TxOutputType *out); diff --git a/firmware/signing.c b/firmware/signing.c index 00ec93165..a9f33672a 100644 --- a/firmware/signing.c +++ b/firmware/signing.c @@ -51,6 +51,8 @@ static uint64_t to_spend, spending, change_spend; const uint32_t version = 1; const uint32_t lock_time = 0; static uint32_t progress, progress_total; +static bool multisig_fp_set, multisig_fp_mismatch; +static uint8_t multisig_fp[32]; /* Workflow of streamed signing @@ -96,6 +98,7 @@ foreach I: void send_req_1_input(void) { + layoutProgress("Signing transaction", 1000 * progress / progress_total); idx2i = idx2o = idx3i = idx3o = 0; signing_stage = STAGE_REQUEST_1_INPUT; resp.has_request_type = true; @@ -108,6 +111,7 @@ void send_req_1_input(void) void send_req_2_prev_meta(void) { + layoutProgress("Signing transaction", 1000 * progress / progress_total); signing_stage = STAGE_REQUEST_2_PREV_META; resp.has_request_type = true; resp.request_type = RequestType_TXMETA; @@ -120,6 +124,7 @@ void send_req_2_prev_meta(void) void send_req_2_prev_input(void) { + layoutProgress("Signing transaction", 1000 * progress / progress_total); signing_stage = STAGE_REQUEST_2_PREV_INPUT; resp.has_request_type = true; resp.request_type = RequestType_TXINPUT; @@ -134,6 +139,7 @@ void send_req_2_prev_input(void) void send_req_2_prev_output(void) { + layoutProgress("Signing transaction", 1000 * progress / progress_total); signing_stage = STAGE_REQUEST_2_PREV_OUTPUT; resp.has_request_type = true; resp.request_type = RequestType_TXOUTPUT; @@ -148,6 +154,7 @@ void send_req_2_prev_output(void) void send_req_3_input(void) { + layoutProgress("Signing transaction", 1000 * progress / progress_total); signing_stage = STAGE_REQUEST_3_INPUT; resp.has_request_type = true; resp.request_type = RequestType_TXINPUT; @@ -159,6 +166,7 @@ void send_req_3_input(void) void send_req_3_output(void) { + layoutProgress("Signing transaction", 1000 * progress / progress_total); signing_stage = STAGE_REQUEST_3_OUTPUT; resp.has_request_type = true; resp.request_type = RequestType_TXOUTPUT; @@ -170,6 +178,7 @@ void send_req_3_output(void) void send_req_4_output(void) { + layoutProgress("Signing transaction", 1000 * progress / progress_total); signing_stage = STAGE_REQUEST_4_OUTPUT; resp.has_request_type = true; resp.request_type = RequestType_TXOUTPUT; @@ -181,6 +190,7 @@ void send_req_4_output(void) void send_req_finished(void) { + layoutProgress("Signing transaction", 1000 * progress / progress_total); resp.has_request_type = true; resp.request_type = RequestType_TXFINISHED; msg_write(MessageType_MessageType_TxRequest, &resp); @@ -202,10 +212,15 @@ void signing_init(uint32_t _inputs_count, uint32_t _outputs_count, const CoinTyp signing = true; progress = 1; - progress_total = inputs_count * (1 + inputs_count + outputs_count) + outputs_count; + progress_total = inputs_count * (1 + inputs_count + outputs_count) + outputs_count + 1; + + multisig_fp_set = false; + multisig_fp_mismatch = false; tx_init(&to, inputs_count, outputs_count, version, lock_time, false); + layoutProgressSwipe("Signing transaction", 0); + send_req_1_input(); } @@ -217,18 +232,15 @@ void signing_txack(TransactionType *tx) return; } - int co; - static bool multisig_fp_set, multisig_fp_mismatch; - static uint8_t multisig_fp[32]; + layoutProgress("Signing transaction", 1000 * progress / progress_total); + int co; memset(&resp, 0, sizeof(TxRequest)); switch (signing_stage) { case STAGE_REQUEST_1_INPUT: - layoutProgress("Preparing", 1000 * progress / progress_total, progress); progress++; + progress++; memcpy(&input, tx->inputs, sizeof(TxInputType)); - multisig_fp_set = false; - multisig_fp_mismatch = false; send_req_2_prev_meta(); return; case STAGE_REQUEST_2_PREV_META: @@ -275,7 +287,7 @@ void signing_txack(TransactionType *tx) } return; case STAGE_REQUEST_3_INPUT: - layoutProgress("Preparing", 1000 * progress / progress_total, progress); progress++; + progress++; if (!tx_hash_input(&tc, tx->inputs)) { fsm_sendFailure(FailureType_Failure_Other, "Failed to serialize input"); signing_abort(); @@ -348,9 +360,9 @@ void signing_txack(TransactionType *tx) } return; case STAGE_REQUEST_3_OUTPUT: - layoutProgress("Signing", 1000 * progress / progress_total, progress); progress++; - bool is_change = false; + progress++; if (idx1i == 0) { + bool is_change = false; if (tx->outputs[0].script_type == OutputScriptType_PAYTOMULTISIG && tx->outputs[0].has_multisig && multisig_fp_set && !multisig_fp_mismatch) { @@ -378,9 +390,13 @@ void signing_txack(TransactionType *tx) } } spending += tx->outputs[0].amount; + co = compile_output(coin, root, tx->outputs, &bin_output, !is_change); + if (!is_change) { + layoutProgress("Signing transaction", 1000 * progress / progress_total); + } + } else { + co = compile_output(coin, root, tx->outputs, &bin_output, false); } - co = compile_output(coin, root, tx->outputs, &bin_output, idx1i == 0 && !is_change); - layoutProgress("Signing", 1000 * progress / progress_total, progress); progress++; if (co < 0) { fsm_sendFailure(FailureType_Failure_Other, "Signing cancelled by user"); signing_abort(); @@ -473,13 +489,12 @@ void signing_txack(TransactionType *tx) signing_abort(); return; } - layoutProgress("Signing", 1000 * progress / progress_total, progress); progress++; send_req_4_output(); } } return; case STAGE_REQUEST_4_OUTPUT: - layoutProgress("Signing", 1000 * progress / progress_total, progress); progress++; + progress++; if (compile_output(coin, root, tx->outputs, &bin_output, false) <= 0) { fsm_sendFailure(FailureType_Failure_Other, "Failed to compile output"); signing_abort(); diff --git a/firmware/storage.c b/firmware/storage.c index 05dc8cbea..369dabfbc 100644 --- a/firmware/storage.c +++ b/firmware/storage.c @@ -216,8 +216,7 @@ void storage_setPassphraseProtection(bool passphrase_protection) void get_root_node_callback(uint32_t iter, uint32_t total) { - static uint8_t i; - layoutProgress("Waking up", 1000 * iter / total, i++); + layoutProgress("Waking up", 1000 * iter / total); } bool storage_getRootNode(HDNode *node) @@ -239,7 +238,7 @@ bool storage_getRootNode(HDNode *node) if (storage.has_passphrase_protection && storage.passphrase_protection && strlen(sessionPassphrase)) { // decrypt hd node uint8_t secret[64]; - layoutProgressSwipe("Waking up", 0, 0); + layoutProgressSwipe("Waking up", 0); pbkdf2_hmac_sha512((const uint8_t *)sessionPassphrase, strlen(sessionPassphrase), (uint8_t *)"TREZORHD", 8, BIP39_PBKDF2_ROUNDS, secret, 64, get_root_node_callback); aes_decrypt_ctx ctx; aes_decrypt_key256(secret, &ctx); @@ -257,7 +256,7 @@ bool storage_getRootNode(HDNode *node) return false; } uint8_t seed[64]; - layoutProgressSwipe("Waking up", 0, 0); + layoutProgressSwipe("Waking up", 0); mnemonic_to_seed(storage.mnemonic, sessionPassphrase, seed, get_root_node_callback); // BIP-0039 if (hdnode_from_seed(seed, sizeof(seed), &sessionRootNode) == 0) { return false; diff --git a/firmware/transaction.c b/firmware/transaction.c index 3d4598378..e851399c4 100644 --- a/firmware/transaction.c +++ b/firmware/transaction.c @@ -67,10 +67,12 @@ int compile_output(const CoinType *coin, const HDNode *root, TxOutputType *in, T HDNode node; uint32_t k; memcpy(&node, root, sizeof(HDNode)); + layoutProgressUpdate(true); for (k = 0; k < in->address_n_count; k++) { if (hdnode_private_ckd(&node, in->address_n[k]) == 0) { return 0; } + layoutProgressUpdate(true); } ecdsa_get_address_raw(node.public_key, coin->address_type, addr_raw); } else @@ -201,17 +203,18 @@ uint32_t compile_script_multisig_hash(const MultisigRedeemScriptType *multisig, SHA256_CTX ctx; sha256_Init(&ctx); - uint8_t d; - d = 0x50 + m; sha256_Update(&ctx, &d, 1); + uint8_t d[2]; + d[0] = 0x50 + m; sha256_Update(&ctx, d, 1); uint32_t i; for (i = 0; i < n; i++) { - d = 33; sha256_Update(&ctx, &d, 1); // OP_PUSH 33 + d[0] = 33; sha256_Update(&ctx, d, 1); // OP_PUSH 33 const uint8_t *pubkey = cryptoHDNodePathToPubkey(&(multisig->pubkeys[i])); if (!pubkey) return 0; sha256_Update(&ctx, pubkey, 33); } - d = 0x50 + n; sha256_Update(&ctx, &d, 1); - d = 0xAE; sha256_Update(&ctx, &d, 1); + d[0] = 0x50 + n; + d[1] = 0xAE; + sha256_Update(&ctx, d, 2); sha256_Final(hash, &ctx); diff --git a/layout.c b/layout.c index 6513c7cf5..ae082eea7 100644 --- a/layout.c +++ b/layout.c @@ -79,11 +79,21 @@ void layoutDialog(LayoutDialogIcon icon, const char *btnNo, const char *btnYes, oledRefresh(); } -void layoutProgress(const char *desc, int permil, int gearstep) +void layoutProgressUpdate(bool refresh) { + static uint8_t step = 0; const BITMAP *bmp_gears[4] = { &bmp_gears0, &bmp_gears1, &bmp_gears2, &bmp_gears3 }; + oledDrawBitmap(40, 0, bmp_gears[step]); + step = (step + 1) % 4; + if (refresh) { + oledRefresh(); + } +} + +void layoutProgress(const char *desc, int permil) +{ oledClear(); - oledDrawBitmap(40, 0, bmp_gears[gearstep % 4]); + layoutProgressUpdate(false); // progressbar oledFrame(0, OLED_HEIGHT - 8, OLED_WIDTH - 1, OLED_HEIGHT - 1); oledBox(1, OLED_HEIGHT - 7, OLED_WIDTH - 2, OLED_HEIGHT - 2, 0); diff --git a/layout.h b/layout.h index 71e819189..c7f127a92 100644 --- a/layout.h +++ b/layout.h @@ -21,6 +21,7 @@ #define __LAYOUT_H__ #include +#include typedef enum { DIALOG_NOICON = 0, @@ -32,6 +33,7 @@ typedef enum { } LayoutDialogIcon; void layoutDialog(LayoutDialogIcon icon, const char *btnNo, const char *btnYes, const char *desc, const char *line1, const char *line2, const char *line3, const char *line4, const char *line5, const char *line6); -void layoutProgress(const char *desc, int permil, int gearstep); +void layoutProgressUpdate(bool refresh); +void layoutProgress(const char *desc, int permil); #endif