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; } const CoinType *coin = fsm_getCoin(msg->coin_name); if (!coin) return; layout_simple_message("Verifying Message..."); uint8_t addr_raw[21]; if(!ecdsa_address_decode(msg->address, addr_raw)) { fsm_sendFailure(FailureType_Failure_InvalidSignature, "Invalid address"); } if(msg->signature.size == 65 && cryptoMessageVerify(coin, msg->message.bytes, msg->message.size, addr_raw, msg->signature.bytes) == 0) { if(review(ButtonRequestType_ButtonRequest_Other, "Message Verified", (char *)msg->message.bytes)) { fsm_sendSuccess("Message verified"); } } else { fsm_sendFailure(FailureType_Failure_InvalidSignature, "Invalid signature"); } go_home(); }
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; } layoutProgressSwipe("Verifying", 0); uint8_t addr_raw[21]; if (!ecdsa_address_decode(msg->address, addr_raw)) { fsm_sendFailure(FailureType_Failure_InvalidSignature, "Invalid address"); } if (msg->signature.size == 65 && cryptoMessageVerify(msg->message.bytes, msg->message.size, addr_raw, msg->signature.bytes) == 0) { layoutVerifyMessage(msg->message.bytes, msg->message.size); protectButton(ButtonRequestType_ButtonRequest_Other, true); fsm_sendSuccess("Message verified"); } else { fsm_sendFailure(FailureType_Failure_InvalidSignature, "Invalid signature"); } layoutHome(); }
/* * verify_exchange_contract() - Verify content of exchange contract is valid * * INPUT * exchange: exchange pointer * root - root hd node * OUTPUT * true/false - success/failure */ static bool verify_exchange_contract(const CoinType *coin, void *vtx_out, const HDNode *root) { ExchangeType *exchange; if (isEthereumLike(coin->coin_name)) { exchange = &((EthereumSignTx *)vtx_out)->exchange_type; /*Verify response structure from client is compatible*/ if (exchange->signed_exchange_response.has_response) { /*Obsolete response data structure detected. Should be ExchangeResponseV2! */ set_exchange_error(ERROR_EXCHANGE_RESPONSE_STRUCTURE); return false; } } else { exchange = &((TxOutputType *)vtx_out)->exchange_type; } void *tx_out_amount; char tx_out_address[sizeof(((ExchangeAddress *)NULL)->address)]; memset(tx_out_address, 0, sizeof(tx_out_address)); CoinType standard_deposit; const CoinType *deposit_coin = NULL; if (isEthereumLike(coin->coin_name)) { EthereumSignTx *tx_out = (EthereumSignTx *)vtx_out; tx_out->has_chain_id = coin->has_forkid; tx_out->chain_id = coin->forkid; if (ethereum_isNonStandardERC20Transfer(tx_out)) { // token specific address, shorcut, and value data2hex(tx_out->token_to.bytes, tx_out->token_to.size, tx_out_address); tx_out_amount = (void *)tx_out->token_value.bytes; deposit_coin = coinByShortcut(tx_out->token_shortcut); } else if (ethereum_isStandardERC20Transfer(tx_out)) { if (!ethereum_getStandardERC20Recipient(tx_out, tx_out_address, sizeof(tx_out_address)) || !ethereum_getStandardERC20Amount(tx_out, &tx_out_amount) || !ethereum_getStandardERC20Coin(tx_out, &standard_deposit)) { set_exchange_error(ERROR_EXCHANGE_RESPONSE_STRUCTURE); return false; } deposit_coin = &standard_deposit; } else { data2hex(tx_out->to.bytes, tx_out->to.size, tx_out_address); tx_out_amount = (void *)tx_out->value.bytes; deposit_coin = coin; } } else { TxOutputType *tx_out = (TxOutputType *)vtx_out; exchange = &tx_out->exchange_type; memcpy(tx_out_address, tx_out->address, sizeof(tx_out->address)); tx_out_amount = (void *)&tx_out->amount; deposit_coin = coin; } if (!deposit_coin) { set_exchange_error(ERROR_EXCHANGE_RESPONSE_STRUCTURE); return false; } /* verify Exchange signature */ uint8_t response_raw[sizeof(ExchangeResponseV2)]; memset(response_raw, 0, sizeof(response_raw)); int response_raw_filled_len = encode_pb( (const void *)&exchange->signed_exchange_response.responseV2, ExchangeResponseV2_fields, response_raw, sizeof(response_raw)); if(response_raw_filled_len == 0) { set_exchange_error(ERROR_EXCHANGE_SIGNATURE); return false; } const CoinType *signed_coin = coinByShortcut((const char *)"BTC"); if(cryptoMessageVerify(signed_coin, response_raw, response_raw_filled_len, ShapeShift_pubkey, (uint8_t *)exchange->signed_exchange_response.signature.bytes) != 0) { set_exchange_error(ERROR_EXCHANGE_SIGNATURE); return false; } /* verify Exchange API-Key */ if(memcmp(ShapeShift_api_key, exchange->signed_exchange_response.responseV2.api_key.bytes, sizeof(ShapeShift_api_key)) != 0) { set_exchange_error(ERROR_EXCHANGE_API_KEY); return false; } /* verify Deposit coin type */ if (!verify_coins_match(deposit_coin, getDepositCoin(exchange))) { set_exchange_error(ERROR_EXCHANGE_DEPOSIT_COINTYPE); return false; } /* verify Deposit address */ if(!addresses_same(tx_out_address, sizeof(tx_out_address), exchange->signed_exchange_response.responseV2.deposit_address.address, sizeof(exchange->signed_exchange_response.responseV2.deposit_address.address), isEthereumLike(coin->coin_name))) { set_exchange_error(ERROR_EXCHANGE_DEPOSIT_ADDRESS); return false; } /* verify Deposit amount*/ if(!verify_exchange_dep_amount(coin->coin_name, tx_out_amount, &exchange->signed_exchange_response.responseV2.deposit_amount)) { set_exchange_error(ERROR_EXCHANGE_DEPOSIT_AMOUNT); return false; } /* verify Withdrawal address */ const CoinType *withdraw_coin = getWithdrawCoin(exchange); if (!withdraw_coin) { set_exchange_error(ERROR_EXCHANGE_WITHDRAWAL_COINTYPE); return false; } if (!verify_coins_match(withdraw_coin, coinByNameOrTicker(exchange->withdrawal_coin_name))) { set_exchange_error(ERROR_EXCHANGE_WITHDRAWAL_COINTYPE); return false; } if (!verify_exchange_address( withdraw_coin, exchange->withdrawal_address_n_count, exchange->withdrawal_address_n, exchange->signed_exchange_response.responseV2.withdrawal_address.address, sizeof(exchange->signed_exchange_response.responseV2.withdrawal_address.address), root, withdraw_coin->has_contract_address)) { set_exchange_error(ERROR_EXCHANGE_WITHDRAWAL_ADDRESS); return false; } /* verify Return coin type */ const CoinType *return_coin = getReturnCoin(exchange); if (!return_coin) { set_exchange_error(ERROR_EXCHANGE_RETURN_COINTYPE); return false; } if (!verify_coins_match(deposit_coin, return_coin)) { set_exchange_error(ERROR_EXCHANGE_RETURN_COINTYPE); return false; } /* verify Return address */ if (!verify_exchange_address( return_coin, exchange->return_address_n_count, exchange->return_address_n, exchange->signed_exchange_response.responseV2.return_address.address, sizeof(exchange->signed_exchange_response.responseV2.return_address.address), root, return_coin->has_contract_address)) { set_exchange_error(ERROR_EXCHANGE_RETURN_ADDRESS); return false; } set_exchange_error(NO_EXCHANGE_ERROR); return true; }