Skip to content

v1.10.3

@MalteKiefer MalteKiefer tagged this 26 Apr 07:43
Verified against OpenSSH 9.9 source (kexmlkem768x25519.c,
kexsntrup761x25519.c):

  1. mlkem768x25519-sha256 client public-key blob is
     `kem_pub || x25519_pub` (kem first, 1184 + 32 = 1216 bytes).
     Previous build sent x25519 first, so OpenSSH rejected the blob
     as a malformed mlkem public key during keypair validation.
  2. Server reply for mlkem768x25519 is
     `kem_ciphertext || server_x25519_pub`. Previous parser had the
     two halves swapped.
  3. Both hybrids derive K = HASH(kem_ss || x25519_ss) — SHA-256
     for mlkem768x25519, SHA-512 for sntrup761x25519 — and the
     resulting digest is the shared-secret bytes that flow through
     `writer.writeString(...)` into the exchange hash and key-
     derivation buffer. The previous build fed the raw concatenation
     into the hash, which made the client and server derive
     different session keys; the negotiation succeeded but the
     first encrypted packet failed integrity.

This is what made connections to PQ-only OpenSSH 9.9+ servers
manifest as `Authentication aborted` even though KEX itself appeared
to negotiate cleanly.
Assets 2
Loading