diff --git a/firmware/crypto.c b/firmware/crypto.c index 04cb9549d..84450c935 100644 --- a/firmware/crypto.c +++ b/firmware/crypto.c @@ -256,10 +256,14 @@ int cryptoMessageDecrypt(curve_point *nonce, uint8_t *payload, pb_size_t payload uint8_t *cryptoHDNodePathToPubkey(const HDNodePathType *hdnodepath) { static HDNode node; - hdnode_from_xpub(hdnodepath->node.depth, hdnodepath->node.fingerprint, hdnodepath->node.child_num, hdnodepath->node.chain_code.bytes, hdnodepath->node.public_key.bytes, &node); + 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; + } uint32_t i; for (i = 0; i < hdnodepath->address_n_count; i++) { - hdnode_public_ckd(&node, hdnodepath->address_n[i]); + if (hdnode_public_ckd(&node, hdnodepath->address_n[i]) == 0) { + return 0; + }; } return node.public_key; } diff --git a/firmware/fsm.c b/firmware/fsm.c index 185160568..8f8af81b5 100644 --- a/firmware/fsm.c +++ b/firmware/fsm.c @@ -89,18 +89,23 @@ HDNode *fsm_getRootNode(void) return &node; } -void fsm_deriveKey(HDNode *node, uint32_t *address_n, size_t address_n_count) +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); } for (i = 0; i < address_n_count; i++) { - hdnode_private_ckd(node, address_n[i]); + if (hdnode_private_ckd(node, address_n[i]) == 0) { + fsm_sendFailure(FailureType_Failure_Other, "Failed to derive private key"); + layoutHome(); + return 0; + } if (address_n_count > 3) { layoutProgress("Preparing keys", 1000 * i / address_n_count, i); } } + return 1; } void fsm_msgInitialize(Initialize *msg) @@ -265,8 +270,7 @@ void fsm_msgGetPublicKey(GetPublicKey *msg) HDNode *node = fsm_getRootNode(); if (!node) return; - - fsm_deriveKey(node, msg->address_n, msg->address_n_count); + if (fsm_deriveKey(node, msg->address_n, msg->address_n_count) == 0) return; resp->node.depth = node->depth; resp->node.fingerprint = node->fingerprint; @@ -395,7 +399,7 @@ void fsm_msgCipherKeyValue(CipherKeyValue *msg) } HDNode *node = fsm_getRootNode(); if (!node) return; - fsm_deriveKey(node, msg->address_n, msg->address_n_count); + if (fsm_deriveKey(node, msg->address_n, msg->address_n_count) == 0) return; bool encrypt = msg->has_encrypt && msg->encrypt; bool ask_on_encrypt = msg->has_ask_on_encrypt && msg->ask_on_encrypt; @@ -499,8 +503,7 @@ void fsm_msgGetAddress(GetAddress *msg) layoutHome(); return; } - - fsm_deriveKey(node, msg->address_n, msg->address_n_count); + if (fsm_deriveKey(node, msg->address_n, msg->address_n_count) == 0) return; if (msg->has_multisig) { if (cryptoMultisigPubkeyIndex(&(msg->multisig), node->public_key) < 0) { @@ -567,8 +570,8 @@ void fsm_msgSignMessage(SignMessage *msg) layoutHome(); return; } + if (fsm_deriveKey(node, msg->address_n, msg->address_n_count) == 0) return; - fsm_deriveKey(node, msg->address_n, msg->address_n_count); layoutProgressSwipe("Signing", 0, 0); if (cryptoMessageSign(msg->message.bytes, msg->message.size, node->private_key, resp->signature.bytes) == 0) { resp->has_address = true; @@ -642,7 +645,8 @@ void fsm_msgEncryptMessage(EncryptMessage *msg) } node = fsm_getRootNode(); if (!node) return; - fsm_deriveKey(node, msg->address_n, msg->address_n_count); + if (fsm_deriveKey(node, msg->address_n, msg->address_n_count) == 0) return; + hdnode_fill_public_key(node); ecdsa_get_address_raw(node->public_key, coin->address_type, address_raw); } @@ -690,7 +694,8 @@ void fsm_msgDecryptMessage(DecryptMessage *msg) } HDNode *node = fsm_getRootNode(); if (!node) return; - fsm_deriveKey(node, msg->address_n, msg->address_n_count); + if (fsm_deriveKey(node, msg->address_n, msg->address_n_count) == 0) return; + layoutProgressSwipe("Decrypting", 0, 0); RESP_INIT(DecryptedMessage); bool display_only = false; diff --git a/firmware/signing.c b/firmware/signing.c index 565cd4f19..1ee9e0e8c 100644 --- a/firmware/signing.c +++ b/firmware/signing.c @@ -281,7 +281,11 @@ void signing_txack(TransactionType *tx) memcpy(&node, root, sizeof(HDNode)); uint32_t k; for (k = 0; k < tx->inputs[0].address_n_count; k++) { - hdnode_private_ckd(&node, tx->inputs[0].address_n[k]); + if (hdnode_private_ckd(&node, tx->inputs[0].address_n[k]) == 0) { + fsm_sendFailure(FailureType_Failure_Other, "Failed to derive private key"); + signing_abort(); + return; + } } if (tx->inputs[0].script_type == InputScriptType_SPENDMULTISIG) { if (!tx->inputs[0].has_multisig) { diff --git a/firmware/storage.c b/firmware/storage.c index 99f21558b..05dc8cbea 100644 --- a/firmware/storage.c +++ b/firmware/storage.c @@ -233,7 +233,9 @@ bool storage_getRootNode(HDNode *node) if (!protectPassphrase()) { return false; } - hdnode_from_xprv(storage.node.depth, storage.node.fingerprint, storage.node.child_num, storage.node.chain_code.bytes, storage.node.private_key.bytes, &sessionRootNode); + if (hdnode_from_xprv(storage.node.depth, storage.node.fingerprint, storage.node.child_num, storage.node.chain_code.bytes, storage.node.private_key.bytes, &sessionRootNode) == 0) { + return false; + } if (storage.has_passphrase_protection && storage.passphrase_protection && strlen(sessionPassphrase)) { // decrypt hd node uint8_t secret[64]; @@ -257,7 +259,9 @@ bool storage_getRootNode(HDNode *node) uint8_t seed[64]; layoutProgressSwipe("Waking up", 0, 0); mnemonic_to_seed(storage.mnemonic, sessionPassphrase, seed, get_root_node_callback); // BIP-0039 - hdnode_from_seed(seed, sizeof(seed), &sessionRootNode); + if (hdnode_from_seed(seed, sizeof(seed), &sessionRootNode) == 0) { + return false; + } memcpy(node, &sessionRootNode, sizeof(HDNode)); sessionRootNodeCached = true; return true; diff --git a/firmware/transaction.c b/firmware/transaction.c index 0e7a0e71b..e9bfa840a 100644 --- a/firmware/transaction.c +++ b/firmware/transaction.c @@ -60,7 +60,9 @@ int compile_output(const CoinType *coin, const HDNode *root, TxOutputType *in, T uint32_t k; memcpy(&node, root, sizeof(HDNode)); for (k = 0; k < in->address_n_count; k++) { - hdnode_private_ckd(&node, in->address_n[k]); + if (hdnode_private_ckd(&node, in->address_n[k]) == 0) { + return 0; + } } ecdsa_get_address(node.public_key, coin->address_type, in->address); } else