Beispiel #1
0
static void test_privkey_valid_enc(const char *base58_str,
				cstring *payload,
				bool compress, bool is_testnet)
{
	assert(payload != NULL);

	cstring *pl = cstr_new_sz(payload->len + 1);
	cstr_append_buf(pl, payload->str, payload->len);
	if (compress)
		cstr_append_c(pl, 1);

	cstring *b58 = base58_encode_check(
		is_testnet ? PRIVKEY_ADDRESS_TEST : PRIVKEY_ADDRESS, true,
		pl->str, pl->len);
	assert(b58 != NULL);
	if (strcmp(b58->str, base58_str)) {
		fprintf(stderr, "base58: have %s, expected %s\n",
			b58->str, base58_str);
		assert(!strcmp(b58->str, base58_str));
	}

	cstr_free(b58, true);
	cstr_free(pl, true);
	cstr_free(payload, true);
}
Beispiel #2
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;
	}

	const CoinType *coin = fsm_getCoin(msg->coin_name);
	if (!coin) return;
	const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count);
	if (!node) return;

	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];
		ecdsa_get_address_raw(node->public_key, coin->address_type, addr_raw);
		base58_encode_check(addr_raw, 21, resp->address, sizeof(resp->address));
		resp->has_signature = true;
		resp->signature.size = 65;
		msg_write(MessageType_MessageType_MessageSignature, resp);
	} else {
		fsm_sendFailure(FailureType_Failure_Other, "Error signing message");
	}
	layoutHome();
}
Beispiel #3
0
void fsm_msgGetAddress(GetAddress *msg)
{
	RESP_INIT(Address);

	if (!protectPin(true)) {
		layoutHome();
		return;
	}

	const CoinType *coin = fsm_getCoin(msg->coin_name);
	if (!coin) return;
	const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count);
	if (!node) return;

	if (msg->has_multisig) {
		layoutProgressSwipe("Preparing", 0);
		if (cryptoMultisigPubkeyIndex(&(msg->multisig), node->public_key) < 0) {
			fsm_sendFailure(FailureType_Failure_Other, "Pubkey not found in multisig script");
			layoutHome();
			return;
		}
		uint8_t buf[32];
		if (compile_script_multisig_hash(&(msg->multisig), buf) == 0) {
			fsm_sendFailure(FailureType_Failure_Other, "Invalid multisig script");
			layoutHome();
			return;
		}
		ripemd160(buf, 32, buf + 1);
		buf[0] = coin->address_type_p2sh; // multisig cointype
		base58_encode_check(buf, 21, resp->address, sizeof(resp->address));
	} else {
		ecdsa_get_address(node->public_key, coin->address_type, resp->address, sizeof(resp->address));
	}

	if (msg->has_show_display && msg->show_display) {
		char desc[16];
		if (msg->has_multisig) {
			strlcpy(desc, "Msig __ of __:", sizeof(desc));
			const uint32_t m = msg->multisig.m;
			const uint32_t n = msg->multisig.pubkeys_count;
			desc[5] = (m < 10) ? ' ': ('0' + (m / 10));
			desc[6] = '0' + (m % 10);
			desc[11] = (n < 10) ? ' ': ('0' + (n / 10));
			desc[12] = '0' + (n % 10);
		} else {
			strlcpy(desc, "Address:", sizeof(desc));
		}
		layoutAddress(resp->address, desc);
		if (!protectButton(ButtonRequestType_ButtonRequest_Address, true)) {
			fsm_sendFailure(FailureType_Failure_ActionCancelled, "Show address cancelled");
			layoutHome();
			return;
		}
	}

	msg_write(MessageType_MessageType_Address, resp);
	layoutHome();
}
Beispiel #4
0
void fsm_msgDecryptMessage(DecryptMessage *msg)
{
	if (!msg->has_nonce) {
		fsm_sendFailure(FailureType_Failure_SyntaxError, "No nonce provided");
		return;
	}
	if (!msg->has_message) {
		fsm_sendFailure(FailureType_Failure_SyntaxError, "No message provided");
		return;
	}
	if (!msg->has_hmac) {
		fsm_sendFailure(FailureType_Failure_SyntaxError, "No message hmac provided");
		return;
	}
	curve_point nonce_pubkey;
	if (msg->nonce.size != 33 || ecdsa_read_pubkey(&secp256k1, msg->nonce.bytes, &nonce_pubkey) == 0) {
		fsm_sendFailure(FailureType_Failure_SyntaxError, "Invalid nonce provided");
		return;
	}
	if (!protectPin(true)) {
		layoutHome();
		return;
	}
	const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count);
	if (!node) return;

	layoutProgressSwipe("Decrypting", 0);
	RESP_INIT(DecryptedMessage);
	bool display_only = false;
	bool signing = false;
	uint8_t address_raw[21];
	if (cryptoMessageDecrypt(&nonce_pubkey, msg->message.bytes, msg->message.size, msg->hmac.bytes, msg->hmac.size, node->private_key, resp->message.bytes, &(resp->message.size), &display_only, &signing, address_raw) != 0) {
		fsm_sendFailure(FailureType_Failure_ActionCancelled, "Error decrypting message");
		layoutHome();
		return;
	}
	if (signing) {
		base58_encode_check(address_raw, 21, resp->address, sizeof(resp->address));
	}
	layoutDecryptMessage(resp->message.bytes, resp->message.size, signing ? resp->address : 0);
	protectButton(ButtonRequestType_ButtonRequest_Other, true);
	if (display_only) {
		resp->has_address = false;
		resp->has_message = false;
		memset(resp->address, 0, sizeof(resp->address));
		memset(&(resp->message), 0, sizeof(resp->message));
	} else {
		resp->has_address = signing;
		resp->has_message = true;
	}
	msg_write(MessageType_MessageType_DecryptedMessage, resp);
	layoutHome();
}
Beispiel #5
0
int script_output_to_address(const uint8_t *script, int scriptlen, char *addr, int addrsize)
{
	uint8_t raw[35];

	// P2PKH
	if (scriptlen == 25 && script[0] == 0x76 && script[1] == 0xA9 && script[2] == 0x14 && script[23] == 0x88 && script[24] == 0xAC) {
		raw[0] = 0x00;
		memcpy(raw + 1, script + 3, 20);
		return base58_encode_check(raw, 1 + 20, addr, addrsize);
	}

	// P2SH
	if (scriptlen == 23 && script[0] == 0xA9 && script[1] == 0x14 && script[22] == 0x87) {
		raw[0] = 0x05;
		memcpy(raw + 1, script + 2, 20);
		return base58_encode_check(raw, 1 + 20, addr, addrsize);
	}

	// P2WPKH
	if (scriptlen == 22 && script[0] == 0x00 && script[1] == 0x14) {
		raw[0] = 0x06;
		raw[1] = 0x00;
		raw[2] = 0x00;
		memcpy(raw + 3, script + 2, 20);
		return base58_encode_check(raw, 3 + 20, addr, addrsize);
	}

	// P2WSH
	if (scriptlen == 34 && script[0] == 0x00 && script[1] == 0x20) {
		raw[0] = 0x0A;
		raw[1] = 0x00;
		raw[2] = 0x00;
		memcpy(raw + 3, script + 2, 32);
		return base58_encode_check(raw, 3 + 32, addr, addrsize);
	}

	return 0;
}
Beispiel #6
0
void fsm_msgSignMessage(SignMessage *msg)
{
    RESP_INIT(MessageSignature);

	if (!storage_is_initialized()) 
    {
		fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized");
		return;
	}

    if(!confirm(ButtonRequestType_ButtonRequest_SignMessage, "Sign Message",
                (char *)msg->message.bytes))
    {
        fsm_sendFailure(FailureType_Failure_ActionCancelled, "Sign message cancelled");
        go_home();
        return;
    }

    if(!pin_protect_cached())
    {
        go_home();
        return;
    }

    const CoinType *coin = fsm_getCoin(msg->coin_name);

    if(!coin) { return; }

    const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count);

    if(!node) { return; }

    if(cryptoMessageSign(coin, msg->message.bytes, msg->message.size, node->private_key,
                         resp->signature.bytes) == 0)
    {
        resp->has_address = true;
        uint8_t addr_raw[21];
        ecdsa_get_address_raw(node->public_key, coin->address_type, addr_raw);
        base58_encode_check(addr_raw, 21, resp->address, sizeof(resp->address));
        resp->has_signature = true;
        resp->signature.size = 65;
        msg_write(MessageType_MessageType_MessageSignature, resp);
    }
    else
    {
        fsm_sendFailure(FailureType_Failure_Other, "Error signing message");
    }

    go_home();
}
Beispiel #7
0
void hdnode_serialize(const HDNode *node, uint32_t version, char use_public, char *str, int strsize)
{
	uint8_t node_data[78];
	write_be(node_data, version);
	node_data[4] = node->depth;
	write_be(node_data + 5, node->fingerprint);
	write_be(node_data + 9, node->child_num);
	memcpy(node_data + 13, node->chain_code, 32);
	if (use_public) {
		memcpy(node_data + 45, node->public_key, 33);
	} else {
		node_data[45] = 0;
		memcpy(node_data + 46, node->private_key, 32);
	}
	base58_encode_check(node_data, 78, str, strsize);
}
Beispiel #8
0
static void test_pubkey_valid_enc(const char *base58_str,
				cstring *payload,
				const char *addrtype_str,
				bool is_testnet)
{
	assert(payload != NULL);

	bool addrtype_pubkey = (strcmp(addrtype_str, "pubkey") == 0);
	bool addrtype_script = (strcmp(addrtype_str, "script") == 0);
	assert(addrtype_pubkey || addrtype_script);

	enum bitc_address_type addrtype;
	if (addrtype_pubkey) {
		if (is_testnet)
			addrtype = PUBKEY_ADDRESS_TEST;
		else
			addrtype = PUBKEY_ADDRESS;
	} else {
		if (is_testnet)
			addrtype = SCRIPT_ADDRESS_TEST;
		else
			addrtype = SCRIPT_ADDRESS;
	}

	cstring *b58 = base58_encode_check(
		addrtype, true,
		payload->str, payload->len);
	if (strcmp(b58->str, base58_str)) {
		fprintf(stderr, "base58: have %s, expected %s\n",
			b58->str, base58_str);
		assert(!strcmp(b58->str, base58_str));
	}

	cstr_free(b58, true);
	cstr_free(payload, true);
}
Beispiel #9
0
void fsm_msgSignIdentity(SignIdentity *msg)
{
	RESP_INIT(SignedIdentity);

	layoutSignIdentity(&(msg->identity), msg->has_challenge_visual ? msg->challenge_visual : 0);
	if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) {
		fsm_sendFailure(FailureType_Failure_ActionCancelled, "Sign identity cancelled");
		layoutHome();
		return;
	}

	if (!protectPin(true)) {
		layoutHome();
		return;
	}

	uint8_t hash[32];
	if (!msg->has_identity || cryptoIdentityFingerprint(&(msg->identity), hash) == 0) {
		fsm_sendFailure(FailureType_Failure_Other, "Invalid identity");
		layoutHome();
		return;
	}

	uint32_t address_n[5];
	address_n[0] = 0x80000000 | 13;
	address_n[1] = 0x80000000 | hash[ 0] | (hash[ 1] << 8) | (hash[ 2] << 16) | (hash[ 3] << 24);
	address_n[2] = 0x80000000 | hash[ 4] | (hash[ 5] << 8) | (hash[ 6] << 16) | (hash[ 7] << 24);
	address_n[3] = 0x80000000 | hash[ 8] | (hash[ 9] << 8) | (hash[10] << 16) | (hash[11] << 24);
	address_n[4] = 0x80000000 | hash[12] | (hash[13] << 8) | (hash[14] << 16) | (hash[15] << 24);

	const HDNode *node = fsm_getDerivedNode(address_n, 5);
	if (!node) return;

	uint8_t public_key[33];  // copy public key to temporary buffer
	memcpy(public_key, node->public_key, sizeof(public_key));

	if (msg->has_ecdsa_curve_name) {
		const ecdsa_curve *curve = get_curve_by_name(msg->ecdsa_curve_name);
		if (curve) {
			// correct public key (since fsm_getDerivedNode uses secp256k1 curve)
			ecdsa_get_public_key33(curve, node->private_key, public_key);
		}
	}

	bool sign_ssh = msg->identity.has_proto && (strcmp(msg->identity.proto, "ssh") == 0);

	int result = 0;
	layoutProgressSwipe("Signing", 0);
	if (sign_ssh) { // SSH does not sign visual challenge
		result = sshMessageSign(msg->challenge_hidden.bytes, msg->challenge_hidden.size, node->private_key, resp->signature.bytes);
	} else {
		uint8_t digest[64];
		sha256_Raw(msg->challenge_hidden.bytes, msg->challenge_hidden.size, digest);
		sha256_Raw((const uint8_t *)msg->challenge_visual, strlen(msg->challenge_visual), digest + 32);
		result = cryptoMessageSign(digest, 64, node->private_key, resp->signature.bytes);
	}

	if (result == 0) {
		if (sign_ssh) {
			resp->has_address = false;
		} else {
			resp->has_address = true;
			uint8_t addr_raw[21];
			ecdsa_get_address_raw(node->public_key, 0x00, addr_raw); // hardcoded Bitcoin address type
			base58_encode_check(addr_raw, 21, resp->address, sizeof(resp->address));
		}
		resp->has_public_key = true;
		resp->public_key.size = 33;
		memcpy(resp->public_key.bytes, public_key, 33);
		resp->has_signature = true;
		resp->signature.size = 65;
		msg_write(MessageType_MessageType_SignedIdentity, resp);
	} else {
		fsm_sendFailure(FailureType_Failure_Other, "Error signing identity");
	}
	layoutHome();
}
Beispiel #10
0
void fsm_msgGetAddress(GetAddress *msg)
{
    RESP_INIT(Address);

    if (!storage_is_initialized()) 
    {
        fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized");
        return;
    }

    if(!pin_protect_cached())
    {
        go_home();
        return;
    }

    const CoinType *coin = fsm_getCoin(msg->coin_name);

    if(!coin) { return; }

    const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count);

    if(!node) { return; }

    if(msg->has_multisig)
    {

        if(cryptoMultisigPubkeyIndex(&(msg->multisig), node->public_key) < 0)
        {
            fsm_sendFailure(FailureType_Failure_Other,
                            "Pubkey not found in multisig script");
            go_home();
            return;
        }

        uint8_t buf[32];

        if(compile_script_multisig_hash(&(msg->multisig), buf) == 0)
        {
            fsm_sendFailure(FailureType_Failure_Other, "Invalid multisig script");
            go_home();
            return;
        }

        ripemd160(buf, 32, buf + 1);
        buf[0] = coin->address_type_p2sh; // multisig cointype
        base58_encode_check(buf, 21, resp->address, sizeof(resp->address));
    }
    else
    {
        ecdsa_get_address(node->public_key, coin->address_type, resp->address,
                          sizeof(resp->address));
    }

    if(msg->has_show_display && msg->show_display)
    {
        char desc[MEDIUM_STR_BUF] = "";

        if(msg->has_multisig)
        {
            const uint32_t m = msg->multisig.m;
            const uint32_t n = msg->multisig.pubkeys_count;

            /* snprintf: 22 + 10 (%lu) + 10 (%lu) + 1 (NULL) = 43 */
            snprintf(desc, MEDIUM_STR_BUF, "(Multi-Signature %lu of %lu)", (unsigned long)m,
                     (unsigned long)n);
        }

        if(!confirm_address(desc, resp->address))
        {
            fsm_sendFailure(FailureType_Failure_ActionCancelled, "Show address cancelled");
            go_home();
            return;
        }
    }

    msg_write(MessageType_MessageType_Address, resp);
    go_home();
}
Beispiel #11
0
void fsm_msgDecryptMessage(DecryptMessage *msg)
{

    if (!storage_is_initialized()) 
    {
        fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized");
        return;
    }

    if(!msg->has_nonce)
    {
        fsm_sendFailure(FailureType_Failure_SyntaxError, "No nonce provided");
        return;
    }

    if(!msg->has_message)
    {
        fsm_sendFailure(FailureType_Failure_SyntaxError, "No message provided");
        return;
    }

    if(!msg->has_hmac)
    {
        fsm_sendFailure(FailureType_Failure_SyntaxError, "No message hmac provided");
        return;
    }

    curve_point nonce_pubkey;

    if(msg->nonce.size != 33 ||
            ecdsa_read_pubkey(&secp256k1, msg->nonce.bytes, &nonce_pubkey) == 0)
    {
        fsm_sendFailure(FailureType_Failure_SyntaxError, "Invalid nonce provided");
        return;
    }

    if(!pin_protect_cached())
    {
        go_home();
        return;
    }

    const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count);

    if(!node) { return; }

    layout_simple_message("Decrypting Message...");

    RESP_INIT(DecryptedMessage);
    bool display_only = false;
    bool signing = false;
    uint8_t address_raw[21];

    if(cryptoMessageDecrypt(&nonce_pubkey, msg->message.bytes, msg->message.size,
                            msg->hmac.bytes, msg->hmac.size, node->private_key, resp->message.bytes,
                            &(resp->message.size), &display_only, &signing, address_raw) != 0)
    {
        fsm_sendFailure(FailureType_Failure_ActionCancelled,
                        "Error decrypting message");
        go_home();
        return;
    }

    if(signing)
    {
        base58_encode_check(address_raw, 21, resp->address, sizeof(resp->address));
    }

    if(!confirm_decrypt_msg((char *)resp->message.bytes,
                            signing ? resp->address : 0))
    {
        fsm_sendFailure(FailureType_Failure_ActionCancelled,
                        "Decrypt message cancelled");
        go_home();
        return;
    }

    if(display_only)
    {
        resp->has_address = false;
        resp->has_message = false;
        memset(resp->address, 0, sizeof(resp->address));
        memset(&(resp->message), 0, sizeof(resp->message));
    }
    else
    {
        resp->has_address = signing;
        resp->has_message = true;
    }

    msg_write(MessageType_MessageType_DecryptedMessage, resp);
    go_home();
}