Skip to content

Reinitialize server MAC HashAlgorithm between packets to prevent spurious MAC errors - #1834

Draft
WojciechNagorski with Copilot wants to merge 2 commits into
developfrom
copilot/fix-mac-error-cryptographicexception
Draft

Reinitialize server MAC HashAlgorithm between packets to prevent spurious MAC errors#1834
WojciechNagorski with Copilot wants to merge 2 commits into
developfrom
copilot/fix-mac-error-cryptographicexception

Conversation

Copilot AI commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Since 2026.0.0, Session.ReceiveMessage verifies the server MAC by reusing a single _serverMac HashAlgorithm instance across the whole session via TransformBlock/TransformFinalBlock, without ever calling Initialize() between packets. This violates HashAlgorithm's reuse contract. On certain older .NET Framework mscorlib.dll builds (pre-HMAC-rework, CAPI-backed implementations), the inner hash state isn't reset after TransformFinalBlock, so the second and subsequent MAC-protected packets fail — silently producing a wrong hash for hmac-sha2-* (SshConnectionException: MAC error) or throwing CryptographicException for hmac-sha1.

Fix

  • In both the ETM and non-ETM MAC verification branches of Session.ReceiveMessage, call _serverMac.Initialize() right after computing/comparing the MAC and before evaluating whether to throw, so the instance is always ready for the next packet.
  • Applied unconditionally, not gated to .NET Framework, since this addresses an actual HashAlgorithm reuse contract violation rather than a platform-specific quirk.
_ = _serverMac.TransformFinalBlock(Array.Empty<byte>(), 0, 0);

var macIsValid = CryptoAbstraction.FixedTimeEquals(_serverMac.Hash, ...);

// Not all HashAlgorithm implementations reset their internal state after
// TransformFinalBlock(), so we need to explicitly reinitialize the algorithm
// before it can be reused to compute the MAC of the next packet.
_serverMac.Initialize();

if (!macIsValid)
{
    throw new SshConnectionException("MAC error", DisconnectReason.MacError);
}

The client-side send path (_clientMac.TryComputeHash) already performs a one-shot hash computation per packet and is unaffected by this issue.

…tion

Co-authored-by: WojciechNagorski <17333903+WojciechNagorski@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix MAC error and CryptographicException in .NET Framework Reinitialize server MAC HashAlgorithm between packets to prevent spurious MAC errors Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MAC error / CryptographicException on .NET Framework in 2026.0.0: _serverMac is reused across packets without Initialize()

2 participants