Skip to content

Commit 0edb38e

Browse files
internal: send a disconnect when key exchange fails
- DoKexDhInit() sends SSH_MSG_DISCONNECT with KEY_EXCHANGE_FAILED on WS_CRYPTO_FAILED and WS_PUBKEY_REJECTED_E, DoKexDhGexGroup() on WS_CRYPTO_FAILED and WS_DH_SIZE_E. - DoKexDhReply() sends KEY_EXCHANGE_FAILED on WS_CRYPTO_FAILED and HOST_KEY_NOT_VERIFIABLE on WS_PUBKEY_REJECTED_E. - DuplexEndpoint records the reason code of a plaintext outbound disconnect, and InitKexReplyHarnessKex() takes an explicit KEX algorithm. - New mutator modes shorten f and e, write a zero-length e, cut the GEX prime below the requested floor and set the GEX generator to 1; LocateSinglePacketPayload() finds the payload for all three single-packet rewriters. - The harness KEX algorithm falls back to curve25519-sha256, then ecdh-sha2-nistp256, when no plain diffie-hellman-group is built. - Tests assert the reason code on the wire for each new mode and for host key rejection, and assert no disconnect on a successful handshake. Issue: F-8838
1 parent 5336ee5 commit 0edb38e

2 files changed

Lines changed: 450 additions & 38 deletions

File tree

src/internal.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5944,6 +5944,12 @@ static int DoKexDhInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
59445944
ret = SendKexDhReply(ssh);
59455945
}
59465946

5947+
/* RFC 8731 sec. 3: a rejected key exchange input aborts with a
5948+
* disconnect */
5949+
if (ret == WS_CRYPTO_FAILED || ret == WS_PUBKEY_REJECTED_E) {
5950+
(void)SendDisconnect(ssh, WOLFSSH_DISCONNECT_KEY_EXCHANGE_FAILED);
5951+
}
5952+
59475953
return ret;
59485954
}
59495955

@@ -7627,6 +7633,15 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
76277633

76287634
if (sigKeyBlock_ptr)
76297635
WFREE(sigKeyBlock_ptr, ssh->ctx->heap, DYNTYPE_PRIVKEY);
7636+
/* RFC 4253 11.1: WS_PUBKEY_REJECTED_E here is only the host key check,
7637+
* which is server authentication, so it gets its own reason. */
7638+
if (ret == WS_CRYPTO_FAILED) {
7639+
(void)SendDisconnect(ssh, WOLFSSH_DISCONNECT_KEY_EXCHANGE_FAILED);
7640+
}
7641+
else if (ret == WS_PUBKEY_REJECTED_E) {
7642+
(void)SendDisconnect(ssh,
7643+
WOLFSSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
7644+
}
76307645
WLOG(WS_LOG_DEBUG, "Leaving DoKexDhReply(), ret = %d", ret);
76317646
return ret;
76327647
}
@@ -8027,6 +8042,12 @@ static int DoKexDhGexGroup(WOLFSSH* ssh,
80278042
ret = SendKexDhInit(ssh);
80288043
}
80298044

8045+
/* A group under the enforced floor (RFC 8270) or a bad generator ends
8046+
* the key exchange, so tell the peer why. */
8047+
if (ret == WS_CRYPTO_FAILED || ret == WS_DH_SIZE_E) {
8048+
(void)SendDisconnect(ssh, WOLFSSH_DISCONNECT_KEY_EXCHANGE_FAILED);
8049+
}
8050+
80308051
return ret;
80318052
}
80328053

@@ -16281,9 +16302,8 @@ int SendKexDhGexRequest(WOLFSSH* ssh)
1628116302
}
1628216303
}
1628316304

16284-
/* RFC 4419 sec. 3 requires min <= preferred <= max on the wire. Clamp
16285-
* preferred into that range in both directions; riding it up with a raised
16286-
* min or down under a lowered max keeps the advertised triple ordered. */
16305+
/* Keep the advertised triple ordered: clamp preferred into [min, max]
16306+
* in both directions. */
1628716307
if (ret == WS_SUCCESS) {
1628816308
if (ssh->handshake->dhGexPreferredSz < ssh->handshake->dhGexMinSz)
1628916309
ssh->handshake->dhGexPreferredSz = ssh->handshake->dhGexMinSz;

0 commit comments

Comments
 (0)