Skip to content

Advertise ETM MAC names for AEAD-only clients (fixes #236)#243

Open
barnaby wants to merge 1 commit into
apple:mainfrom
fdmtl:machine0-mac-advertise
Open

Advertise ETM MAC names for AEAD-only clients (fixes #236)#243
barnaby wants to merge 1 commit into
apple:mainfrom
fdmtl:machine0-mac-advertise

Conversation

@barnaby

@barnaby barnaby commented Jul 5, 2026

Copy link
Copy Markdown

Motivation

swift-nio-ssh only implements AEAD ciphers (AES-GCM, chacha20-poly1305), which report macName == nil and ignore MAC negotiation. But the KEXINIT still requires the MAC-name lists to intersect. The all-AEAD fallback in supportedMacAlgorithms advertises a single placeholder hmac-sha2-256, so a hardened OpenSSH server that offers only encrypt-then-MAC names (e.g. NixOS-style configs: hmac-sha2-512-etm@openssh.com, hmac-sha2-256-etm@openssh.com) has no intersection and the client fails with keyExchangeNegotiationFailure mid-handshake.

This is #236. Real-world impact: an iOS app using swift-nio-ssh as a direct SSH client cannot connect to hardened DigitalOcean/NixOS machines at all.

Change

When the scheme set yields no real MAC (all-AEAD), advertise the plain and -etm@openssh.com variants of SHA-256/512 instead of the single placeholder. The negotiated MAC value is still never used for AEAD schemes (integrity comes from the AEAD tag) — the list exists only so the KEXINIT MAC rows intersect with both stock and hardened servers.

Tests

Adds negotiation coverage in SSHKeyExchangeStateMachineTests: a captured hardened-prod KEXINIT (OpenSSH 10.2), ETM-only, rekey (same path re-run), both-directions-consulted, asymmetric-rejected (documents the symmetric-only constraint), and negative paths (no shared cipher / KEX / host-key).

Verified end-to-end: the patched stack completes the full handshake against real hardened OpenSSH 10.2 production machines in ~1s, where upstream fails at ~0.4s.

swift-nio-ssh only implements AEAD ciphers (AES-GCM, chacha20-poly1305),
which report macName == nil and ignore MAC negotiation. But the KEXINIT
still requires the MAC-name lists to intersect. The fallback advertised a
single placeholder hmac-sha2-256, so hardened OpenSSH servers that offer
ONLY encrypt-then-MAC names (e.g. NixOS-style configs) failed with
keyExchangeNegotiationFailure. Advertise the plain + -etm variants of
SHA-256/512 so negotiation intersects with both stock and hardened servers.
The negotiated value remains unused for AEAD schemes.

Adds negotiation tests: hardened-prod KEXINIT (captured vectors), ETM-only,
rekey, both-directions consulted, asymmetric-rejected, and negative paths
(no shared cipher/KEX/host-key).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant