Fix issues found during src/ code review

- ECH: add bounds check on hpkePubkeyLen against HPKE_Npk_MAX to
  prevent heap buffer overflow from untrusted ECH config data

- Sniffer: fix reassembly memory limit check typo, MaxRecoveryMemory -1
  should be MaxRecoveryMemory != -1

- Sniffer: add bounds check in IPv6 extension header parsing loop to
  prevent OOB read when next_header never matches TCP or NO_NEXT_HEADER

- Sniffer: validate tlsFragOffset + rhSize against tlsFragSize before
  XMEMCPY in both TLS handshake fragment reassembly paths

- Internal: use WC_SAFE_SUM_WORD32 in GrowAnOutputBuffer to prevent
  integer overflow on allocation size, matching existing pattern in
  GrowOutputBuffer
This commit is contained in:
Andrew Hutchings
2026-02-16 17:27:10 +00:00
parent 4fe05d7fe0
commit 8b44b00317
3 changed files with 29 additions and 6 deletions
+10 -4
View File
@@ -11294,6 +11294,7 @@ static WC_INLINE int GrowAnOutputBuffer(WOLFSSL* ssl,
#else
const byte align = WOLFSSL_GENERAL_ALIGNMENT;
#endif
word32 newSz = 0;
#if WOLFSSL_GENERAL_ALIGNMENT > 0
/* the encrypted data will be offset from the front of the buffer by
@@ -11304,8 +11305,13 @@ static WC_INLINE int GrowAnOutputBuffer(WOLFSSL* ssl,
align *= 2;
#endif
tmp = (byte*)XMALLOC(size + outputBuffer->length + align,
ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
if (!WC_SAFE_SUM_WORD32(outputBuffer->length, (word32)size, newSz))
return BUFFER_E;
#if WOLFSSL_GENERAL_ALIGNMENT > 0
if (!WC_SAFE_SUM_WORD32(newSz, align, newSz))
return BUFFER_E;
#endif
tmp = (byte*)XMALLOC(newSz, ssl->heap, DYNAMIC_TYPE_OUT_BUFFER);
WOLFSSL_MSG("growing output buffer");
if (tmp == NULL)
@@ -11318,7 +11324,7 @@ static WC_INLINE int GrowAnOutputBuffer(WOLFSSL* ssl,
#ifdef WOLFSSL_STATIC_MEMORY
/* can be from IO memory pool which does not need copy if same buffer */
if (outputBuffer->length && tmp == outputBuffer->buffer) {
outputBuffer->bufferSize = size + outputBuffer->length;
outputBuffer->bufferSize = newSz - align;
return 0;
}
#endif
@@ -11339,7 +11345,7 @@ static WC_INLINE int GrowAnOutputBuffer(WOLFSSL* ssl,
outputBuffer->buffer = tmp;
outputBuffer->dynamicFlag = 1;
outputBuffer->bufferSize = size + outputBuffer->length;
outputBuffer->bufferSize = newSz - align;
return 0;
}
#endif
+15 -2
View File
@@ -2146,8 +2146,13 @@ static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error)
exthdrsz += hdrsz;
exthdr = (Ip6ExtHdr*)((byte*)exthdr + hdrsz);
}
while (exthdr->next_header != TCP_PROTOCOL &&
while (exthdrsz < length &&
exthdr->next_header != TCP_PROTOCOL &&
exthdr->next_header != NO_NEXT_HEADER);
if (exthdrsz >= length) {
SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
return WOLFSSL_FATAL_ERROR;
}
}
#ifndef WOLFSSL_SNIFFER_WATCH
@@ -4571,6 +4576,10 @@ static int DoHandShake(const byte* input, int* sslBytes,
#ifdef HAVE_MAX_FRAGMENT
if (session->tlsFragBuf) {
if (session->tlsFragOffset + rhSize > session->tlsFragSize) {
SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
return WOLFSSL_FATAL_ERROR;
}
XMEMCPY(session->tlsFragBuf + session->tlsFragOffset, input, rhSize);
session->tlsFragOffset += rhSize;
*sslBytes -= rhSize;
@@ -4625,6 +4634,10 @@ static int DoHandShake(const byte* input, int* sslBytes,
*sslBytes += HANDSHAKE_HEADER_SZ;
}
if (session->tlsFragOffset + rhSize > session->tlsFragSize) {
SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
return WOLFSSL_FATAL_ERROR;
}
XMEMCPY(session->tlsFragBuf + session->tlsFragOffset, input, rhSize);
session->tlsFragOffset += rhSize;
*sslBytes -= rhSize;
@@ -5622,7 +5635,7 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
if (end >= curr->begin)
end = curr->begin - 1;
if (MaxRecoveryMemory -1 &&
if (MaxRecoveryMemory != -1 &&
(int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
return WOLFSSL_FATAL_ERROR;
+4
View File
@@ -580,6 +580,10 @@ int SetEchConfigsEx(WOLFSSL_EchConfig** outputConfigs, void* heap,
ato16(echConfig, &hpkePubkeyLen);
echConfig += 2;
/* hpke public_key */
if (hpkePubkeyLen > HPKE_Npk_MAX) {
ret = BUFFER_E;
break;
}
XMEMCPY(workingConfig->receiverPubkey, echConfig, hpkePubkeyLen);
echConfig += hpkePubkeyLen;
/* cipherSuitesLen */