Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This adds support for receiving (and ignoring) decoy packets in the handshake before the final version packet is sent.
Without this patch, our handshake fails if any decoy packets are sent in the handshake because it currently assumes that only a version packet is sent. This hasn't bitten us yet because Core doesn't send decoys, but it is definitely not meeting the spec. The spec has the specifics on the decoy packets.
They can be sent immediately after the garbage terminator in the handshake ("here" in the above quote is right after the materials are generated, before the version packet). The only requirement is that the first packet sent, which can be a decoy or the version packet, has the garbage authentication in the AAD. Other than that there are actually very little requirements for the decoy packets which makes them a bit of burden.
Closes #28
Core Support
As of v28.0rc2, Core does not support sending decoys in the handshake. In V2Transport::ProcessReceivedKeyBytes, the version packet is sent right after the garbage terminator. This has been Core's behavior since BIP324 was implemented in v26. This begs the question, should this complexity of decoy packets in the handshake even exist?
Handshake Tweaks
The
Handshake
is attempting to do a lot under the hood for the caller before handing off responsibilities with thePacketHandler
. ThePacketHandler
is able to pretty easily expose the allocation responsibilities to the caller, they either need the 3 bytes for length or the length of the message. In theHandshake
however there might be a variable amount of decoy packets right in the middle. This flexibility is tough to handle without allocation.Attempting to find a middle ground between robustness and usability, I initially went with a new const
MAX_HANDSHAKE_PACKET_BYTES
to keep the whole process sans-io. The trade off is that a large decoy package will blow the whole thing up. Ideally, decoy messages look like real communication so I don't believe there is much incentive to send super large packets, but this still felt pretty fragile so went back to the drawing board.I added a new error variant to the module,
BufferTooSmall
, which is returned by the handshake function if it is unable to decrypt the decoy and version packets. Aauthenticate_garbage_and_version_with_alloc
wrapper function which requiresalloc
also shows a nice pattern for callers to expand their buffers when necessary.Error Variants
I added the
BufferTooSmall
variant and noticed we had been abusingMessageLengthTooSmall
in a few spots. We may want to consider renaming that one for its remaining use cases.Next Up
Plan is to add decoy sending support, along with more unit tests, in a follow up patch. The sending functions will make it way easier to add tests. All existing tests are covering the pre-decoy paths which is all we support at the moment so feel pretty good about this one for now.