-
Notifications
You must be signed in to change notification settings - Fork 36.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BIP324: Add encrypted p2p transport {de}serializer #23233
Conversation
988a1af
to
f81e8ad
Compare
Rebased and lint errors fixed. Ready for review. |
uint32_t len = aead.DecryptLength(in.data()); | ||
len = 0; // addressing the [[nodiscard]] and otherwise unused variable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uint32_t len = aead.DecryptLength(in.data()); | |
len = 0; // addressing the [[nodiscard]] and otherwise unused variable | |
(void)aead.DecryptLength(in.data()); |
Does this not work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That does indeed work. Thank you.
I've updated the commit in PR #20962 (where it originally belongs) and also here(this PR is based off that one).
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
Addressed #23233 (comment) - ready for further review. |
Rebased. Ready for further review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK ab5b49d. This PR nicely implements the v2 transport serialisation and deserialisation process.
- 4be7638
- To introduce short-IDs,
allNetMessageTypes[]
is represented as a map and functions to convert short-ID to a message and vice versa are added. Verified that changes don’t need to be made to other files due to this commit.
- To introduce short-IDs,
- a53a06c
- The v2TransportDeserializer contains:
readHeader()
: copies the header frommsg_bytes
to location invRecv[]
which is addressed bym_hdr_pos
. After the entire header is read, it switches to read message data mode(m_in_data
= true).readData()
: copies the data frommsg_bytes
to location invRecv[]
which is addressed byCHACHA20_POLY1305_AEAD_AAD_LEN + m_data_pos
.vRecv[]
is resized to at max 256 KiB forward if there’s no space to holdmsg_bytes
.GetMessage()
: performs decryption ofvRecv[]
and chops off the AAD and MAC tag if successful decryption occurs. It reads the first byte of the payload insize_or_shortid
. Ifsize_or_shortid
is a number between 1 and 12, then it’s a string command and the nextsize_or_shortid
bytes is read intocommand_name
. Ifsize_or_shortid
is larger than 12, then it’s a Message-Type-ID and if it's string mapping is found, it's stored incommand_name
. Otherwise thesize_or_shortid
is appended with the prefix ‘unknown’ and stored incommand_name
.CNetMessage msg
is constructed and returned.
- The v2TransportSerializer contains:
prepareForTransport()
: prepares theCSerializedNetMsg msg
for serialisation.serialized_command_size
is used to store the size of short id (1 byte) or the size of message command string if short id isn’t assigned.packet_length
contains the length of the message type id and payload which is stored in a LE representation inserialized_header
. The short id/ command string is also appended to it.serialized_header
is then inserted into the beginning ofmsg
buffer. Encryption is performed onmsg
and returns true when successful.
- The v2TransportDeserializer contains:
src/net.cpp
Outdated
} | ||
|
||
// we got the AAD bytes at this point (3 bytes encrypted packet length) | ||
// we keep the sequence numbers unchanged at this point. Once the message is authenticated and decrypted, we increase the sequence numbers (or the aad_pos) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// we keep the sequence numbers unchanged at this point. Once the message is authenticated and decrypted, we increase the sequence numbers (or the aad_pos) |
This comment can be removed since it's related to the AEAD cipher suite implementation and doesn't play a role here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good find. Removed.
src/net.cpp
Outdated
m_message_size = m_aead->DecryptLength((const uint8_t*)vRecv.data()); | ||
|
||
// reject messages larger than MAX_SIZE | ||
if (m_message_size > MAX_SIZE) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will need to be updated to be consistent with the BIP since MAX_SIZE is 2^25 bytes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the catch. Fixed.
src/net.cpp
Outdated
return copy_bytes; | ||
} | ||
|
||
std::optional<CNetMessage> V2TransportDeserializer::GetMessage(std::chrono::microseconds time, uint32_t& out_err_raw_size) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function can be modified to keep it's format consistent with the v1 GetMessage since #22735 got merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Rebased with master.
src/net.cpp
Outdated
// encode as varstr, max 12 chars | ||
serialized_command_size = ::GetSerializeSize(msg.m_type, PROTOCOL_VERSION); | ||
} | ||
// prepare the packet length that will later be encrypted and part of the MAC (AD) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// prepare the packet length that will later be encrypted and part of the MAC (AD) | |
// prepare the packet length that will later be encrypted and part of the MAC (AAD) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/net.cpp
Outdated
|
||
// insert header directly into the CSerializedNetMsg data buffer (insert at begin) | ||
// TODO: if we refactor the ChaCha20Poly1350 crypt function to allow separate buffers for | ||
// the AD, payload and MAC, we could avoid a insert and thus a potential reallocation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// the AD, payload and MAC, we could avoid a insert and thus a potential reallocation | |
// the AAD, payload and MAC, we could avoid a insert and thus a potential reallocation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/net.cpp
Outdated
} | ||
|
||
// insert header directly into the CSerializedNetMsg data buffer (insert at begin) | ||
// TODO: if we refactor the ChaCha20Poly1350 crypt function to allow separate buffers for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// TODO: if we refactor the ChaCha20Poly1350 crypt function to allow separate buffers for | |
// TODO: if we refactor the ChaCha20Poly1305 crypt function to allow separate buffers for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/net.cpp
Outdated
|
||
std::optional<CNetMessage> V2TransportDeserializer::GetMessage(std::chrono::microseconds time, uint32_t& out_err_raw_size) | ||
{ | ||
// In v2, vRecv contains the encrypted payload plus the MAC tag (1+bytes serialized message command + ? bytes message payload + 16 byte mac tag) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// In v2, vRecv contains the encrypted payload plus the MAC tag (1+bytes serialized message command + ? bytes message payload + 16 byte mac tag) | |
// In v2, vRecv contains the AAD, encrypted payload plus the MAC tag (3 byte AAD + 1+bytes serialized message command + ? bytes message payload + 16 byte mac tag) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/test/net_tests.cpp
Outdated
// second: read the encrypted payload (if required) | ||
Span<const uint8_t> span_msg(msg.data.data(), msg.data.size()); | ||
if (msg.data.size() > 0) read_bytes += deserializer->Read(span_msg); | ||
if (msg.data.size() > read_bytes && msg.data.size() - read_bytes > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (msg.data.size() > read_bytes && msg.data.size() - read_bytes > 0) { | |
if (msg.data.size() > read_bytes) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, that was quite silly. Thanks for reviewing closely. Done.
src/test/net_tests.cpp
Outdated
uint32_t out_err_raw_size{0}; | ||
std::optional<CNetMessage> result{deserializer->GetMessage(GetTime<std::chrono::microseconds>(), out_err_raw_size)}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be updated to keep it consistent with 22735's change.
uint32_t out_err_raw_size{0}; | |
std::optional<CNetMessage> result{deserializer->GetMessage(GetTime<std::chrono::microseconds>(), out_err_raw_size)}; | |
bool reject_message{false}; | |
CNetMessage result{deserializer->GetMessage(GetTime<std::chrono::microseconds>(), reject_message)}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
uint32_t out_err_raw_size{0}; | ||
std::optional<CNetMessage> result{deserializer.GetMessage(m_time, out_err_raw_size)}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uint32_t out_err_raw_size{0}; | |
std::optional<CNetMessage> result{deserializer.GetMessage(m_time, out_err_raw_size)}; | |
bool reject_message{false}; | |
CNetMessage result{deserializer.GetMessage(m_time, reject_message)}; |
Here also.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Rebased to bring in changes from #22735, and addressed comments from @stratospher (Thank you!). Ready for further review. |
Pushed changes to enforce connection termination upon finding an invalid mac tag. Ready for further review. |
Rebased. Brought in upstream changes. |
Rebased. |
Latest push:
|
Co-authored-by: Jonas Schnelli <dev@jonasschnelli.ch>
Co-authored-by: Jonas Schnelli <dev@jonasschnelli.ch>
Latest push:
|
Closing for now. This will be picked up again later. BIP324 review attention should be directed towards #27479 and bitcoin-core/secp256k1#1129. |
Revives #18242. Depends on #25361 (please review that first, the last 4 commits are to be reviewed here).
This PR adds a p2p message transport {de}serializer for encrypted packets leveraging the BIP324 specification.
The dependency tree for BIP324 PRs is here.