Skip to content

Commit 7e3db6a

Browse files
committed
Expose BIP324CipherSuite AAD via transport classes
1 parent 19abc1b commit 7e3db6a

5 files changed

+35
-16
lines changed

src/net.cpp

+11-5
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,7 @@ bool CNode::ReceiveMsgBytes(Span<const uint8_t> msg_bytes, bool& complete)
673673
// decompose a transport agnostic CNetMessage from the deserializer
674674
bool reject_message{false};
675675
bool disconnect{false};
676-
CNetMessage msg = m_deserializer->GetMessage(time, reject_message, disconnect);
676+
CNetMessage msg = m_deserializer->GetMessage(time, reject_message, disconnect, {});
677677

678678
if (disconnect) {
679679
// v2 p2p incorrect MAC tag. Disconnect from peer.
@@ -771,7 +771,10 @@ const uint256& V1TransportDeserializer::GetMessageHash() const
771771
return data_hash;
772772
}
773773

774-
CNetMessage V1TransportDeserializer::GetMessage(const std::chrono::microseconds time, bool& reject_message, bool& disconnect)
774+
CNetMessage V1TransportDeserializer::GetMessage(const std::chrono::microseconds time,
775+
bool& reject_message,
776+
bool& disconnect,
777+
Span<const std::byte> aad)
775778
{
776779
// Initialize out parameter
777780
reject_message = false;
@@ -876,7 +879,10 @@ int V2TransportDeserializer::readData(Span<const uint8_t> pkt_bytes)
876879
return copy_bytes;
877880
}
878881

879-
CNetMessage V2TransportDeserializer::GetMessage(const std::chrono::microseconds time, bool& reject_message, bool& disconnect)
882+
CNetMessage V2TransportDeserializer::GetMessage(const std::chrono::microseconds time,
883+
bool& reject_message,
884+
bool& disconnect,
885+
Span<const std::byte> aad)
880886
{
881887
const size_t min_contents_size = 1; // BIP324 1-byte message type id is the minimum contents
882888

@@ -895,7 +901,7 @@ CNetMessage V2TransportDeserializer::GetMessage(const std::chrono::microseconds
895901

896902
BIP324HeaderFlags flags;
897903
size_t msg_type_size = 1; // at least one byte needed for message type
898-
if (m_cipher_suite->Crypt({},
904+
if (m_cipher_suite->Crypt(aad,
899905
Span{reinterpret_cast<const std::byte*>(vRecv.data() + BIP324_LENGTH_FIELD_LEN), BIP324_HEADER_LEN + m_contents_size + RFC8439_EXPANSION},
900906
Span{reinterpret_cast<std::byte*>(vRecv.data()), m_contents_size}, flags, false)) {
901907
// MAC check was successful
@@ -983,7 +989,7 @@ bool V2TransportSerializer::prepareForTransport(CSerializedNetMsg& msg, std::vec
983989

984990
BIP324HeaderFlags flags{BIP324_NONE};
985991
// encrypt the payload, this should always succeed (controlled buffers, don't check the MAC during encrypting)
986-
auto success = m_cipher_suite->Crypt({},
992+
auto success = m_cipher_suite->Crypt(msg.aad,
987993
Span{reinterpret_cast<const std::byte*>(msg.data.data()), contents_size},
988994
Span{reinterpret_cast<std::byte*>(msg.data.data()), encrypted_pkt_size},
989995
flags, true);

src/net.h

+13-3
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ struct CSerializedNetMsg {
125125
}
126126

127127
std::vector<unsigned char> data;
128+
std::vector<std::byte> aad; // associated authenticated data for encrypted BIP324 (v2) transport
128129
std::string m_type;
129130
};
130131

@@ -260,7 +261,10 @@ class TransportDeserializer {
260261
/** read and deserialize data, advances msg_bytes data pointer */
261262
virtual int Read(Span<const uint8_t>& msg_bytes) = 0;
262263
// decomposes a message from the context
263-
virtual CNetMessage GetMessage(std::chrono::microseconds time, bool& reject_message, bool& disconnect) = 0;
264+
virtual CNetMessage GetMessage(std::chrono::microseconds time,
265+
bool& reject_message,
266+
bool& disconnect,
267+
Span<const std::byte> aad) = 0;
264268
virtual ~TransportDeserializer() {}
265269
};
266270

@@ -324,7 +328,10 @@ class V1TransportDeserializer final : public TransportDeserializer
324328
}
325329
return ret;
326330
}
327-
CNetMessage GetMessage(std::chrono::microseconds time, bool& reject_message, bool& disconnect) override;
331+
CNetMessage GetMessage(std::chrono::microseconds time,
332+
bool& reject_message,
333+
bool& disconnect,
334+
Span<const std::byte> aad) override;
328335
};
329336

330337
/** V2TransportDeserializer is a transport deserializer after BIP324 */
@@ -383,7 +390,10 @@ class V2TransportDeserializer final : public TransportDeserializer
383390
}
384391
return ret;
385392
}
386-
CNetMessage GetMessage(const std::chrono::microseconds time, bool& reject_message, bool& disconnect) override;
393+
CNetMessage GetMessage(const std::chrono::microseconds time,
394+
bool& reject_message,
395+
bool& disconnect,
396+
Span<const std::byte> aad) override;
387397
};
388398

389399
/** The TransportSerializer prepares messages for the network transport

src/test/fuzz/p2p_transport_serialization.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ FUZZ_TARGET_INIT(p2p_transport_serialization, initialize_p2p_transport_serializa
7070
const std::chrono::microseconds m_time{std::numeric_limits<int64_t>::max()};
7171
bool reject_message{false};
7272
bool disconnect{false};
73-
CNetMessage msg = deserializer.GetMessage(m_time, reject_message, disconnect);
73+
CNetMessage msg = deserializer.GetMessage(m_time, reject_message, disconnect, {});
7474
assert(msg.m_type.size() <= CMessageHeader::COMMAND_SIZE);
7575
assert(msg.m_raw_message_size <= mutable_msg_bytes.size());
7676
assert(msg.m_raw_message_size == CMessageHeader::HEADER_SIZE + msg.m_message_size);

src/test/fuzz/p2p_v2_transport_serialization.cpp

+9-6
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ FUZZ_TARGET(p2p_v2_transport_serialization)
4343

4444
// There is no sense in providing a mac assist if the length is incorrect.
4545
bool mac_assist = length_assist && fdp.ConsumeBool();
46+
auto aad = fdp.ConsumeBytes<std::byte>(fdp.ConsumeIntegralInRange(0, 1024));
4647
auto encrypted_packet = fdp.ConsumeRemainingBytes<uint8_t>();
4748
bool is_decoy_packet{false};
4849

@@ -56,17 +57,18 @@ FUZZ_TARGET(p2p_v2_transport_serialization)
5657

5758
if (mac_assist) {
5859
std::array<std::byte, RFC8439_EXPANSION> tag;
59-
ComputeRFC8439Tag(GetPoly1305Key(c20), {},
60+
ComputeRFC8439Tag(GetPoly1305Key(c20), aad,
6061
{reinterpret_cast<std::byte*>(encrypted_packet.data()) + BIP324_LENGTH_FIELD_LEN,
61-
encrypted_packet.size() - BIP324_LENGTH_FIELD_LEN - RFC8439_EXPANSION}, tag);
62+
encrypted_packet.size() - BIP324_LENGTH_FIELD_LEN - RFC8439_EXPANSION},
63+
tag);
6264
memcpy(encrypted_packet.data() + encrypted_packet.size() - RFC8439_EXPANSION, tag.data(), RFC8439_EXPANSION);
6365

6466
std::vector<std::byte> dec_header_and_contents(
65-
encrypted_packet.size() - BIP324_LENGTH_FIELD_LEN - RFC8439_EXPANSION);
66-
RFC8439Decrypt({}, key_P, nonce,
67+
encrypted_packet.size() - BIP324_LENGTH_FIELD_LEN - RFC8439_EXPANSION);
68+
RFC8439Decrypt(aad, key_P, nonce,
6769
{reinterpret_cast<std::byte*>(encrypted_packet.data() + BIP324_LENGTH_FIELD_LEN),
6870
encrypted_packet.size() - BIP324_LENGTH_FIELD_LEN},
69-
dec_header_and_contents);
71+
dec_header_and_contents);
7072
if (BIP324HeaderFlags((uint8_t)dec_header_and_contents.at(0) & BIP324_IGNORE) != BIP324_NONE) {
7173
is_decoy_packet = true;
7274
}
@@ -83,7 +85,7 @@ FUZZ_TARGET(p2p_v2_transport_serialization)
8385
const std::chrono::microseconds m_time{std::numeric_limits<int64_t>::max()};
8486
bool reject_message{true};
8587
bool disconnect{true};
86-
CNetMessage result{deserializer.GetMessage(m_time, reject_message, disconnect)};
88+
CNetMessage result{deserializer.GetMessage(m_time, reject_message, disconnect, aad)};
8789

8890
if (mac_assist) {
8991
assert(!disconnect);
@@ -104,6 +106,7 @@ FUZZ_TARGET(p2p_v2_transport_serialization)
104106

105107
std::vector<unsigned char> header;
106108
auto msg = CNetMsgMaker{result.m_recv.GetVersion()}.Make(result.m_type, MakeUCharSpan(result.m_recv));
109+
msg.aad = aad;
107110
// if decryption succeeds, encryption must succeed
108111
assert(serializer.prepareForTransport(msg, header));
109112
}

src/test/net_tests.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,7 @@ void message_serialize_deserialize_test(bool v2, const std::vector<CSerializedNe
955955

956956
bool reject_message{true};
957957
bool disconnect{true};
958-
CNetMessage result{deserializer->GetMessage(GetTime<std::chrono::microseconds>(), reject_message, disconnect)};
958+
CNetMessage result{deserializer->GetMessage(GetTime<std::chrono::microseconds>(), reject_message, disconnect, {})};
959959
BOOST_CHECK(!reject_message);
960960
BOOST_CHECK(!disconnect);
961961
BOOST_CHECK_EQUAL(result.m_type, msg_orig.m_type);

0 commit comments

Comments
 (0)