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);