Skip to content

Commit

Permalink
net: Simplify v2 recv logic by decoupling AAD from state machine
Browse files Browse the repository at this point in the history
  • Loading branch information
real-or-random committed Sep 27, 2023
1 parent a90bde5 commit ac96c38
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 24 deletions.
38 changes: 16 additions & 22 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1191,8 +1191,8 @@ bool V2Transport::ProcessReceivedGarbageBytes() noexcept
if (m_recv_buffer.size() >= BIP324Cipher::GARBAGE_TERMINATOR_LEN) {
if (MakeByteSpan(m_recv_buffer).last(BIP324Cipher::GARBAGE_TERMINATOR_LEN) == m_cipher.GetReceiveGarbageTerminator()) {
// Garbage terminator received. Store garbage to authenticate it as AAD later.
m_recv_garbage = std::move(m_recv_buffer);
m_recv_garbage.resize(m_recv_garbage.size() - BIP324Cipher::GARBAGE_TERMINATOR_LEN);
m_recv_aad = std::move(m_recv_buffer);
m_recv_aad.resize(m_recv_aad.size() - BIP324Cipher::GARBAGE_TERMINATOR_LEN);
m_recv_buffer.clear();
SetReceiveState(RecvState::VERSION);
} else if (m_recv_buffer.size() == MAX_GARBAGE_LEN + BIP324Cipher::GARBAGE_TERMINATOR_LEN) {
Expand Down Expand Up @@ -1236,43 +1236,37 @@ bool V2Transport::ProcessReceivedPacketBytes() noexcept
// as GetMaxBytesToProcess only allows up to LENGTH_LEN into the buffer before that point.
m_recv_decode_buffer.resize(m_recv_len);
bool ignore{false};
Span<const std::byte> aad;
if (m_recv_state == RecvState::VERSION) aad = MakeByteSpan(m_recv_garbage);
bool ret = m_cipher.Decrypt(
/*input=*/MakeByteSpan(m_recv_buffer).subspan(BIP324Cipher::LENGTH_LEN),
/*aad=*/aad,
/*aad=*/MakeByteSpan(m_recv_aad),
/*ignore=*/ignore,
/*contents=*/MakeWritableByteSpan(m_recv_decode_buffer));
if (!ret) {
LogPrint(BCLog::NET, "V2 transport error: packet decryption failure (%u bytes), peer=%d\n", m_recv_len, m_nodeid);
return false;
}
// We have decrypted a valid packet with the AAD we expected, so clear the expected AAD.
ClearShrink(m_recv_aad);
// Feed the last 4 bytes of the Poly1305 authentication tag (and its timing) into our RNG.
RandAddEvent(ReadLE32(m_recv_buffer.data() + m_recv_buffer.size() - 4));

// At this point we have a valid packet decrypted into m_recv_decode_buffer. Depending on
// the current state, decide what to do with it.
switch (m_recv_state) {
case RecvState::VERSION:
if (!ignore) {
// At this point we have a valid packet decrypted into m_recv_decode_buffer. If it's not a
// decoy, which we simply ignore, use the current state to decide what to do with it.
if (!ignore) {
switch (m_recv_state) {
case RecvState::VERSION:
// Version message received; transition to application phase. The contents is
// ignored, but can be used for future extensions.
SetReceiveState(RecvState::APP);
}
// We have decrypted one valid packet (which may or may not have been a decoy) with the
// received garbage as AAD. We no longer need the received garbage and further packets
// are expected to use the empty string as AAD.
ClearShrink(m_recv_garbage);
break;
case RecvState::APP:
if (!ignore) {
break;
case RecvState::APP:
// Application message decrypted correctly. It can be extracted using GetMessage().
SetReceiveState(RecvState::APP_READY);
break;
default:
// Any other state is invalid (this function should not have been called).
Assume(false);
}
break;
default:
// Any other state is invalid (this function should not have been called).
Assume(false);
}
// Wipe the receive buffer where the next packet will be received into.
ClearShrink(m_recv_buffer);
Expand Down
4 changes: 2 additions & 2 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -578,8 +578,8 @@ class V2Transport final : public Transport
uint32_t m_recv_len GUARDED_BY(m_recv_mutex) {0};
/** Receive buffer; meaning is determined by m_recv_state. */
std::vector<uint8_t> m_recv_buffer GUARDED_BY(m_recv_mutex);
/** During VERSION, the garbage received during GARB_GARBTERM. */
std::vector<uint8_t> m_recv_garbage GUARDED_BY(m_recv_mutex);
/** AAD expected in next received packet (currently used only for garbage). */
std::vector<uint8_t> m_recv_aad GUARDED_BY(m_recv_mutex);
/** Buffer to put decrypted contents in, for converting to CNetMessage. */
std::vector<uint8_t> m_recv_decode_buffer GUARDED_BY(m_recv_mutex);
/** Deserialization type. */
Expand Down

0 comments on commit ac96c38

Please sign in to comment.