From 127e304901ddb23d8ae130de76ab4c60fbd2347a Mon Sep 17 00:00:00 2001 From: John Safranek Date: Sun, 1 Mar 2020 16:43:10 -0800 Subject: [PATCH 1/2] DTLS Fix An endpoint's retransmit pool was being reset when receiving its peer's change cipher spec message. When the finished message was lost, and retransmits need to happen, they weren't available, so nothing happened. Moved the reset to the finished case rather than CCS. --- src/internal.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index 0d6fa1630..eeff0e1bf 100644 --- a/src/internal.c +++ b/src/internal.c @@ -11376,6 +11376,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); @@ -14735,7 +14740,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; From 04dcb8f7747f2299ea9cac6a44be88257805d907 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 1 Apr 2020 17:17:51 -0700 Subject: [PATCH 2/2] DTLS Fix If the finished message (well, next epoch handshake message) is received, store it. Process it after a change cipher spec message. --- src/internal.c | 93 +++++++++++++++++++++++++++++++++++++++++----- wolfssl/internal.h | 2 + 2 files changed, 85 insertions(+), 10 deletions(-) diff --git a/src/internal.c b/src/internal.c index eeff0e1bf..ff1b3a3b3 100644 --- a/src/internal.c +++ b/src/internal.c @@ -5874,6 +5874,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 @@ -6088,6 +6091,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 @@ -11202,6 +11210,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); @@ -11930,6 +11943,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 @@ -12179,6 +12200,7 @@ static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl) window = peerSeq->prevWindow; } else { + WOLFSSL_MSG("Different epoch"); return 0; } @@ -14198,20 +14220,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 @@ -14761,6 +14807,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 17d9fc496..099ceb123 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3964,6 +3964,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