From 36a539760a387973d57782bdfbd33b16d5c3e493 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 31 Jul 2017 11:24:42 -0700 Subject: [PATCH] DTLS Bad MAC Checks 1. Make the decrypt and verify MAC failure cases behave the same with respect to DTLS messages. It should pretend the message never happened. 2. Allow the echoclient to survive the echoserver sending a message with a bad MAC. 3. Allow the server to survive the client sending a message with a bad MAC. --- examples/echoclient/echoclient.c | 12 +++++++++++- examples/server/server.c | 9 +++++++++ src/internal.c | 27 ++++++++++++++++++++++++--- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/examples/echoclient/echoclient.c b/examples/echoclient/echoclient.c index 4a827f101..4e4afdf8d 100644 --- a/examples/echoclient/echoclient.c +++ b/examples/echoclient/echoclient.c @@ -25,10 +25,12 @@ #endif #include - /* let's use cyassl layer AND cyassl openssl layer */ #include #include +#ifdef CYASSL_DTLS + #include +#endif #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) #include @@ -266,6 +268,14 @@ void echoclient_test(void* args) fflush(fout) ; sendSz -= ret; } +#ifdef CYASSL_DTLS + else if (wolfSSL_dtls(ssl) && err == DECRYPT_ERROR) { + /* This condition is OK. The packet should be dropped + * silently when there is a decrypt or MAC error on + * a DTLS record. */ + sendSz = 0; + } +#endif else { printf("SSL_read msg error %d, %s\n", err, ERR_error_string(err, buffer)); diff --git a/examples/server/server.c b/examples/server/server.c index 60ee22007..7bcc83c20 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -47,6 +47,9 @@ #endif #include #include +#ifdef CYASSL_DTLS + #include +#endif #include "examples/server/server.h" @@ -294,6 +297,12 @@ static void ServerRead(WOLFSSL* ssl, char* input, int inputLen) if (ret < 0) break; } else + #endif + #ifdef CYASSL_DTLS + if (wolfSSL_dtls(ssl) && err == DECRYPT_ERROR) { + printf("Dropped client's message due to a bad MAC\n"); + } + else #endif if (err != SSL_ERROR_WANT_READ) { printf("SSL_read input error %d, %s\n", err, diff --git a/src/internal.c b/src/internal.c index df31227ed..42007c496 100755 --- a/src/internal.c +++ b/src/internal.c @@ -11706,6 +11706,9 @@ int ProcessReply(WOLFSSL* ssl) ssl->options.processReply = doProcessInit; ssl->buffers.inputBuffer.idx = ssl->buffers.inputBuffer.length; + #ifdef WOLFSSL_DTLS_DROP_STATS + ssl->macDropCount++; + #endif /* WOLFSSL_DTLS_DROP_STATS */ } #endif /* WOLFSSL_DTLS */ @@ -11732,9 +11735,18 @@ int ProcessReply(WOLFSSL* ssl) if (ret < 0) { WOLFSSL_MSG("VerifyMac failed"); WOLFSSL_ERROR(ret); - #ifdef WOLFSSL_DTLS_DROP_STATS - ssl->macDropCount++; - #endif /* WOLFSSL_DTLS_DROP_STATS */ + #ifdef WOLFSSL_DTLS + /* If in DTLS mode, if the decrypt fails for any + * reason, pretend the datagram never happened. */ + if (ssl->options.dtls) { + ssl->options.processReply = doProcessInit; + ssl->buffers.inputBuffer.idx = + ssl->buffers.inputBuffer.length; + #ifdef WOLFSSL_DTLS_DROP_STATS + ssl->macDropCount++; + #endif /* WOLFSSL_DTLS_DROP_STATS */ + } + #endif /* WOLFSSL_DTLS */ return DECRYPT_ERROR; } } @@ -13537,6 +13549,15 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) if (ssl->error == WANT_WRITE || ssl->error == WC_PENDING_E) ssl->error = 0; +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + /* In DTLS mode, we forgive some errors and allow the session + * to continue despite them. */ + if (ssl->error == VERIFY_MAC_ERROR || ssl->error == DECRYPT_ERROR) + ssl->error = 0; + } +#endif /* WOLFSSL_DTLS */ + #ifdef WOLFSSL_EARLY_DATA if (ssl->earlyData) { if (ssl->options.handShakeState == HANDSHAKE_DONE) {