From 04dcb8f7747f2299ea9cac6a44be88257805d907 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 1 Apr 2020 17:17:51 -0700 Subject: [PATCH] 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