From 780afd84a2fbc10316c1c57329b8ecb3c2933f01 Mon Sep 17 00:00:00 2001 From: SChernykh Date: Tue, 31 Aug 2021 17:23:20 +0200 Subject: [PATCH] Added checks for tx keys --- src/block_template.cpp | 4 +++- src/crypto.cpp | 21 +++++++++++++++++---- src/crypto.h | 1 + src/p2p_server.cpp | 2 +- src/pool_block.cpp | 1 + src/pool_block_parser.inl | 9 ++++++++- src/side_chain.cpp | 13 +++++++++++-- src/wallet.cpp | 27 ++++++++++++++++++++++----- src/wallet.h | 4 ++-- 9 files changed, 66 insertions(+), 16 deletions(-) diff --git a/src/block_template.cpp b/src/block_template.cpp index e6ec746..c21e65a 100644 --- a/src/block_template.cpp +++ b/src/block_template.cpp @@ -628,7 +628,9 @@ bool BlockTemplate::create_miner_tx(const MinerData& data, const std::vectorget_eph_public_key(m_txkeySec, i, eph_public_key); + if (!shares[i].m_wallet->get_eph_public_key(m_txkeySec, i, eph_public_key)) { + LOGERR(1, "get_eph_public_key failed at index " << i); + } m_minerTx.insert(m_minerTx.end(), eph_public_key.h, eph_public_key.h + HASH_SIZE); m_poolBlockTemplate->m_outputs.emplace_back(m_rewards[i], eph_public_key); } diff --git a/src/crypto.cpp b/src/crypto.cpp index 41ae7af..d4b7e54 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -84,10 +84,7 @@ void generate_keys(hash& pub, hash& sec) static constexpr uint8_t limit[32] = { 0xe3, 0x6a, 0x67, 0x72, 0x8b, 0xce, 0x13, 0x29, 0x8f, 0x30, 0x82, 0x8c, 0x0b, 0xa4, 0x10, 0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0 }; do { - randomBytes(sec.h); - if (!less32(sec.h, limit)) { - continue; - } + do { randomBytes(sec.h); } while (!less32(sec.h, limit)); sc_reduce32(sec.h); } while (!sc_isnonzero(sec.h)); @@ -96,6 +93,22 @@ void generate_keys(hash& pub, hash& sec) ge_p3_tobytes(pub.h, &point); } +bool check_keys(const hash& pub, const hash& sec) +{ + // From ge_scalarmult_base's comment: "preconditions a[31] <= 127" + if (sec.h[HASH_SIZE - 1] > 127) { + return false; + } + + ge_p3 point; + ge_scalarmult_base(&point, sec.h); + + hash pub_check; + ge_p3_tobytes(pub_check.h, &point); + + return pub == pub_check; +} + bool generate_key_derivation(const hash& key1, const hash& key2, hash& derivation) { ge_p3 point; diff --git a/src/crypto.h b/src/crypto.h index bbe404a..00bef64 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -20,6 +20,7 @@ namespace p2pool { void generate_keys(hash& pub, hash& sec); +bool check_keys(const hash& pub, const hash& sec); bool generate_key_derivation(const hash& key1, const hash& key2, hash& derivation); bool derive_public_key(const hash& derivation, size_t output_index, const hash& base, hash& derived_key); diff --git a/src/p2p_server.cpp b/src/p2p_server.cpp index 0d45805..e88bc36 100644 --- a/src/p2p_server.cpp +++ b/src/p2p_server.cpp @@ -721,7 +721,7 @@ bool P2PServer::P2PClient::on_connect() // server->m_clientsListLock is already locked here for (P2PClient* client = static_cast(server->m_connectedClientsList->m_next); client != server->m_connectedClientsList; client = static_cast(client->m_next)) { if ((client != this) && (client->m_addr == m_addr)) { - LOGWARN(5, "peer " << static_cast(m_addrString) << " is already connected as " << static_cast(client->m_addrString)); + LOGINFO(5, "peer " << static_cast(m_addrString) << " is already connected as " << static_cast(client->m_addrString)); return false; } } diff --git a/src/pool_block.cpp b/src/pool_block.cpp index 2cdf159..0331f7f 100644 --- a/src/pool_block.cpp +++ b/src/pool_block.cpp @@ -20,6 +20,7 @@ #include "keccak.h" #include "side_chain.h" #include "pow_hash.h" +#include "crypto.h" static constexpr char log_category_prefix[] = "PoolBlock "; diff --git a/src/pool_block_parser.inl b/src/pool_block_parser.inl index 53bebd0..bdfaf7e 100644 --- a/src/pool_block_parser.inl +++ b/src/pool_block_parser.inl @@ -233,9 +233,16 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, SideChain& sidechai hash view_pub_key; READ_BUF(spend_pub_key.h, HASH_SIZE); READ_BUF(view_pub_key.h, HASH_SIZE); - m_minerWallet.assign(spend_pub_key, view_pub_key); + if (!m_minerWallet.assign(spend_pub_key, view_pub_key, sidechain.network_type())) { + return __LINE__; + } READ_BUF(m_txkeySec.h, HASH_SIZE); + + if (!check_keys(m_txkeyPub, m_txkeySec)) { + return __LINE__; + } + READ_BUF(m_parent.h, HASH_SIZE); uint64_t num_uncles; diff --git a/src/side_chain.cpp b/src/side_chain.cpp index cb503df..dd8fea3 100644 --- a/src/side_chain.cpp +++ b/src/side_chain.cpp @@ -550,7 +550,9 @@ bool SideChain::get_outputs_blob(PoolBlock* block, uint64_t total_reward, std::v blob.emplace_back(TXOUT_TO_KEY); - shares[i].m_wallet->get_eph_public_key(block->m_txkeySec, i, eph_public_key); + if (!shares[i].m_wallet->get_eph_public_key(block->m_txkeySec, i, eph_public_key)) { + LOGWARN(6, "get_eph_public_key failed at index " << i); + } blob.insert(blob.end(), eph_public_key.h, eph_public_key.h + HASH_SIZE); block->m_outputs.emplace_back(rewards[i], eph_public_key); @@ -1146,7 +1148,14 @@ void SideChain::verify(PoolBlock* block) } hash eph_public_key; - shares[i].m_wallet->get_eph_public_key(block->m_txkeySec, i, eph_public_key); + if (!shares[i].m_wallet->get_eph_public_key(block->m_txkeySec, i, eph_public_key)) { + LOGWARN(3, "block at height = " << block->m_sidechainHeight << + ", id = " << block->m_sidechainId << + ", mainchain height = " << block->m_txinGenHeight << + " failed to eph_public_key at index " << i); + block->m_invalid = true; + return; + } if (eph_public_key != block->m_outputs[i].m_ephPublicKey) { LOGWARN(3, "block at height = " << block->m_sidechainHeight << diff --git a/src/wallet.cpp b/src/wallet.cpp index 41b61d3..8e47b9c 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -24,6 +24,10 @@ #include "crypto.h" #include +extern "C" { +#include "crypto-ops.h" +} + static constexpr char log_category_prefix[] = "Wallet "; namespace { @@ -189,8 +193,13 @@ bool Wallet::decode(const char* address) return valid(); } -void Wallet::assign(const hash& spend_pub_key, const hash& view_pub_key) +bool Wallet::assign(const hash& spend_pub_key, const hash& view_pub_key, NetworkType type) { + ge_p3 point; + if ((ge_frombytes_vartime(&point, spend_pub_key.h) != 0) || (ge_frombytes_vartime(&point, view_pub_key.h) != 0)) { + return false; + } + MutexLock lock(m_lock); m_prefix = 0; @@ -198,15 +207,17 @@ void Wallet::assign(const hash& spend_pub_key, const hash& view_pub_key) m_viewPublicKey = view_pub_key; m_checksum = 0; - m_type = NetworkType::Mainnet; + m_type = type; m_txkeySec = {}; m_outputIndex = std::numeric_limits::max(); m_derivation = {}; m_ephPublicKey = {}; + + return true; } -void Wallet::get_eph_public_key(const hash& txkey_sec, size_t output_index, hash& eph_public_key) +bool Wallet::get_eph_public_key(const hash& txkey_sec, size_t output_index, hash& eph_public_key) { MutexLock lock(m_lock); @@ -217,7 +228,9 @@ void Wallet::get_eph_public_key(const hash& txkey_sec, size_t output_index, hash derivation = m_derivation; } else { - generate_key_derivation(m_viewPublicKey, txkey_sec, derivation); + if (!generate_key_derivation(m_viewPublicKey, txkey_sec, derivation)) { + return false; + } m_derivation = derivation; m_txkeySec = txkey_sec; derivation_changed = true; @@ -227,10 +240,14 @@ void Wallet::get_eph_public_key(const hash& txkey_sec, size_t output_index, hash eph_public_key = m_ephPublicKey; } else { - derive_public_key(derivation, output_index, m_spendPublicKey, eph_public_key); + if (!derive_public_key(derivation, output_index, m_spendPublicKey, eph_public_key)) { + return false; + } m_outputIndex = output_index; m_ephPublicKey = eph_public_key; } + + return true; } } // namespace p2pool diff --git a/src/wallet.h b/src/wallet.h index 18ad3af..856e860 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -34,12 +34,12 @@ public: FORCEINLINE NetworkType type() const { return m_type; } bool decode(const char* address); - void assign(const hash& spend_pub_key, const hash& view_pub_key); + bool assign(const hash& spend_pub_key, const hash& view_pub_key, NetworkType type); FORCEINLINE const hash& spend_public_key() const { return m_spendPublicKey; } FORCEINLINE const hash& view_public_key() const { return m_viewPublicKey; } - void get_eph_public_key(const hash& txkey_sec, size_t output_index, hash& eph_public_key); + bool get_eph_public_key(const hash& txkey_sec, size_t output_index, hash& eph_public_key); FORCEINLINE bool operator<(const Wallet& w) const { return m_spendPublicKey < w.m_spendPublicKey; } FORCEINLINE bool operator==(const Wallet& w) const { return m_spendPublicKey == w.m_spendPublicKey; }