From 59fdd98f1d97745687e986cfb9f7d8f9bfb71689 Mon Sep 17 00:00:00 2001 From: Stefan Gula Date: Wed, 26 Oct 2016 10:37:23 +0200 Subject: [PATCH] Adjust DTLS retranmission logic This patch adjust DTLS retranmission logic in order to avoid message floods between client and server --- src/internal.c | 40 +++++++++++++++++++++++++++++++++------- src/ssl.c | 2 +- wolfssl/internal.h | 3 ++- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/internal.c b/src/internal.c index 33c3b2826..4ce862173 100755 --- a/src/internal.c +++ b/src/internal.c @@ -4118,8 +4118,23 @@ int DtlsPoolTimeout(WOLFSSL* ssl) return result; } +int VerifyForDtlsPoolSend(WOLFSSL* ssl, byte type, word32 fragOffset) +{ + /** + * only the first message from previous flight should be valid + * to be used for triggering retransmission of whole DtlsPool. + * change cipher suite type is not verified here + */ + return ((fragOffset == 0) && + (((ssl->options.side == WOLFSSL_SERVER_END) && + ((type == client_hello) || + ((ssl->options.verifyPeer) && (type == certificate)) || + ((!ssl->options.verifyPeer) && (type == client_key_exchange)))) || + ((ssl->options.side == WOLFSSL_CLIENT_END) && + (type == server_hello)))); +} -int DtlsPoolSend(WOLFSSL* ssl) +int DtlsPoolSend(WOLFSSL* ssl, byte sendOnlyFirstPacket) { DtlsPool* pool = ssl->dtls_pool; @@ -4127,8 +4142,19 @@ int DtlsPoolSend(WOLFSSL* ssl) int ret = 0; int i; buffer* buf; + /** + * on server side, retranmission is being triggered only by sending + * first message of given flight, in order to trigger client + * to retransmit its whole flight. Sending the whole previous flight + * could lead to retranmission of previous client flight for each + * server message from previous flight. Therefore one message should be + * enough to do the trick. + */ + int maxPoolIndex = (((sendOnlyFirstPacket == 1) && + (ssl->options.side == WOLFSSL_SERVER_END) && + (pool->used >= 1)) ? 1 : pool->used); - for (i = 0, buf = pool->buf; i < pool->used; i++, buf++) { + for (i = 0, buf = pool->buf; i < maxPoolIndex; i++, buf++) { if (pool->epoch[i] == 0) { DtlsRecordLayerHeader* dtls; int epochOrder; @@ -4938,7 +4964,7 @@ retry: if (IsDtlsNotSctpMode(ssl) && !ssl->options.handShakeDone && DtlsPoolTimeout(ssl) == 0 && - DtlsPoolSend(ssl) == 0) { + DtlsPoolSend(ssl, 0) == 0) { goto retry; } @@ -7995,8 +8021,8 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, } *inOutIdx += ssl->keys.padSz; } - if (IsDtlsNotSctpMode(ssl)) - ret = DtlsPoolSend(ssl); + if (IsDtlsNotSctpMode(ssl) && VerifyForDtlsPoolSend(ssl, type, fragOffset)) + ret = DtlsPoolSend(ssl, 0); } else if (fragSz < size) { /* Since this branch is in order, but fragmented, dtls_msg_list will be @@ -9356,7 +9382,7 @@ int ProcessReply(WOLFSSL* ssl) ssl->buffers.inputBuffer.idx = 0; if (IsDtlsNotSctpMode(ssl) && ssl->options.dtlsHsRetain) { - ret = DtlsPoolSend(ssl); + ret = DtlsPoolSend(ssl, 0); if (ret != 0) return ret; } @@ -9515,7 +9541,7 @@ int ProcessReply(WOLFSSL* ssl) return ret; if (IsDtlsNotSctpMode(ssl)) { - ret = DtlsPoolSend(ssl); + ret = DtlsPoolSend(ssl, 1); if (ret != 0) return ret; } diff --git a/src/ssl.c b/src/ssl.c index 01bd455fd..5aed31dc7 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -6750,7 +6750,7 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) int result = SSL_SUCCESS; if (!ssl->options.handShakeDone && - (DtlsPoolTimeout(ssl) < 0 || DtlsPoolSend(ssl) < 0)) { + (DtlsPoolTimeout(ssl) < 0 || DtlsPoolSend(ssl, 0) < 0)) { result = SSL_FATAL_ERROR; } diff --git a/wolfssl/internal.h b/wolfssl/internal.h index ba2a6e89f..d51fb23a3 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3073,7 +3073,8 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); WOLFSSL_LOCAL int DtlsPoolInit(WOLFSSL*); WOLFSSL_LOCAL int DtlsPoolSave(WOLFSSL*, const byte*, int); WOLFSSL_LOCAL int DtlsPoolTimeout(WOLFSSL*); - WOLFSSL_LOCAL int DtlsPoolSend(WOLFSSL*); + WOLFSSL_LOCAL int DtlsPoolSend(WOLFSSL*, byte); + WOLFSSL_LOCAL int VerifyForDtlsPoolSend(WOLFSSL*, byte, word32); WOLFSSL_LOCAL void DtlsPoolReset(WOLFSSL*); WOLFSSL_LOCAL void DtlsPoolDelete(WOLFSSL*);