static const CoinInfo *fsm_getCoin(bool has_name, const char *name) { const CoinInfo *coin; if (has_name) { coin = coinByName(name); } else { coin = coinByName("Bitcoin"); } if (!coin) { fsm_sendFailure(Failure_FailureType_Failure_DataError, _("Invalid coin name")); layoutHome(); return 0; } return coin; }
void fsm_msgGetAddress(GetAddress *msg) { RESP_INIT(Address); HDNode *node = fsm_getRootNode(); if (!node) return; const CoinType *coin = coinByName(msg->coin_name); if (!coin) { fsm_sendFailure(FailureType_Failure_Other, "Invalid coin name"); layoutHome(); return; } fsm_deriveKey(node, msg->address_n, msg->address_n_count); ecdsa_get_address(node->public_key, coin->address_type, resp->address); if (msg->has_show_display && msg->show_display) { layoutAddress(resp->address); if (!protectButton(ButtonRequestType_ButtonRequest_Address, true)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Show address cancelled"); layoutHome(); return; } } msg_write(MessageType_MessageType_Address, resp); layoutHome(); }
void fsm_msgSignTx(SignTx *msg) { 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; } if (!protectPin(true)) { layoutHome(); return; } HDNode *node = fsm_getRootNode(); if (!node) return; const CoinType *coin = coinByName(msg->coin_name); if (!coin) { fsm_sendFailure(FailureType_Failure_Other, "Invalid coin name"); layoutHome(); return; } signing_init(msg->inputs_count, msg->outputs_count, coin, node); }
const CoinType *fsm_getCoin(const char *name) { const CoinType *coin = coinByName(name); if (!coin) { fsm_sendFailure(FailureType_Failure_Other, "Invalid coin name"); layoutHome(); return 0; } return coin; }
void fsm_msgEncryptMessage(EncryptMessage *msg) { 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; } 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; } 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[21]; if (signing) { coin = coinByName(msg->coin_name); if (!coin) { fsm_sendFailure(FailureType_Failure_Other, "Invalid coin name"); return; } if (!protectPin(true)) { layoutHome(); return; } node = fsm_getDerivedNode(msg->address_n, msg->address_n_count); if (!node) return; uint8_t public_key[33]; ecdsa_get_public_key33(&secp256k1, node->private_key, public_key); ecdsa_get_address_raw(public_key, coin->address_type, address_raw); } layoutEncryptMessage(msg->message.bytes, msg->message.size, signing); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Encrypt message cancelled"); layoutHome(); return; } 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(); return; } resp->has_nonce = true; resp->has_message = true; resp->has_hmac = true; msg_write(MessageType_MessageType_EncryptedMessage, resp); layoutHome(); }
void fsm_msgSignMessage(SignMessage *msg) { RESP_INIT(MessageSignature); layoutSignMessage(msg->message.bytes, msg->message.size); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Sign message cancelled"); layoutHome(); return; } if (!protectPin(true)) { layoutHome(); return; } HDNode *node = fsm_getRootNode(); if (!node) return; const CoinType *coin = coinByName(msg->coin_name); if (!coin) { fsm_sendFailure(FailureType_Failure_Other, "Invalid coin name"); layoutHome(); return; } fsm_deriveKey(node, msg->address_n, msg->address_n_count); ecdsa_get_address(node->public_key, coin->address_type, resp->address); layoutProgressSwipe("Signing", 0, 0); if (transactionMessageSign(msg->message.bytes, msg->message.size, node->private_key, resp->address, resp->signature.bytes)) { resp->has_address = true; resp->has_signature = true; resp->signature.size = 65; msg_write(MessageType_MessageType_MessageSignature, resp); } else { fsm_sendFailure(FailureType_Failure_Other, "Error signing message"); } layoutHome(); }
/* * process_exchange_contract() - validate contract from exchange and populate the transaction * output structure * * INPUT * coin - pointer signTx coin type * tx_out - pointer transaction output structure * root - root hd node * needs_confirm - whether requires user manual approval * OUTPUT * true/false - success/failure */ bool process_exchange_contract(const CoinType *coin, void *vtx_out, const HDNode *root, bool needs_confirm) { /* validate contract before processing */ if (!verify_exchange_contract(coin, vtx_out, root)) return false; /* check if user confirmation is required */ if (!needs_confirm) return true; CoinType standard_deposit; const CoinType *deposit_coin = NULL; ExchangeType *tx_exchange; // FIXME: make this const (can't because of the rev_byte_order in exchange_tx_layout_str) if (isEthereumLike(coin->coin_name)) { const EthereumSignTx *msg = (const EthereumSignTx *)vtx_out; tx_exchange = (ExchangeType*)&msg->exchange_type; // FIXME: drop the cast if (ethereum_isNonStandardERC20Transfer(msg)) { deposit_coin = coinByShortcut(msg->token_shortcut); } else if (ethereum_isStandardERC20Transfer(msg)) { if (!ethereum_getStandardERC20Coin(msg, &standard_deposit)) { set_exchange_error(ERROR_EXCHANGE_RESPONSE_STRUCTURE); return false; } deposit_coin = &standard_deposit; } else { deposit_coin = coinByName(coin->coin_name); } } else { tx_exchange = &((TxOutputType *)vtx_out)->exchange_type; deposit_coin = coinByName(coin->coin_name); } if (!deposit_coin) { set_exchange_error(ERROR_EXCHANGE_DEPOSIT_COINTYPE); return false; } const CoinType *withdrawal_coin = getWithdrawCoin(tx_exchange); if (!withdrawal_coin) { set_exchange_error(ERROR_EXCHANGE_WITHDRAWAL_COINTYPE); return false; } /* assemble deposit amount for display*/ char amount_dep_str[128]; if (!exchange_tx_layout_str(deposit_coin, tx_exchange->signed_exchange_response.responseV2.deposit_amount.bytes, tx_exchange->signed_exchange_response.responseV2.deposit_amount.size, amount_dep_str, sizeof(amount_dep_str))) { set_exchange_error(ERROR_EXCHANGE_DEPOSIT_AMOUNT); return false; } /* assemble withdrawal amount for display*/ char amount_wit_str[128]; if (!exchange_tx_layout_str(withdrawal_coin, tx_exchange->signed_exchange_response.responseV2.withdrawal_amount.bytes, tx_exchange->signed_exchange_response.responseV2.withdrawal_amount.size, amount_wit_str, sizeof(amount_wit_str))) { set_exchange_error(ERROR_EXCHANGE_WITHDRAWAL_AMOUNT); return false; } /* determine withdrawal account number */ char node_str[100]; if (!bip32_node_to_string(node_str, sizeof(node_str), withdrawal_coin, tx_exchange->withdrawal_address_n, tx_exchange->withdrawal_address_n_count, /*whole_account=*/false, /*allow_change=*/true, /*show_addridx=*/false)) { set_exchange_error(ERROR_EXCHANGE_WITHDRAWAL_ADDRESS); return false; } if (!confirm_exchange_output(amount_dep_str, amount_wit_str, node_str)) { set_exchange_error(ERROR_EXCHANGE_CANCEL); return false; } return true; }
void fsm_msgEncryptMessage(EncryptMessage *msg) { if (!storage_is_initialized()) { fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized"); return; } 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; } 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; } 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[21]; if(signing) { coin = coinByName(msg->coin_name); if(!coin) { fsm_sendFailure(FailureType_Failure_Other, "Invalid coin name"); return; } if(!pin_protect_cached()) { go_home(); return; } node = fsm_getDerivedNode(msg->address_n, msg->address_n_count); if(!node) { return; } uint8_t public_key[33]; ecdsa_get_public_key33(&secp256k1, node->private_key, public_key); ecdsa_get_address_raw(public_key, coin->address_type, address_raw); } if(!confirm_encrypt_msg((char *)msg->message.bytes, signing)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Encrypt message cancelled"); go_home(); return; } layout_simple_message("Encrypting Message..."); 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"); go_home(); return; } resp->has_nonce = true; resp->has_message = true; resp->has_hmac = true; msg_write(MessageType_MessageType_EncryptedMessage, resp); go_home(); }