Expected: When a single ClientKeyExchange packet from a client drops, the client should still be able to finish the DTLS handshake with a ClientKeyExchange resend.
Actual: The ClientKeyExchange resend(s) cause(s) the client hash verification to fail, leading to the following observable errors in debug mode:
Dropping non-verified Finished Handshake from <source>
and the following error looping on resend:
Dropping non-ClientHello (ClientKeyExchange) message from non-peer <source>
Cause: The issue was tracked to each SendClientKeyExchangeFlight changing the handshake hash because this.nextEpoch.VerificationStream.CalculateHash(handshakeHash); internally calls TransformFinalBlock each time despite the assumption that TransformFinalBlock is only ever called once.
Fix: Sha256Stream was updated with an internal flag to only finalize the hash a single time. A unit test was added that tests the single SendClientKeyExchangeFlight drop.
Expected: When a single ClientKeyExchange packet from a client drops, the client should still be able to finish the DTLS handshake with a ClientKeyExchange resend.
Actual: The ClientKeyExchange resend(s) cause(s) the client hash verification to fail, leading to the following observable errors in debug mode:
Dropping non-verified Finished Handshake from <source>
and the following error looping on resend:Dropping non-ClientHello (ClientKeyExchange) message from non-peer <source>
Cause: The issue was tracked to each SendClientKeyExchangeFlight changing the handshake hash because
this.nextEpoch.VerificationStream.CalculateHash(handshakeHash);
internally callsTransformFinalBlock
each time despite the assumption thatTransformFinalBlock
is only ever called once.Fix: Sha256Stream was updated with an internal flag to only finalize the hash a single time. A unit test was added that tests the single SendClientKeyExchangeFlight drop.