|
|
|
@ -1190,8 +1190,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) {
|
|
|
|
@ -1235,43 +1235,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);
|
|
|
|
|