diff --git a/src/internal.c b/src/internal.c index 320bb78e3..77af578ac 100644 --- a/src/internal.c +++ b/src/internal.c @@ -6270,6 +6270,9 @@ void SSL_ResourceFree(WOLFSSL* ssl) ssl->dtls_rx_msg_list = NULL; ssl->dtls_rx_msg_list_sz = 0; } + XFREE(ssl->dtls_pending_finished, ssl->heap, DYNAMIC_TYPE_DTLS_BUFFER); + ssl->dtls_pending_finished = NULL; + ssl->dtls_pending_finished_sz = 0; XFREE(ssl->buffers.dtlsCtx.peer.sa, ssl->heap, DYNAMIC_TYPE_SOCKADDR); ssl->buffers.dtlsCtx.peer.sa = NULL; #ifndef NO_WOLFSSL_SERVER @@ -6508,6 +6511,11 @@ void FreeHandshakeResources(WOLFSSL* ssl) DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap); ssl->dtls_rx_msg_list = NULL; ssl->dtls_rx_msg_list_sz = 0; + if (ssl->dtls_pending_finished != NULL) { + XFREE(ssl->dtls_pending_finished, ssl->heap, DYNAMIC_TYPE_DTLS_MSG); + ssl->dtls_pending_finished = NULL; + ssl->dtls_pending_finished_sz = 0; + } } #endif @@ -11722,6 +11730,11 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, default: ret = BUFFER_ERROR; } +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + DtlsMsgPoolReset(ssl); + } +#endif if (ret != 0) SendAlert(ssl, alert_fatal, bad_certificate_status_response); @@ -11896,6 +11909,11 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size, ssl->options.handShakeDone = 1; } } +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + DtlsMsgPoolReset(ssl); + } +#endif WOLFSSL_LEAVE("DoFinished", 0); WOLFSSL_END(WC_FUNC_FINISHED_DO); @@ -12447,6 +12465,14 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, case finished: WOLFSSL_MSG("processing finished"); ret = DoFinished(ssl, input, inOutIdx, size, totalSz, NO_SNIFF); + + #ifdef WOLFSSL_DTLS + if (ssl->dtls_pending_finished != NULL) { + XFREE(ssl->dtls_pending_finished, ssl->heap, DYNAMIC_TYPE_DTLS_MSG); + ssl->dtls_pending_finished = NULL; + ssl->dtls_pending_finished_sz = 0; + } + #endif break; #ifndef NO_WOLFSSL_SERVER @@ -12697,6 +12723,7 @@ static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl) window = peerSeq->prevWindow; } else { + WOLFSSL_MSG("Different epoch"); return 0; } @@ -14716,20 +14743,44 @@ int ProcessReply(WOLFSSL* ssl) &ssl->curRL, &ssl->curSize); #ifdef WOLFSSL_DTLS if (ssl->options.dtls && ret == SEQUENCE_ERROR) { - WOLFSSL_MSG("Silently dropping out of order DTLS message"); - ssl->options.processReply = doProcessInit; - ssl->buffers.inputBuffer.length = 0; - ssl->buffers.inputBuffer.idx = 0; + if (ssl->keys.curEpoch != 0) { + word32 sz = ssl->buffers.inputBuffer.length - + ssl->buffers.inputBuffer.idx + + DTLS_RECORD_HEADER_SZ; + + if (ssl->dtls_pending_finished != NULL) { + XFREE(ssl->dtls_pending_finished, ssl->heap, + DYNAMIC_TYPE_DTLS_MSG); + } + + ssl->dtls_pending_finished = (byte*)XMALLOC(sz, ssl->heap, + DYNAMIC_TYPE_DTLS_MSG); + if (ssl->dtls_pending_finished == NULL) + return MEMORY_E; + + ssl->dtls_pending_finished_sz = sz; + XMEMCPY(ssl->dtls_pending_finished, + ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.idx - + DTLS_RECORD_HEADER_SZ, + sz); + ssl->buffers.inputBuffer.idx += ssl->curSize; + } + else { + WOLFSSL_MSG("Silently dropping out of order DTLS message"); + ssl->options.processReply = doProcessInit; + ssl->buffers.inputBuffer.length = 0; + ssl->buffers.inputBuffer.idx = 0; #ifdef WOLFSSL_DTLS_DROP_STATS - ssl->replayDropCount++; + ssl->replayDropCount++; #endif /* WOLFSSL_DTLS_DROP_STATS */ - if (IsDtlsNotSctpMode(ssl) && ssl->options.dtlsHsRetain) { - ret = DtlsMsgPoolSend(ssl, 0); - if (ret != 0) - return ret; + if (IsDtlsNotSctpMode(ssl) && ssl->options.dtlsHsRetain) { + ret = DtlsMsgPoolSend(ssl, 0); + if (ret != 0) + return ret; + } } - continue; } #endif @@ -15258,7 +15309,6 @@ int ProcessReply(WOLFSSL* ssl) ssl->ctx->mcastMaxSeq); } #endif - DtlsMsgPoolReset(ssl); peerSeq->nextEpoch++; peerSeq->prevSeq_lo = peerSeq->nextSeq_lo; peerSeq->prevSeq_hi = peerSeq->nextSeq_hi; @@ -15280,6 +15330,33 @@ int ProcessReply(WOLFSSL* ssl) server : client); if (ret != 0) return ret; +#ifdef WOLFSSL_DTLS + if (ssl->dtls_pending_finished != NULL && + ssl->dtls_pending_finished_sz > 0) { + + if (GrowInputBuffer(ssl, ssl->dtls_pending_finished_sz, + ssl->buffers.inputBuffer.length - + ssl->buffers.inputBuffer.idx) < 0) { + + return MEMORY_E; + } + + XMEMCPY(ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.idx, + ssl->dtls_pending_finished, + ssl->dtls_pending_finished_sz); + ssl->buffers.inputBuffer.length += + ssl->dtls_pending_finished_sz; + + XFREE(ssl->dtls_pending_finished, ssl->heap, + DYNAMIC_TYPE_DTLS_MSG); + ssl->dtls_pending_finished = NULL; + ssl->dtls_pending_finished_sz = 0; + + ssl->options.processReply = getRecordLayerHeader; + continue; + } +#endif #endif /* !WOLFSSL_NO_TLS12 */ break; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 7c6e6090a..7c2c6571f 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -4019,6 +4019,8 @@ struct WOLFSSL { DtlsMsg* dtls_tx_msg_list; DtlsMsg* dtls_tx_msg; DtlsMsg* dtls_rx_msg_list; + byte* dtls_pending_finished; + word32 dtls_pending_finished_sz; void* IOCB_CookieCtx; /* gen cookie ctx */ word32 dtls_expected_rx; #ifdef WOLFSSL_SESSION_EXPORT