From 9e8467907727fde9db0d6b3b014a194d3a997794 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 12 May 2026 09:52:39 -0700 Subject: [PATCH 1/4] Zero key buffers on load failure - ForceZero newKey before WFREE in DoPemKey/DoOpenSshKey, covering both locally-allocated and caller-supplied buffers. - ForceZero PEM file buffer after read in wolfSSH_ReadKey_file - Track newKeySz for caller-supplied buffer path Issue: F-2885, F-3211, F-3212 --- src/ssh.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ssh.c b/src/ssh.c index ec0f6a361..5e261c482 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -1868,7 +1868,7 @@ static int DoPemKey(const byte* in, word32 inSz, byte** out, WOLFSSH_UNUSED(heap); if (*out == NULL) { - newKey = (byte*)WMALLOC(inSz, heap, DYNTYPE_PRIVKEY); + newKey = (byte*)WMALLOC(newKeySz, heap, DYNTYPE_PRIVKEY); if (newKey == NULL) { return WS_MEMORY_E; } @@ -1879,6 +1879,7 @@ static int DoPemKey(const byte* in, word32 inSz, byte** out, return WS_BUFFER_E; } newKey = *out; + newKeySz = *outSz; } /* If it is PEM, convert to ASN1 then process. */ @@ -1914,6 +1915,7 @@ static int DoPemKey(const byte* in, word32 inSz, byte** out, } else { WLOG(WS_LOG_DEBUG, "Unable to identify PEM key"); + ForceZero(newKey, newKeySz); if (*out == NULL) { WFREE(newKey, heap, DYNTYPE_PRIVKEY); } @@ -1943,6 +1945,7 @@ static int DoOpenSshKey(const byte* in, word32 inSz, byte** out, return WS_BUFFER_E; } newKey = *out; + newKeySz = *outSz; } in += WSTRLEN(PrivBeginOpenSSH); @@ -1970,6 +1973,7 @@ static int DoOpenSshKey(const byte* in, word32 inSz, byte** out, } else { WLOG(WS_LOG_DEBUG, "Unable to identify key"); + ForceZero(newKey, newKeySz); if (*out == NULL) { WFREE(newKey, heap, DYNTYPE_PRIVKEY); } @@ -2122,6 +2126,7 @@ int wolfSSH_ReadKey_file(const char* name, } WFCLOSE(NULL, file); + ForceZero(in, inSz); WFREE(in, heap, DYNTYPE_FILE); return ret; From 0652f129c56e7915f2aaf45cb25ea97ba5cfb34e Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 12 May 2026 10:38:39 -0700 Subject: [PATCH 2/4] Zero lastBlock buffers in GenerateKey - Add ForceZero on lastBlock in both remainder paths - Prevents leftover key-derivation material on the stack Issue: F-2494 --- src/internal.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/internal.c b/src/internal.c index e50693795..eb44c4792 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2584,6 +2584,7 @@ int GenerateKey(byte hashId, byte keyId, ret = wc_HashFinal(&hash, enmhashId, lastBlock); if (ret == WS_SUCCESS) WMEMCPY(key, lastBlock, remainder); + ForceZero(lastBlock, sizeof(lastBlock)); } } else { @@ -2629,6 +2630,7 @@ int GenerateKey(byte hashId, byte keyId, ret = wc_HashFinal(&hash, enmhashId, lastBlock); if (ret == WS_SUCCESS) WMEMCPY(key + runningKeySz, lastBlock, remainder); + ForceZero(lastBlock, sizeof(lastBlock)); } } } From 5905e830921112a6d77cdea8be2ee76e732f820e Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 12 May 2026 10:52:14 -0700 Subject: [PATCH 3/4] Fix integer overflow in ParseRFC6187 name length - Reject name lengths that would overflow m when added to sizeof(word32), preventing OOB reads on later checks. Issue: F-1277 --- apps/wolfssh/common.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/wolfssh/common.c b/apps/wolfssh/common.c index 8eb2c6059..03b4ac633 100644 --- a/apps/wolfssh/common.c +++ b/apps/wolfssh/common.c @@ -144,6 +144,9 @@ static int ParseRFC6187(const byte* in, word32 inSz, byte** leafOut, /* Skip the name */ ato32(in, &l); + if (l > inSz - sizeof(word32)) + return WS_BUFFER_E; + m += l + sizeof(word32); /* Get the cert count */ From 6c394c12f7b4f4b82260b6c83dda0c40ece06374 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 12 May 2026 11:05:39 -0700 Subject: [PATCH 4/4] Pin expectMsgId after KEXDH_GEX_GROUP - Set expectMsgId to MSGID_KEXDH_GEX_INIT so the server rejects any other KEX message at this stage (RFC 4419 sec 3). - Reject NULL ssh->handshake in the entry check now that the success path dereferences it. Issue: F-3668 --- src/internal.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/internal.c b/src/internal.c index eb44c4792..ccb2b9fdd 100644 --- a/src/internal.c +++ b/src/internal.c @@ -13476,7 +13476,7 @@ int SendKexDhGexGroup(WOLFSSH* ssh) int ret = WS_SUCCESS; WLOG(WS_LOG_DEBUG, "Entering SendKexDhGexGroup()"); - if (ssh == NULL) + if (ssh == NULL || ssh->handshake == NULL) ret = WS_BAD_ARGUMENT; if (ret == WS_SUCCESS) { @@ -13523,8 +13523,11 @@ int SendKexDhGexGroup(WOLFSSH* ssh) ret = BundlePacket(ssh); } - if (ret == WS_SUCCESS) + if (ret == WS_SUCCESS) { + WLOG_EXPECT_MSGID(MSGID_KEXDH_GEX_INIT); + ssh->handshake->expectMsgId = MSGID_KEXDH_GEX_INIT; ret = wolfSSH_SendPacket(ssh); + } WLOG(WS_LOG_DEBUG, "Leaving SendKexDhGexGroup(), ret = %d", ret); return ret;