Merge pull request #10691 from julek-wolfssl/tls13-fragmented-sessionticket-defrag

TLS 1.3: reassemble fragmented post-handshake messages after FreeArrays
This commit is contained in:
Daniel Pouzzner
2026-07-03 00:50:10 -05:00
committed by GitHub
6 changed files with 210 additions and 72 deletions
+31 -25
View File
@@ -8339,8 +8339,6 @@ void FreeArrays(WOLFSSL* ssl, int keep)
XFREE(ssl->arrays->preMasterSecret, ssl->heap, DYNAMIC_TYPE_SECRET);
ssl->arrays->preMasterSecret = NULL;
}
XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
ssl->arrays->pendingMsg = NULL;
ForceZero(ssl->arrays, sizeof(Arrays)); /* clear arrays struct */
}
XFREE(ssl->arrays, ssl->heap, DYNAMIC_TYPE_ARRAYS);
@@ -8863,6 +8861,15 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl)
FreeCiphers(ssl);
FreeArrays(ssl, 0);
/* Defrag buffer for fragmented handshake messages. Lives in WOLFSSL (not
* Arrays) so it survives FreeArrays()/FreeHandshakeResources() and can be
* used to reassemble post-handshake messages; release it here. */
XFREE(ssl->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
ssl->pendingMsg = NULL;
/* Reset the rest of the defrag state for a possible object reuse. */
ssl->pendingMsgSz = 0;
ssl->pendingMsgOffset = 0;
ssl->pendingMsgType = 0;
FreeKeyExchange(ssl);
#ifdef WOLFSSL_ASYNC_IO
/* Cleanup async */
@@ -19182,7 +19189,7 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
/* If there is a pending fragmented handshake message,
* pending message size will be non-zero. */
if (ssl->arrays->pendingMsgSz == 0) {
if (ssl->pendingMsgSz == 0) {
byte type;
word32 size;
@@ -19210,17 +19217,17 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
/* size is the size of the certificate message payload */
if (inputLength - HANDSHAKE_HEADER_SZ < size) {
ssl->arrays->pendingMsgType = type;
ssl->arrays->pendingMsgSz = size + HANDSHAKE_HEADER_SZ;
ssl->arrays->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ,
ssl->heap,
DYNAMIC_TYPE_ARRAYS);
if (ssl->arrays->pendingMsg == NULL)
/* Commit pending state only after the allocation succeeds. */
ssl->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ,
ssl->heap, DYNAMIC_TYPE_ARRAYS);
if (ssl->pendingMsg == NULL)
return MEMORY_E;
XMEMCPY(ssl->arrays->pendingMsg,
ssl->pendingMsgType = type;
ssl->pendingMsgSz = size + HANDSHAKE_HEADER_SZ;
XMEMCPY(ssl->pendingMsg,
input + *inOutIdx - HANDSHAKE_HEADER_SZ,
inputLength);
ssl->arrays->pendingMsgOffset = inputLength;
ssl->pendingMsgOffset = inputLength;
*inOutIdx += inputLength - HANDSHAKE_HEADER_SZ;
return 0;
}
@@ -19228,8 +19235,7 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
}
else {
word32 pendSz =
ssl->arrays->pendingMsgSz - ssl->arrays->pendingMsgOffset;
word32 pendSz = ssl->pendingMsgSz - ssl->pendingMsgOffset;
/* Catch the case where there may be the remainder of a fragmented
* handshake message and the next handshake message in the same
@@ -19237,7 +19243,7 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
if (inputLength > pendSz)
inputLength = pendSz;
ret = EarlySanityCheckMsgReceived(ssl, ssl->arrays->pendingMsgType,
ret = EarlySanityCheckMsgReceived(ssl, ssl->pendingMsgType,
inputLength);
if (ret != 0) {
WOLFSSL_ERROR(ret);
@@ -19250,32 +19256,32 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
{
/* for async this copy was already done, do not replace, since
* contents may have been changed for inline operations */
XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset,
XMEMCPY(ssl->pendingMsg + ssl->pendingMsgOffset,
input + *inOutIdx, inputLength);
}
ssl->arrays->pendingMsgOffset += inputLength;
ssl->pendingMsgOffset += inputLength;
*inOutIdx += inputLength;
if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz)
if (ssl->pendingMsgOffset == ssl->pendingMsgSz)
{
word32 idx = HANDSHAKE_HEADER_SZ;
ret = DoHandShakeMsgType(ssl,
ssl->arrays->pendingMsg,
&idx, ssl->arrays->pendingMsgType,
ssl->arrays->pendingMsgSz - idx,
ssl->arrays->pendingMsgSz);
ssl->pendingMsg,
&idx, ssl->pendingMsgType,
ssl->pendingMsgSz - idx,
ssl->pendingMsgSz);
#ifdef WOLFSSL_ASYNC_CRYPT
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
/* setup to process fragment again */
ssl->arrays->pendingMsgOffset -= inputLength;
ssl->pendingMsgOffset -= inputLength;
*inOutIdx -= inputLength;
}
else
#endif
{
XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
ssl->arrays->pendingMsg = NULL;
ssl->arrays->pendingMsgSz = 0;
XFREE(ssl->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
ssl->pendingMsg = NULL;
ssl->pendingMsgSz = 0;
}
}
}
+7
View File
@@ -7960,6 +7960,13 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out,
ssl->keys.encryptionOn = 0;
XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
/* Discard any partial handshake-message reassembly on reuse. */
XFREE(ssl->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
ssl->pendingMsg = NULL;
ssl->pendingMsgSz = 0;
ssl->pendingMsgOffset = 0;
ssl->pendingMsgType = 0;
FreeCiphers(ssl);
InitCiphers(ssl);
InitCipherSpecs(&ssl->specs);
+23 -43
View File
@@ -14117,24 +14117,6 @@ int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
WOLFSSL_ENTER("DoTls13HandShakeMsg");
if (ssl->arrays == NULL) {
if (GetHandshakeHeader(ssl, input, inOutIdx, &type, &size,
totalSz) != 0) {
SendAlert(ssl, alert_fatal, unexpected_message);
WOLFSSL_ERROR_VERBOSE(PARSE_ERROR);
return PARSE_ERROR;
}
ret = EarlySanityCheckMsgReceived(ssl, type, size);
if (ret != 0) {
WOLFSSL_ERROR(ret);
return ret;
}
return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size,
totalSz);
}
/* totalSz is now curStartIdx + curSize (content-only, padSz already
* subtracted in ProcessReply). */
if (*inOutIdx > totalSz)
@@ -14143,7 +14125,7 @@ int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
/* If there is a pending fragmented handshake message,
* pending message size will be non-zero. */
if (ssl->arrays->pendingMsgSz == 0) {
if (ssl->pendingMsgSz == 0) {
if (GetHandshakeHeader(ssl, input, inOutIdx, &type, &size,
totalSz) != 0) {
@@ -14170,17 +14152,17 @@ int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
/* size is the size of the certificate message payload */
if (inputLength - HANDSHAKE_HEADER_SZ < size) {
ssl->arrays->pendingMsgType = type;
ssl->arrays->pendingMsgSz = size + HANDSHAKE_HEADER_SZ;
ssl->arrays->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ,
ssl->heap,
DYNAMIC_TYPE_ARRAYS);
if (ssl->arrays->pendingMsg == NULL)
/* Commit pending state only after the allocation succeeds. */
ssl->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ,
ssl->heap, DYNAMIC_TYPE_ARRAYS);
if (ssl->pendingMsg == NULL)
return MEMORY_E;
XMEMCPY(ssl->arrays->pendingMsg,
ssl->pendingMsgType = type;
ssl->pendingMsgSz = size + HANDSHAKE_HEADER_SZ;
XMEMCPY(ssl->pendingMsg,
input + *inOutIdx - HANDSHAKE_HEADER_SZ,
inputLength);
ssl->arrays->pendingMsgOffset = inputLength;
ssl->pendingMsgOffset = inputLength;
*inOutIdx += inputLength - HANDSHAKE_HEADER_SZ;
return 0;
}
@@ -14189,45 +14171,43 @@ int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
totalSz);
}
else {
if (inputLength + ssl->arrays->pendingMsgOffset >
ssl->arrays->pendingMsgSz) {
inputLength = ssl->arrays->pendingMsgSz -
ssl->arrays->pendingMsgOffset;
if (inputLength + ssl->pendingMsgOffset > ssl->pendingMsgSz) {
inputLength = ssl->pendingMsgSz - ssl->pendingMsgOffset;
}
ret = EarlySanityCheckMsgReceived(ssl, ssl->arrays->pendingMsgType,
ret = EarlySanityCheckMsgReceived(ssl, ssl->pendingMsgType,
inputLength);
if (ret != 0) {
WOLFSSL_ERROR(ret);
return ret;
}
XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset,
XMEMCPY(ssl->pendingMsg + ssl->pendingMsgOffset,
input + *inOutIdx, inputLength);
ssl->arrays->pendingMsgOffset += inputLength;
ssl->pendingMsgOffset += inputLength;
*inOutIdx += inputLength;
if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz)
if (ssl->pendingMsgOffset == ssl->pendingMsgSz)
{
word32 idx = 0;
ret = DoTls13HandShakeMsgType(ssl,
ssl->arrays->pendingMsg + HANDSHAKE_HEADER_SZ,
&idx, ssl->arrays->pendingMsgType,
ssl->arrays->pendingMsgSz - HANDSHAKE_HEADER_SZ,
ssl->arrays->pendingMsgSz);
ssl->pendingMsg + HANDSHAKE_HEADER_SZ,
&idx, ssl->pendingMsgType,
ssl->pendingMsgSz - HANDSHAKE_HEADER_SZ,
ssl->pendingMsgSz);
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) ||
ret == WC_NO_ERR_TRACE(OCSP_WANT_READ)) {
/* setup to process fragment again */
ssl->arrays->pendingMsgOffset -= inputLength;
ssl->pendingMsgOffset -= inputLength;
*inOutIdx -= inputLength;
}
else
#endif
{
XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
ssl->arrays->pendingMsg = NULL;
ssl->arrays->pendingMsgSz = 0;
XFREE(ssl->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS);
ssl->pendingMsg = NULL;
ssl->pendingMsgSz = 0;
}
}
}