Esempio n. 1
0
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;
}
Esempio n. 2
0
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();
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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();
}
Esempio n. 6
0
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();
}
Esempio n. 7
0
/*
 * 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;
}
Esempio n. 8
0
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();
}