mirror of https://github.com/wolfSSL/wolfssh.git
Client: check first_packet_follows guess in DoKexDhReply
When a server sends first_kex_packet_follows=TRUE with an incorrect KEX algorithm guess, the client now silently discards the server's speculative KEXDH_REPLY message by checking ignoreNextKexMsg at the top of DoKexDhReply, matching the existing server-side handling in DoKexDhInit. Add regression test covering the client-side skip path. Affected functions: DoKexDhReply. Issue: F-2863pull/960/head
parent
b610dd75c4
commit
f0c17282bc
|
|
@ -5823,6 +5823,17 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
if (ssh->handshake->ignoreNextKexMsg) {
|
||||
/* skip this message. */
|
||||
WLOG(WS_LOG_DEBUG, "Skipping server's KEXDH_REPLY message due to "
|
||||
"first_packet_follows guess mismatch.");
|
||||
ssh->handshake->ignoreNextKexMsg = 0;
|
||||
*idx += len;
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS && len < LENGTH_SZ*2 + *idx) {
|
||||
ret = WS_BUFFER_E;
|
||||
}
|
||||
|
|
@ -17901,6 +17912,11 @@ int wolfSSH_TestDoKexDhInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
|
|||
return DoKexDhInit(ssh, buf, len, idx);
|
||||
}
|
||||
|
||||
int wolfSSH_TestDoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
|
||||
{
|
||||
return DoKexDhReply(ssh, buf, len, idx);
|
||||
}
|
||||
|
||||
int wolfSSH_TestChannelPutData(WOLFSSH_CHANNEL* channel, byte* data,
|
||||
word32 dataSz)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2072,9 +2072,9 @@ typedef int (*FirstPacketFollowsSkipFn)(WOLFSSH* ssh, byte* buf, word32 len,
|
|||
word32* idx);
|
||||
|
||||
/* With ignoreNextKexMsg set, the target Do* handler must consume the packet,
|
||||
* clear the flag, and not advance clientState past CLIENT_KEXINIT_DONE. */
|
||||
* clear the flag, and not advance the peer's state past KEXINIT_DONE. */
|
||||
static void RunFirstPacketFollowsSkipCase(FirstPacketFollowsSkipFn fn,
|
||||
const char* label)
|
||||
const char* label, byte endpointType, byte initState)
|
||||
{
|
||||
WOLFSSH_CTX* ctx;
|
||||
WOLFSSH* ssh;
|
||||
|
|
@ -2082,7 +2082,7 @@ static void RunFirstPacketFollowsSkipCase(FirstPacketFollowsSkipFn fn,
|
|||
word32 idx = 0;
|
||||
int ret;
|
||||
|
||||
ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL);
|
||||
ctx = wolfSSH_CTX_new(endpointType, NULL);
|
||||
AssertNotNull(ctx);
|
||||
|
||||
ssh = wolfSSH_new(ctx);
|
||||
|
|
@ -2090,9 +2090,12 @@ static void RunFirstPacketFollowsSkipCase(FirstPacketFollowsSkipFn fn,
|
|||
AssertNotNull(ssh->handshake);
|
||||
|
||||
ssh->handshake->ignoreNextKexMsg = 1;
|
||||
ssh->clientState = CLIENT_KEXINIT_DONE;
|
||||
if (endpointType == WOLFSSH_ENDPOINT_SERVER)
|
||||
ssh->clientState = initState;
|
||||
else
|
||||
ssh->serverState = initState;
|
||||
|
||||
/* Garbage payload — must never be parsed when skipped. */
|
||||
/* Garbage payload that must never be parsed when skipped. */
|
||||
WMEMSET(payload, 0xAB, sizeof(payload));
|
||||
|
||||
ret = fn(ssh, payload, sizeof(payload), &idx);
|
||||
|
|
@ -2101,7 +2104,10 @@ static void RunFirstPacketFollowsSkipCase(FirstPacketFollowsSkipFn fn,
|
|||
}
|
||||
AssertIntEQ(idx, sizeof(payload));
|
||||
AssertIntEQ(ssh->handshake->ignoreNextKexMsg, 0);
|
||||
AssertIntEQ(ssh->clientState, CLIENT_KEXINIT_DONE);
|
||||
if (endpointType == WOLFSSH_ENDPOINT_SERVER)
|
||||
AssertIntEQ(ssh->clientState, initState);
|
||||
else
|
||||
AssertIntEQ(ssh->serverState, initState);
|
||||
|
||||
wolfSSH_free(ssh);
|
||||
wolfSSH_CTX_free(ctx);
|
||||
|
|
@ -2109,11 +2115,14 @@ static void RunFirstPacketFollowsSkipCase(FirstPacketFollowsSkipFn fn,
|
|||
|
||||
static void TestFirstPacketFollowsSkipped(void)
|
||||
{
|
||||
RunFirstPacketFollowsSkipCase(wolfSSH_TestDoKexDhInit, "DoKexDhInit");
|
||||
RunFirstPacketFollowsSkipCase(wolfSSH_TestDoKexDhInit,
|
||||
"DoKexDhInit", WOLFSSH_ENDPOINT_SERVER, CLIENT_KEXINIT_DONE);
|
||||
#ifndef WOLFSSH_NO_DH_GEX_SHA256
|
||||
RunFirstPacketFollowsSkipCase(wolfSSH_TestDoKexDhGexRequest,
|
||||
"DoKexDhGexRequest");
|
||||
"DoKexDhGexRequest", WOLFSSH_ENDPOINT_SERVER, CLIENT_KEXINIT_DONE);
|
||||
#endif
|
||||
RunFirstPacketFollowsSkipCase(wolfSSH_TestDoKexDhReply,
|
||||
"DoKexDhReply", WOLFSSH_ENDPOINT_CLIENT, SERVER_KEXINIT_DONE);
|
||||
}
|
||||
|
||||
static void TestFirstPacketFollows(void)
|
||||
|
|
|
|||
|
|
@ -1337,6 +1337,8 @@ enum WS_MessageIdLimits {
|
|||
word32 len, word32* idx);
|
||||
WOLFSSH_API int wolfSSH_TestDoKexDhInit(WOLFSSH* ssh, byte* buf,
|
||||
word32 len, word32* idx);
|
||||
WOLFSSH_API int wolfSSH_TestDoKexDhReply(WOLFSSH* ssh, byte* buf,
|
||||
word32 len, word32* idx);
|
||||
WOLFSSH_API int wolfSSH_TestChannelPutData(WOLFSSH_CHANNEL*, byte*, word32);
|
||||
#ifndef WOLFSSH_NO_DH_GEX_SHA256
|
||||
WOLFSSH_API int wolfSSH_TestDoKexDhGexRequest(WOLFSSH* ssh, byte* buf,
|
||||
|
|
|
|||
Loading…
Reference in New Issue