From 8b934624f54c3ad89d1e7b1c198e633a3ebbb712 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 25 Aug 2020 11:26:20 +0200 Subject: [PATCH 1/7] DTLS non-blocking scrwith example --- examples/client/client.c | 52 +++++++++++++++++++++++++++++++++++++--- examples/server/server.c | 16 +++++++++---- src/internal.c | 51 +++++++++++++++++++++++++++++++-------- src/ssl.c | 16 +++++++++++++ wolfssl/error-ssl.h | 1 + wolfssl/internal.h | 1 + 6 files changed, 119 insertions(+), 18 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 84d65496c..0288325e3 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -856,7 +856,8 @@ static int ClientWrite(WOLFSSL* ssl, const char* msg, int msgSz, const char* str } #endif } - } while (err == WOLFSSL_ERROR_WANT_WRITE + } while (err == WOLFSSL_ERROR_WANT_WRITE || + err == WOLFSSL_ERROR_WANT_READ #ifdef WOLFSSL_ASYNC_CRYPT || err == WC_PENDING_E #endif @@ -3089,8 +3090,53 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_SECURE_RENEGOTIATION if (scr && forceScr) { if (nonBlocking) { - printf("not doing secure renegotiation on example with" - " nonblocking yet\n"); + if (!resumeScr) { + if ((ret = wolfSSL_Rehandshake(ssl)) != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + if (err == WOLFSSL_ERROR_WANT_READ || + err == WOLFSSL_ERROR_WANT_WRITE) { + (void)ClientWrite(ssl, + "This is a fun message sent during renegotiation", + sizeof("This is a fun message sent during renegotiation"), + "", 1); + do { + if (err == APP_DATA_READY) { + if ((ret = wolfSSL_read(ssl, reply, sizeof(reply)-1)) < 0) { + err_sys("APP DATA should be present but error returned"); + } + printf("Received message: %s\n", reply); + } + err = 0; + if ((ret = wolfSSL_connect(ssl)) != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, ret); + } + } while (ret != WOLFSSL_SUCCESS && + (err == WOLFSSL_ERROR_WANT_READ || + err == WOLFSSL_ERROR_WANT_WRITE || + err == APP_DATA_READY)); + + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + printf("wolfSSL_Rehandshake error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("non-blocking wolfSSL_Rehandshake failed"); + } + printf("NON-BLOCKING RENEGOTIATION SUCCESSFUL\n"); + } + else { + printf("wolfSSL_Rehandshake error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("non-blocking wolfSSL_Rehandshake failed"); + } + } + } + else { + printf("not doing secure resumption with non-blocking"); + } } else { if (!resumeScr) { printf("Beginning secure renegotiation.\n"); diff --git a/examples/server/server.c b/examples/server/server.c index dba33feca..d5acdff89 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -345,7 +345,7 @@ static int NonBlockingSSL_Accept(SSL* ssl) return ret; } -/* Echo number of bytes specified by -e arg */ +/* Echo number of bytes specified by -B arg */ int ServerEchoData(SSL* ssl, int clientfd, int echoData, int block, size_t throughput) { @@ -366,7 +366,10 @@ int ServerEchoData(SSL* ssl, int clientfd, int echoData, int block, select_ret = tcp_select(clientfd, 1); /* Timeout=1 second */ if (select_ret == TEST_RECV_READY) { - len = min(block, (int)(throughput - xfer_bytes)); + if (throughput) + len = min(block, (int)(throughput - xfer_bytes)); + else + len = block; rx_pos = 0; if (throughput) { @@ -386,7 +389,8 @@ int ServerEchoData(SSL* ssl, int clientfd, int echoData, int block, else #endif if (err != WOLFSSL_ERROR_WANT_READ && - err != WOLFSSL_ERROR_ZERO_RETURN) { + err != WOLFSSL_ERROR_ZERO_RETURN && + err != APP_DATA_READY) { printf("SSL_read echo error %d\n", err); err_sys_ex(runWithErrors, "SSL_read failed"); break; @@ -398,6 +402,8 @@ int ServerEchoData(SSL* ssl, int clientfd, int echoData, int block, } else { rx_pos += ret; + if (!throughput) + break; } } if (throughput) { @@ -408,7 +414,7 @@ int ServerEchoData(SSL* ssl, int clientfd, int echoData, int block, /* Write data */ do { err = 0; /* reset error */ - ret = SSL_write(ssl, buffer, len); + ret = SSL_write(ssl, buffer, min(len, rx_pos)); if (ret <= 0) { err = SSL_get_error(ssl, 0); #ifdef WOLFSSL_ASYNC_CRYPT @@ -419,7 +425,7 @@ int ServerEchoData(SSL* ssl, int clientfd, int echoData, int block, #endif } } while (err == WC_PENDING_E); - if (ret != len) { + if (ret != (int)min(len, rx_pos)) { printf("SSL_write echo error %d\n", err); err_sys_ex(runWithErrors, "SSL_write failed"); } diff --git a/src/internal.c b/src/internal.c index dc57df024..ab370fdf4 100644 --- a/src/internal.c +++ b/src/internal.c @@ -14587,6 +14587,27 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx) #endif *inOutIdx = idx; +#ifdef HAVE_SECURE_RENEGOTIATION + if (IsSCR(ssl)) { + /* If we are in a secure renegotiation then APP DATA is treated + * differently */ + if (ssl->options.dtls) { + /* Reset the processReply state since + * we finished processing this message. */ + ssl->options.processReply = doProcessInit; + return APP_DATA_READY; + } + else { + /* TODO should fail for TLS? */ + ssl->buffers.clearOutputBuffer.buffer = NULL; + ssl->buffers.clearOutputBuffer.length = 0; +#ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, unexpected_message); +#endif + return OUT_OF_ORDER_E; + } + } +#endif return 0; } @@ -14867,6 +14888,9 @@ int ProcessReply(WOLFSSL* ssl) #endif if (ssl->error != 0 && ssl->error != WANT_READ && ssl->error != WANT_WRITE + #ifdef HAVE_SECURE_RENEGOTIATION + && ssl->error != APP_DATA_READY + #endif #ifdef WOLFSSL_ASYNC_CRYPT && ssl->error != WC_PENDING_E #endif @@ -17595,14 +17619,15 @@ int DtlsCheckOrder(WOLFSSL* ssl, int order) /* If secure renegotiation is disabled, this will always return false. * Otherwise it checks to see if we are currently renegotiating. */ -static WC_INLINE int IsSCR(WOLFSSL* ssl) +int IsSCR(WOLFSSL* ssl) { #ifndef HAVE_SECURE_RENEGOTIATION (void)ssl; #else /* HAVE_SECURE_RENEGOTIATION */ if (ssl->secure_renegotiation && - ssl->secure_renegotiation->enabled && - ssl->options.handShakeState != HANDSHAKE_DONE) + ssl->secure_renegotiation->enabled && /* Is SCR enabled? */ + ssl->options.handShakeDone && /* At least one handshake done? */ + ssl->options.handShakeState != HANDSHAKE_DONE) /* Currently handshaking? */ return 1; #endif /* HAVE_SECURE_RENEGOTIATION */ return 0; @@ -17651,7 +17676,8 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) } else #endif - if (ssl->options.handShakeState != HANDSHAKE_DONE && !IsSCR(ssl)) { + if (ssl->options.handShakeState != HANDSHAKE_DONE && + !ssl->options.dtls /* Allow data during renegotiation */ ) { int err; WOLFSSL_MSG("handshake not complete, trying to finish"); if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) { @@ -17838,10 +17864,18 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) #ifdef HAVE_SECURE_RENEGOTIATION startScr: if (ssl->secure_renegotiation && ssl->secure_renegotiation->startScr) { + int ret; int err; WOLFSSL_MSG("Need to start scr, server requested"); - if ( (err = wolfSSL_Rehandshake(ssl)) != WOLFSSL_SUCCESS) - return err; + if ( (ret = wolfSSL_Rehandshake(ssl)) != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + if (err == WOLFSSL_ERROR_WANT_READ || + err == WOLFSSL_ERROR_WANT_WRITE || + err == APP_DATA_READY) + ssl->secure_renegotiation->startScr = 0; /* only start once + * on non-blocking */ + return ret; + } ssl->secure_renegotiation->startScr = 0; /* only start once */ } #endif @@ -17871,10 +17905,7 @@ startScr: #endif } - if (sz < (int)ssl->buffers.clearOutputBuffer.length) - size = sz; - else - size = ssl->buffers.clearOutputBuffer.length; + size = min(sz, ssl->buffers.clearOutputBuffer.length); XMEMCPY(output, ssl->buffers.clearOutputBuffer.buffer, size); diff --git a/src/ssl.c b/src/ssl.c index 11bc08a3c..e51f068fb 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2020,6 +2020,22 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek) errno = 0; #endif +#ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->buffers.clearOutputBuffer.length > 0) { + int size = min(sz, ssl->buffers.clearOutputBuffer.length); + XMEMCPY(data, ssl->buffers.clearOutputBuffer.buffer, size); + if (peek == 0) { + ssl->buffers.clearOutputBuffer.length -= size; + ssl->buffers.clearOutputBuffer.buffer += size; + } + if (ssl->buffers.clearOutputBuffer.length == 0 && + ssl->buffers.inputBuffer.dynamicFlag) + ShrinkInputBuffer(ssl, NO_FORCED_FREE); + WOLFSSL_LEAVE("wolfSSL_read_internal()", size); + return size; + } +#endif + #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { ssl->dtls_expected_rx = max(sz + 100, MAX_MTU); diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index c6870d96c..88c47b9c6 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -169,6 +169,7 @@ enum wolfSSL_ErrorCodes { TLS13_SECRET_CB_E = -438, /* TLS1.3 secret Cb fcn failure */ DTLS_SIZE_ERROR = -439, /* Trying to send too much data */ NO_CERT_ERROR = -440, /* TLS1.3 - no cert set error */ + APP_DATA_READY = -441, /* DTLS1.2 application data ready for read */ /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 925720fd2..95ed8347e 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -4550,6 +4550,7 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); WOLFSSL_LOCAL int IsDtlsMsgSCRKeys(WOLFSSL* ssl); WOLFSSL_LOCAL int DtlsUseSCRKeys(WOLFSSL* ssl); WOLFSSL_LOCAL int DtlsCheckOrder(WOLFSSL* ssl, int order); + WOLFSSL_LOCAL int IsSCR(WOLFSSL* ssl); #endif WOLFSSL_LOCAL void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out); From 52df9d6c69ee627a1e5d0829ff0d654c1be1eba2 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 27 Aug 2020 20:57:53 +0200 Subject: [PATCH 2/7] TLS and DTLS both need to support APP DATA during SCR Also some misc fixes --- examples/client/client.c | 4 +-- examples/server/server.c | 28 +++++++++++++-- src/internal.c | 73 +++++++++++++++++++--------------------- src/ssl.c | 16 --------- 4 files changed, 63 insertions(+), 58 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 0288325e3..b8c37b110 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -3096,8 +3096,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE) { (void)ClientWrite(ssl, - "This is a fun message sent during renegotiation", - sizeof("This is a fun message sent during renegotiation"), + "msg sent during renegotiation", + sizeof("msg sent during renegotiation"), "", 1); do { if (err == APP_DATA_READY) { diff --git a/examples/server/server.c b/examples/server/server.c index d5acdff89..8ccac29b4 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -474,6 +474,17 @@ static void ServerRead(WOLFSSL* ssl, char* input, int inputLen) if (ret < 0) { err = SSL_get_error(ssl, 0); + #ifdef HAVE_SECURE_RENEGOTIATION + if (err == APP_DATA_READY) { + ret = SSL_read(ssl, input, inputLen); + if (ret >= 0) { + /* null terminate message */ + input[ret] = '\0'; + printf("Client message: %s\n", input); + return; + } + } + #endif #ifdef WOLFSSL_ASYNC_CRYPT if (err == WC_PENDING_E) { ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); @@ -487,7 +498,11 @@ static void ServerRead(WOLFSSL* ssl, char* input, int inputLen) } else #endif - if (err != WOLFSSL_ERROR_WANT_READ) { + if (err != WOLFSSL_ERROR_WANT_READ + #ifdef HAVE_SECURE_RENEGOTIATION + && err != APP_DATA_READY + #endif + ) { printf("SSL_read input error %d, %s\n", err, ERR_error_string(err, buffer)); err_sys_ex(runWithErrors, "SSL_read failed"); @@ -499,7 +514,8 @@ static void ServerRead(WOLFSSL* ssl, char* input, int inputLen) } } while (err == WC_PENDING_E || err == WOLFSSL_ERROR_WANT_READ); if (ret > 0) { - input[ret] = 0; /* null terminate message */ + /* null terminate message */ + input[ret] = '\0'; printf("Client message: %s\n", input); } } @@ -2428,6 +2444,14 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) if (echoData == 0 && throughput == 0) { ServerRead(ssl, input, sizeof(input)-1); err = SSL_get_error(ssl, 0); +#ifdef HAVE_SECURE_RENEGOTIATION + if (err == APP_DATA_READY) { + /* Data was sent during SCR so let's get the message + * after the SCR as well */ + ServerRead(ssl, input, sizeof(input)-1); + err = SSL_get_error(ssl, 0); + } +#endif } #if defined(HAVE_SECURE_RENEGOTIATION) && \ diff --git a/src/internal.c b/src/internal.c index ab370fdf4..b81c0feb2 100644 --- a/src/internal.c +++ b/src/internal.c @@ -14589,23 +14589,12 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx) *inOutIdx = idx; #ifdef HAVE_SECURE_RENEGOTIATION if (IsSCR(ssl)) { + /* Reset the processReply state since + * we finished processing this message. */ + ssl->options.processReply = doProcessInit; /* If we are in a secure renegotiation then APP DATA is treated * differently */ - if (ssl->options.dtls) { - /* Reset the processReply state since - * we finished processing this message. */ - ssl->options.processReply = doProcessInit; - return APP_DATA_READY; - } - else { - /* TODO should fail for TLS? */ - ssl->buffers.clearOutputBuffer.buffer = NULL; - ssl->buffers.clearOutputBuffer.length = 0; -#ifdef WOLFSSL_EXTRA_ALERTS - SendAlert(ssl, alert_fatal, unexpected_message); -#endif - return OUT_OF_ORDER_E; - } + return APP_DATA_READY; } #endif return 0; @@ -17676,8 +17665,7 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) } else #endif - if (ssl->options.handShakeState != HANDSHAKE_DONE && - !ssl->options.dtls /* Allow data during renegotiation */ ) { + if (ssl->options.handShakeState != HANDSHAKE_DONE && !IsSCR(ssl)) { int err; WOLFSSL_MSG("handshake not complete, trying to finish"); if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) { @@ -17836,6 +17824,9 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) if (ssl->error != 0 && ssl->error != WANT_WRITE #ifdef WOLFSSL_ASYNC_CRYPT && ssl->error != WC_PENDING_E +#endif +#ifdef HAVE_SECURE_RENEGOTIATION + && ssl->error != APP_DATA_READY #endif ) { WOLFSSL_MSG("User calling wolfSSL_read in error state, not allowed"); @@ -17847,17 +17838,31 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) } else #endif - if (ssl->options.handShakeState != HANDSHAKE_DONE) { - int err; - WOLFSSL_MSG("Handshake not complete, trying to finish"); - if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) { - #ifdef WOLFSSL_ASYNC_CRYPT - /* if async would block return WANT_WRITE */ - if (ssl->error == WC_PENDING_E) { - return WOLFSSL_CBIO_ERR_WANT_READ; + { + int negotiate = 0; +#ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) { + if (ssl->options.handShakeState != HANDSHAKE_DONE + && ssl->buffers.clearOutputBuffer.length == 0) + negotiate = 1; + } + else +#endif + if (ssl->options.handShakeState != HANDSHAKE_DONE) + negotiate = 1; + + if (negotiate) { + int err; + WOLFSSL_MSG("Handshake not complete, trying to finish"); + if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) { + #ifdef WOLFSSL_ASYNC_CRYPT + /* if async would block return WANT_WRITE */ + if (ssl->error == WC_PENDING_E) { + return WOLFSSL_CBIO_ERR_WANT_READ; + } + #endif + return err; } - #endif - return err; } } @@ -17865,18 +17870,10 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) startScr: if (ssl->secure_renegotiation && ssl->secure_renegotiation->startScr) { int ret; - int err; - WOLFSSL_MSG("Need to start scr, server requested"); - if ( (ret = wolfSSL_Rehandshake(ssl)) != WOLFSSL_SUCCESS) { - err = wolfSSL_get_error(ssl, 0); - if (err == WOLFSSL_ERROR_WANT_READ || - err == WOLFSSL_ERROR_WANT_WRITE || - err == APP_DATA_READY) - ssl->secure_renegotiation->startScr = 0; /* only start once - * on non-blocking */ - return ret; - } + ret = wolfSSL_Rehandshake(ssl); ssl->secure_renegotiation->startScr = 0; /* only start once */ + if (ret != WOLFSSL_SUCCESS) + return ret; } #endif diff --git a/src/ssl.c b/src/ssl.c index e51f068fb..11bc08a3c 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2020,22 +2020,6 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek) errno = 0; #endif -#ifdef HAVE_SECURE_RENEGOTIATION - if (ssl->buffers.clearOutputBuffer.length > 0) { - int size = min(sz, ssl->buffers.clearOutputBuffer.length); - XMEMCPY(data, ssl->buffers.clearOutputBuffer.buffer, size); - if (peek == 0) { - ssl->buffers.clearOutputBuffer.length -= size; - ssl->buffers.clearOutputBuffer.buffer += size; - } - if (ssl->buffers.clearOutputBuffer.length == 0 && - ssl->buffers.inputBuffer.dynamicFlag) - ShrinkInputBuffer(ssl, NO_FORCED_FREE); - WOLFSSL_LEAVE("wolfSSL_read_internal()", size); - return size; - } -#endif - #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { ssl->dtls_expected_rx = max(sz + 100, MAX_MTU); From 605b274442c8dd45509fd027ec803bc830db71cc Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Fri, 28 Aug 2020 11:35:48 +0200 Subject: [PATCH 3/7] Jenkins fixes --- examples/server/server.c | 4 +--- src/internal.c | 2 +- wolfssl/internal.h | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/server/server.c b/examples/server/server.c index 8ccac29b4..abd1d716b 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -39,9 +39,7 @@ #include #include -#ifdef WOLFSSL_DTLS - #include -#endif +#include #include "examples/server/server.h" diff --git a/src/internal.c b/src/internal.c index b81c0feb2..3cdba396e 100644 --- a/src/internal.c +++ b/src/internal.c @@ -17902,7 +17902,7 @@ startScr: #endif } - size = min(sz, ssl->buffers.clearOutputBuffer.length); + size = min(sz, (int)ssl->buffers.clearOutputBuffer.length); XMEMCPY(output, ssl->buffers.clearOutputBuffer.buffer, size); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 95ed8347e..bec0352ee 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -4550,8 +4550,8 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); WOLFSSL_LOCAL int IsDtlsMsgSCRKeys(WOLFSSL* ssl); WOLFSSL_LOCAL int DtlsUseSCRKeys(WOLFSSL* ssl); WOLFSSL_LOCAL int DtlsCheckOrder(WOLFSSL* ssl, int order); - WOLFSSL_LOCAL int IsSCR(WOLFSSL* ssl); #endif + WOLFSSL_LOCAL int IsSCR(WOLFSSL* ssl); WOLFSSL_LOCAL void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out); From a65ffe15bc5f0319702778dcb5ab548ad8257692 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 9 Sep 2020 21:41:20 +0200 Subject: [PATCH 4/7] Implement non-blocking SCR on server side --- examples/server/server.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/examples/server/server.c b/examples/server/server.c index abd1d716b..2f4dac0da 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -2456,8 +2456,44 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) defined(HAVE_SERVER_RENEGOTIATION_INFO) if (scr && forceScr) { if (nonBlocking) { - printf("not doing secure renegotiation on example with" - " nonblocking yet\n"); + if ((ret = wolfSSL_Rehandshake(ssl)) != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + if (err == WOLFSSL_ERROR_WANT_READ || + err == WOLFSSL_ERROR_WANT_WRITE) { + do { + if (err == APP_DATA_READY) { + if ((ret = wolfSSL_read(ssl, input, sizeof(input)-1)) < 0) { + err_sys("APP DATA should be present but error returned"); + } + printf("Received message: %s\n", input); + } + err = 0; + if ((ret = wolfSSL_accept(ssl)) != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, ret); + } + } while (ret != WOLFSSL_SUCCESS && + (err == WOLFSSL_ERROR_WANT_READ || + err == WOLFSSL_ERROR_WANT_WRITE || + err == APP_DATA_READY)); + + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + printf("wolfSSL_Rehandshake error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("non-blocking wolfSSL_Rehandshake failed"); + } + printf("NON-BLOCKING RENEGOTIATION SUCCESSFUL\n"); + } + else { + printf("wolfSSL_Rehandshake error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(ssl); ssl = NULL; + wolfSSL_CTX_free(ctx); ctx = NULL; + err_sys("non-blocking wolfSSL_Rehandshake failed"); + } + } } else { if ((ret = wolfSSL_Rehandshake(ssl)) != WOLFSSL_SUCCESS) { #ifdef WOLFSSL_ASYNC_CRYPT From 04b4ef3e3b5b5632b4034226d059509589f50462 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 16 Sep 2020 14:02:51 +0200 Subject: [PATCH 5/7] Don't send null byte --- examples/client/client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/client/client.c b/examples/client/client.c index b8c37b110..057700197 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -3097,7 +3097,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) err == WOLFSSL_ERROR_WANT_WRITE) { (void)ClientWrite(ssl, "msg sent during renegotiation", - sizeof("msg sent during renegotiation"), + sizeof("msg sent during renegotiation") - 1, "", 1); do { if (err == APP_DATA_READY) { From 84f0fc56efed7c59d780dae8b88d10dbf7f6d145 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Fri, 25 Sep 2020 11:35:23 +0200 Subject: [PATCH 6/7] check ClientWrite return --- examples/client/client.c | 34 +++++++++++++++++++++------------- src/internal.c | 1 + 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 057700197..3aa2afa62 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -3095,25 +3095,33 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) err = wolfSSL_get_error(ssl, 0); if (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE) { - (void)ClientWrite(ssl, + ret = ClientWrite(ssl, "msg sent during renegotiation", sizeof("msg sent during renegotiation") - 1, "", 1); - do { - if (err == APP_DATA_READY) { - if ((ret = wolfSSL_read(ssl, reply, sizeof(reply)-1)) < 0) { - err_sys("APP DATA should be present but error returned"); + if (ret != 0) { + ret = WOLFSSL_FAILURE; + } + else { + do { + if (err == APP_DATA_READY) { + if ((ret = wolfSSL_read(ssl, reply, + sizeof(reply)-1)) < 0) { + err_sys("APP DATA should be present " + "but error returned"); + } + printf("Received message: %s\n", reply); } - printf("Received message: %s\n", reply); - } - err = 0; - if ((ret = wolfSSL_connect(ssl)) != WOLFSSL_SUCCESS) { - err = wolfSSL_get_error(ssl, ret); - } - } while (ret != WOLFSSL_SUCCESS && - (err == WOLFSSL_ERROR_WANT_READ || + err = 0; + if ((ret = wolfSSL_connect(ssl)) + != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, ret); + } + } while (ret != WOLFSSL_SUCCESS && + (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE || err == APP_DATA_READY)); + } if (ret != WOLFSSL_SUCCESS) { err = wolfSSL_get_error(ssl, 0); diff --git a/src/internal.c b/src/internal.c index 3cdba396e..dedee911e 100644 --- a/src/internal.c +++ b/src/internal.c @@ -17870,6 +17870,7 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) startScr: if (ssl->secure_renegotiation && ssl->secure_renegotiation->startScr) { int ret; + WOLFSSL_MSG("Need to start scr, server requested"); ret = wolfSSL_Rehandshake(ssl); ssl->secure_renegotiation->startScr = 0; /* only start once */ if (ret != WOLFSSL_SUCCESS) From a7fdfbaf4098b1f8cdbccad47e391683e1f95dcf Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 30 Sep 2020 13:46:23 +0200 Subject: [PATCH 7/7] Passing scr-app-data in to -i to client sends a message during SCR Modify mygetopt so that if an argument expects a value and that value is the next argument then myoptarg is set to a NULL pointer. --- examples/client/client.c | 31 +++++++++--- examples/server/server.c | 21 ++++---- tests/test-dtls-reneg-client.conf | 81 +++++++++++++++++++++++++++++++ wolfssl/test.h | 27 ++++++++++- 4 files changed, 140 insertions(+), 20 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 3aa2afa62..52471640f 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -999,7 +999,11 @@ static const char* client_usage_msg[][59] = { "-M Use STARTTLS, using protocol (smtp)\n", /* 27 */ #ifdef HAVE_SECURE_RENEGOTIATION "-R Allow Secure Renegotiation\n", /* 28 */ - "-i Force client Initiated Secure Renegotiation\n", /* 29 */ + "-i Force client Initiated Secure Renegotiation. If the\n" + " string 'scr-app-data' is passed in as the value and\n" + " Non-blocking sockets are enabled ('-N') then wolfSSL\n" + " sends a test message during the secure renegotiation.\n" + " The string parameter is optional.\n", /* 29 */ #endif "-f Fewer packets/group messages\n", /* 30 */ "-x Disable client cert/key loading\n", /* 31 */ @@ -1160,7 +1164,7 @@ static const char* client_usage_msg[][59] = { "使用する\n", /* 27 */ #ifdef HAVE_SECURE_RENEGOTIATION "-R セキュアな再ネゴシエーションを許可する\n", /* 28 */ - "-i クライアント主導のネゴシエーションを強制する\n", /* 29 */ + "-i クライアント主導のネゴシエーションを強制する\n", /* 29 */ #endif "-f より少ないパケット/グループメッセージを使用する\n",/* 30 */ "-x クライアントの証明書/鍵のロードを無効する\n", /* 31 */ @@ -1461,6 +1465,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) int err = 0; int scr = 0; /* allow secure renegotiation */ int forceScr = 0; /* force client initiated scr */ + int scrAppData = 0; int resumeScr = 0; /* use resumption for renegotiation */ #ifndef WOLFSSL_NO_CLIENT_AUTH int useClientCert = 1; @@ -1597,6 +1602,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) (void)atomicUser; (void)scr; (void)forceScr; + (void)scrAppData; (void)resumeScr; (void)ourKey; (void)ourCert; @@ -1623,7 +1629,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifndef WOLFSSL_VXWORKS /* Not used: All used */ while ((ch = mygetopt(argc, argv, "?:" - "ab:c:defgh:ijk:l:mnop:q:rstuv:wxyz" + "ab:c:defgh:i;jk:l:mnop:q:rstuv:wxyz" "A:B:CDE:F:GH:IJKL:M:NO:PQRS:TUVW:XYZ:" "01:23:458")) != -1) { switch (ch) { @@ -1862,6 +1868,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_SECURE_RENEGOTIATION scr = 1; forceScr = 1; + if (XSTRNCMP(myoptarg, "scr-app-data", 12) == 0) { + scrAppData = 1; + } #endif break; @@ -3095,10 +3104,15 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) err = wolfSSL_get_error(ssl, 0); if (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE) { - ret = ClientWrite(ssl, - "msg sent during renegotiation", - sizeof("msg sent during renegotiation") - 1, - "", 1); + if (scrAppData) { + ret = ClientWrite(ssl, + "msg sent during renegotiation", + sizeof("msg sent during renegotiation") - 1, + "", 1); + } + else { + ret = 0; + } if (ret != 0) { ret = WOLFSSL_FAILURE; } @@ -3110,7 +3124,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) err_sys("APP DATA should be present " "but error returned"); } - printf("Received message: %s\n", reply); + printf("Received message during " + "renegotiation: %s\n", reply); } err = 0; if ((ret = wolfSSL_connect(ssl)) diff --git a/examples/server/server.c b/examples/server/server.c index 2f4dac0da..cc7afc39b 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -470,16 +470,23 @@ static void ServerRead(WOLFSSL* ssl, char* input, int inputLen) err = 0; /* reset error */ ret = SSL_read(ssl, input, inputLen); if (ret < 0) { - err = SSL_get_error(ssl, 0); + err = SSL_get_error(ssl, ret); #ifdef HAVE_SECURE_RENEGOTIATION if (err == APP_DATA_READY) { + /* If we receive a message during renegotiation + * then just print it. We return the message sent + * after the renegotiation. */ ret = SSL_read(ssl, input, inputLen); if (ret >= 0) { /* null terminate message */ input[ret] = '\0'; - printf("Client message: %s\n", input); - return; + printf("Client message received during " + "secure renegotiation: %s\n", input); + err = WOLFSSL_ERROR_WANT_READ; + } + else { + err = SSL_get_error(ssl, ret); } } #endif @@ -2442,14 +2449,6 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) if (echoData == 0 && throughput == 0) { ServerRead(ssl, input, sizeof(input)-1); err = SSL_get_error(ssl, 0); -#ifdef HAVE_SECURE_RENEGOTIATION - if (err == APP_DATA_READY) { - /* Data was sent during SCR so let's get the message - * after the SCR as well */ - ServerRead(ssl, input, sizeof(input)-1); - err = SSL_get_error(ssl, 0); - } -#endif } #if defined(HAVE_SECURE_RENEGOTIATION) && \ diff --git a/tests/test-dtls-reneg-client.conf b/tests/test-dtls-reneg-client.conf index bb405c16d..60d73af5c 100644 --- a/tests/test-dtls-reneg-client.conf +++ b/tests/test-dtls-reneg-client.conf @@ -4,6 +4,87 @@ -v 3 -l DHE-RSA-CHACHA20-POLY1305 +# client DTLSv1.2 DHE-RSA-CHACHA20-POLY1305 +-i scr-app-data +-u +-v 3 +-l DHE-RSA-CHACHA20-POLY1305 + +# server DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 +-M +-u +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305 + +# client DTLSv1.2 ECDHE-RSA-CHACHA20-POLY1305 +-i scr-app-data +-u +-v 3 +-l ECDHE-RSA-CHACHA20-POLY1305 + +# server DTLSv1.2 ECDHE-EDCSA-CHACHA20-POLY1305 +-M +-u +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client DTLSv1.2 ECDHE-ECDSA-CHACHA20-POLY1305 +-i scr-app-data +-u +-v 3 +-l ECDHE-ECDSA-CHACHA20-POLY1305 +-A ./certs/ca-ecc-cert.pem + +# server TLSv1.2 DHE-PSK-CHACHA20-POLY1305 +-M +-u +-v 3 +-s +-l DHE-PSK-CHACHA20-POLY1305 + +# client TLSv1.2 DHE-PSK-CHACHA20-POLY1305 +-i scr-app-data +-u +-v 3 +-s +-l DHE-PSK-CHACHA20-POLY1305 + +# server TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-M +-u +-v 3 +-s +-l ECDHE-PSK-CHACHA20-POLY1305 + +# client TLSv1.2 ECDHE-PSK-CHACHA20-POLY1305 +-i scr-app-data +-u +-v 3 +-s +-l ECDHE-PSK-CHACHA20-POLY1305 + +# server TLSv1.2 PSK-CHACHA20-POLY1305 +-M +-u +-v 3 +-s +-l PSK-CHACHA20-POLY1305 + +# client TLSv1.2 PSK-CHACHA20-POLY1305 +-i scr-app-data +-u +-v 3 +-s +-l PSK-CHACHA20-POLY1305 + +# server DTLSv1.2 DHE-RSA-CHACHA20-POLY1305 +-M +-u +-v 3 +-l DHE-RSA-CHACHA20-POLY1305 + # client DTLSv1.2 DHE-RSA-CHACHA20-POLY1305 -i -u diff --git a/wolfssl/test.h b/wolfssl/test.h index c3136894b..3b933a14e 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -505,6 +505,17 @@ err_sys(const char* msg) extern int myoptind; extern char* myoptarg; +/** + * + * @param argc Number of argv strings + * @param argv Array of string arguments + * @param optstring String containing the supported alphanumeric arguments. + * A ':' following a character means that it requires a + * value in myoptarg to be set. A ';' means that the + * myoptarg is optional. myoptarg is set to "" if not + * present. + * @return Option letter in argument + */ static WC_INLINE int mygetopt(int argc, char** argv, const char* optstring) { static char* next = NULL; @@ -554,7 +565,7 @@ static WC_INLINE int mygetopt(int argc, char** argv, const char* optstring) /* The C++ strchr can return a different value */ cp = (char*)strchr(optstring, c); - if (cp == NULL || c == ':') + if (cp == NULL || c == ':' || 'c' == ';') return '?'; cp++; @@ -571,6 +582,20 @@ static WC_INLINE int mygetopt(int argc, char** argv, const char* optstring) else return '?'; } + else if (*cp == ';') { + myoptarg = (char*)""; + if (*next != '\0') { + myoptarg = next; + next = NULL; + } + else if (myoptind < argc) { + /* Check if next argument is not a parameter argument */ + if (argv[myoptind] && argv[myoptind][0] != '-') { + myoptarg = argv[myoptind]; + myoptind++; + } + } + } return c; }