diff --git a/src/internal.c b/src/internal.c index 111eb9ffde..c43e9a9ac4 100644 --- a/src/internal.c +++ b/src/internal.c @@ -22292,17 +22292,6 @@ static int DoProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) return ssl->error; } - /* If checking alert on error (allowSocketErr == 1) do not try and - * process alerts for async or ocsp non blocking */ -#if defined(WOLFSSL_CHECK_ALERT_ON_ERR) && \ - (defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)) - if (allowSocketErr == 1 && \ - (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E) || - ssl->error == WC_NO_ERR_TRACE(OCSP_WANT_READ))) { - return ssl->error; - } -#endif - #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_ASYNC_CRYPT) /* process any pending DTLS messages - this flow can happen with async */ if (ssl->dtls_rx_msg_list != NULL) { @@ -42524,6 +42513,37 @@ int wolfSSL_TestAppleNativeCertValidation_AppendCA(WOLFSSL_CTX* ctx, #endif /* defined(__APPLE__) && defined(WOLFSSL_SYS_CA_CERTS) */ +/* Do not try to process error for async, non blocking io, and app_read */ +void wolfssl_local_MaybeCheckAlertOnErr(WOLFSSL* ssl, int err) +{ +#if defined(WOLFSSL_CHECK_ALERT_ON_ERR) +#if defined(WOLFSSL_ASYNC_CRYPT) + if (err == WC_NO_ERR_TRACE(WC_PENDING_E)) { + return; + } +#endif +#if defined(WOLFSSL_NONBLOCK_OCSP) + if (err == WC_NO_ERR_TRACE(OCSP_WANT_READ)) { + return; + } +#endif +#if defined(WOLFSSL_EARLY_DATA) + if (err == WC_NO_ERR_TRACE(APP_DATA_READY)) { + return; + } +#endif + if (err == WC_NO_ERR_TRACE(WANT_WRITE) || + err == WC_NO_ERR_TRACE(WANT_READ)) { + return; + } + /* check if an alert was sent */ + ProcessReplyEx(ssl, 1); +#else + (void)ssl; + (void)err; +#endif /* WOLFSSL_CHECK_ALERT_ON_ERR */ +} + #undef ERROR_OUT #endif /* !WOLFCRYPT_ONLY */ diff --git a/src/ssl.c b/src/ssl.c index 4c1f7b1856..d0983b1a7d 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -10591,9 +10591,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif if (ssl->options.sendVerify) { if ( (ssl->error = SendCertificate(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif + wolfssl_local_MaybeCheckAlertOnErr(ssl, ssl->error); WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -10612,9 +10610,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif if (!ssl->options.resuming) { if ( (ssl->error = SendClientKeyExchange(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif + wolfssl_local_MaybeCheckAlertOnErr(ssl, ssl->error); #ifdef WOLFSSL_EXTRA_ALERTS if (ssl->error == WC_NO_ERR_TRACE(NO_PEER_KEY) || ssl->error == WC_NO_ERR_TRACE(PSK_KEY_ERROR)) { @@ -10643,9 +10639,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH) if (ssl->options.sendVerify) { if ( (ssl->error = SendCertificateVerify(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif + wolfssl_local_MaybeCheckAlertOnErr(ssl, ssl->error); WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -10658,9 +10652,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, case FIRST_REPLY_THIRD : if ( (ssl->error = SendChangeCipher(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif + wolfssl_local_MaybeCheckAlertOnErr(ssl, ssl->error); WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -10671,9 +10663,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, case FIRST_REPLY_FOURTH : if ( (ssl->error = SendFinished(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif + wolfssl_local_MaybeCheckAlertOnErr(ssl, ssl->error); WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -11051,9 +11041,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, return WOLFSSL_FATAL_ERROR; } if ( (ssl->error = SendServerHello(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif + wolfssl_local_MaybeCheckAlertOnErr(ssl, ssl->error); WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -11070,9 +11058,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #ifndef NO_CERTS if (!ssl->options.resuming) if ( (ssl->error = SendCertificate(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif + wolfssl_local_MaybeCheckAlertOnErr(ssl, ssl->error); WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -11085,9 +11071,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #ifndef NO_CERTS if (!ssl->options.resuming) if ( (ssl->error = SendCertificateStatus(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif + wolfssl_local_MaybeCheckAlertOnErr(ssl, ssl->error); WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -11104,9 +11088,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif if (!ssl->options.resuming) if ( (ssl->error = SendServerKeyExchange(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif + wolfssl_local_MaybeCheckAlertOnErr(ssl, ssl->error); WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -11119,10 +11101,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, if (!ssl->options.resuming) { if (ssl->options.verifyPeer) { if ( (ssl->error = SendCertificateRequest(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - /* See if an alert was sent. */ - ProcessReplyEx(ssl, 1); - #endif + wolfssl_local_MaybeCheckAlertOnErr(ssl, ssl->error); WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -11140,9 +11119,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, case CERT_REQ_SENT : if (!ssl->options.resuming) if ( (ssl->error = SendServerHelloDone(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif + wolfssl_local_MaybeCheckAlertOnErr(ssl, ssl->error); WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -11181,9 +11158,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #ifdef HAVE_SESSION_TICKET if (ssl->options.createTicket && !ssl->options.noTicketTls12) { if ( (ssl->error = SendTicket(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif + wolfssl_local_MaybeCheckAlertOnErr(ssl, ssl->error); WOLFSSL_MSG("Thought we need ticket but failed"); WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; @@ -11202,9 +11177,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } if ( (ssl->error = SendChangeCipher(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif + wolfssl_local_MaybeCheckAlertOnErr(ssl, ssl->error); WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -11214,9 +11187,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, case CHANGE_CIPHER_SENT : if ( (ssl->error = SendFinished(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif + wolfssl_local_MaybeCheckAlertOnErr(ssl, ssl->error); WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } diff --git a/src/tls13.c b/src/tls13.c index e4026c8527..9726c50b9f 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -13396,24 +13396,26 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) ssl->options.connectState = CLIENT_HELLO_SENT; WOLFSSL_MSG("TLSv13 connect state: CLIENT_HELLO_SENT"); + FALL_THROUGH; + + case CLIENT_HELLO_SENT: #ifdef WOLFSSL_EARLY_DATA - if (ssl->earlyData != no_early_data) { + if (ssl->earlyData != no_early_data && + ssl->options.handShakeState != CLIENT_HELLO_COMPLETE) { #if defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) - if (!ssl->options.dtls && ssl->options.tls13MiddleBoxCompat) { - if ((ssl->error = SendChangeCipher(ssl)) != 0) { - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; + if (!ssl->options.dtls && + ssl->options.tls13MiddleBoxCompat) { + if ((ssl->error = SendChangeCipher(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.sentChangeCipher = 1; } - ssl->options.sentChangeCipher = 1; - } #endif - ssl->options.handShakeState = CLIENT_HELLO_COMPLETE; - return WOLFSSL_SUCCESS; + ssl->options.handShakeState = CLIENT_HELLO_COMPLETE; + return WOLFSSL_SUCCESS; } #endif - FALL_THROUGH; - - case CLIENT_HELLO_SENT: /* Get the response/s from the server. */ while (ssl->options.serverState < SERVER_HELLOVERIFYREQUEST_COMPLETE) { @@ -13546,9 +13548,7 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) if (!ssl->options.resuming && ssl->options.sendVerify) { ssl->error = SendTls13Certificate(ssl); if (ssl->error != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif + wolfssl_local_MaybeCheckAlertOnErr(ssl, ssl->error); WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -13568,9 +13568,7 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) if (!ssl->options.resuming && ssl->options.sendVerify) { ssl->error = SendTls13CertificateVerify(ssl); if (ssl->error != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif + wolfssl_local_MaybeCheckAlertOnErr(ssl, ssl->error); WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -13584,9 +13582,7 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) case FIRST_REPLY_FOURTH: if ((ssl->error = SendTls13Finished(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif + wolfssl_local_MaybeCheckAlertOnErr(ssl, ssl->error); WOLFSSL_ERROR(ssl->error); return WOLFSSL_FATAL_ERROR; } @@ -14736,15 +14732,16 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) ssl->options.acceptState = TLS13_ACCEPT_FINISHED_SENT; WOLFSSL_MSG("accept state ACCEPT_FINISHED_SENT"); + FALL_THROUGH; + + case TLS13_ACCEPT_FINISHED_SENT: #ifdef WOLFSSL_EARLY_DATA - if (ssl->earlyData != no_early_data) { + if (ssl->earlyData != no_early_data && + ssl->options.handShakeState != SERVER_FINISHED_COMPLETE) { ssl->options.handShakeState = SERVER_FINISHED_COMPLETE; return WOLFSSL_SUCCESS; } #endif - FALL_THROUGH; - - case TLS13_ACCEPT_FINISHED_SENT : #ifdef HAVE_SESSION_TICKET #ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED if (!ssl->options.verifyPeer && !ssl->options.noTicketTls13 && @@ -15064,7 +15061,10 @@ int wolfSSL_read_early_data(WOLFSSL* ssl, void* data, int sz, int* outSz) return SIDE_ERROR; if (ssl->options.handShakeState == NULL_STATE) { - if (ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E)) + /* the server flight can return WANT_WRITE and we re-enter here after + * setting ssl->earlyData = process_early_data, set earlyData to + * expecting_early_data just once */ + if (ssl->earlyData < expecting_early_data) ssl->earlyData = expecting_early_data; /* this used to be: ret = wolfSSL_accept_TLSv13(ssl); * However, wolfSSL_accept_TLSv13() expects a certificate to @@ -15096,6 +15096,20 @@ int wolfSSL_read_early_data(WOLFSSL* ssl, void* data, int sz, int* outSz) #endif /* WOLFSSL_DTLS13 */ } } +#ifdef WOLFSSL_DTLS13 + else if (ssl->buffers.outputBuffer.length > 0 && + ssl->options.dtls && ssl->dtls13SendingAckOrRtx) { + ret = SendBuffered(ssl); + if (ret == 0) { + ssl->dtls13SendingAckOrRtx = 0; + } + else { + ssl->error = ret; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } +#endif /* WOLFSSL_DTLS13 */ else ret = 0; #else diff --git a/tests/api/test_tls13.c b/tests/api/test_tls13.c index abf0e1e02b..b28faf24f8 100644 --- a/tests/api/test_tls13.c +++ b/tests/api/test_tls13.c @@ -1992,6 +1992,101 @@ int test_tls13_pq_groups(void) return EXPECT_RESULT(); } +#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ + defined(WOLFSSL_EARLY_DATA) && defined(HAVE_SESSION_TICKET) +static int test_tls13_read_until_write_ok(WOLFSSL* ssl, void* buf, int bufLen) +{ + int ret, err; + int tries = 5; + + err = 0; + do { + ret = wolfSSL_read(ssl, buf, bufLen); + if (ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) { + err = wolfSSL_get_error(ssl, ret); + } + } while (tries-- && ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR) && + err == WC_NO_ERR_TRACE(WOLFSSL_ERROR_WANT_WRITE)); + return ret; +} +static int test_tls13_connect_until_write_ok(WOLFSSL* ssl) +{ + int ret, err; + int tries = 5; + + err = 0; + do { + ret = wolfSSL_connect(ssl); + if (ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) { + err = wolfSSL_get_error(ssl, ret); + } + } while (tries-- && ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR) && + err == WC_NO_ERR_TRACE(WOLFSSL_ERROR_WANT_WRITE)); + return ret; +} +static int test_tls13_write_until_write_ok(WOLFSSL* ssl, const void* msg, + int msgLen) +{ + int ret, err; + int tries = 5; + + err = 0; + do { + ret = wolfSSL_write(ssl, msg, msgLen); + if (ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) { + err = wolfSSL_get_error(ssl, ret); + } + } while (tries-- && ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR) && + err == WC_NO_ERR_TRACE(WOLFSSL_ERROR_WANT_WRITE)); + return ret; +} +static int test_tls13_early_data_read_until_write_ok(WOLFSSL* ssl, void* buf, + int bufLen, int* read) +{ + int ret, err; + int tries = 5; + + err = 0; + do { + ret = wolfSSL_read_early_data(ssl, buf, bufLen, read); + if (ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) { + err = wolfSSL_get_error(ssl, ret); + } + } while (tries-- && ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR) && + err == WC_NO_ERR_TRACE(WOLFSSL_ERROR_WANT_WRITE)); + return ret; +} +static int test_tls13_early_data_write_until_write_ok(WOLFSSL* ssl, + const void* msg, int msgLen, int* written) +{ + int ret, err; + int tries = 5; + + err = 0; + do { + ret = wolfSSL_write_early_data(ssl, msg, msgLen, written); + if (ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) { + err = wolfSSL_get_error(ssl, ret); + } + } while (tries-- && ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR) && + err == WC_NO_ERR_TRACE(WOLFSSL_ERROR_WANT_WRITE)); + return ret; +} +struct test_tls13_wwrite_ctx { + int want_write; + struct test_memio_ctx *test_ctx; +}; +static int test_tls13_mock_wantwrite_cb(WOLFSSL* ssl, char* data, int sz, + void* ctx) +{ + struct test_tls13_wwrite_ctx *wwctx = (struct test_tls13_wwrite_ctx *)ctx; + wwctx->want_write = !wwctx->want_write; + if (wwctx->want_write) { + return WOLFSSL_CBIO_ERR_WANT_WRITE; + } + return test_memio_write_cb(ssl, data, sz, wwctx->test_ctx); +} +#endif /* HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES && WOLFSSL_EARLY_DATA */ int test_tls13_early_data(void) { EXPECT_DECLS; @@ -2000,7 +2095,6 @@ int test_tls13_early_data(void) int written = 0; int read = 0; size_t i; - int splitEarlyData; char msg[] = "This is early data"; char msg2[] = "This is client data"; char msg3[] = "This is server data"; @@ -2011,164 +2105,207 @@ int test_tls13_early_data(void) method_provider server_meth; const char* tls_version; int isUdp; + int splitEarlyData; + int everyWriteWantWrite; } params[] = { #ifdef WOLFSSL_TLS13 { wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, - "TLS 1.3", 0 }, + "TLS 1.3", 0, 0, 0 }, + { wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, + "TLS 1.3", 0, 1, 0 }, + { wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, + "TLS 1.3", 0, 0, 1 }, + { wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, + "TLS 1.3", 0, 1, 1 }, #endif #ifdef WOLFSSL_DTLS13 { wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, - "DTLS 1.3", 1 }, + "DTLS 1.3", 1, 0, 0 }, + { wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, + "DTLS 1.3", 1, 1, 0 }, + { wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, + "DTLS 1.3", 1, 0, 1 }, + { wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, + "DTLS 1.3", 1, 1, 1 }, #endif }; for (i = 0; i < sizeof(params)/sizeof(*params) && !EXPECT_FAIL(); i++) { - for (splitEarlyData = 0; splitEarlyData < 2; splitEarlyData++) { - struct test_memio_ctx test_ctx; - WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; - WOLFSSL *ssl_c = NULL, *ssl_s = NULL; - WOLFSSL_SESSION *sess = NULL; - - XMEMSET(&test_ctx, 0, sizeof(test_ctx)); - - fprintf(stderr, "\tEarly data with %s\n", params[i].tls_version); - - ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, - &ssl_s, params[i].client_meth, params[i].server_meth), 0); - - /* Get a ticket so that we can do 0-RTT on the next connection */ - ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); - /* Make sure we read the ticket */ - ExpectIntEQ(wolfSSL_read(ssl_c, msgBuf, sizeof(msgBuf)), -1); - ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); - ExpectNotNull(sess = wolfSSL_get1_session(ssl_c)); - - wolfSSL_free(ssl_c); - ssl_c = NULL; - wolfSSL_free(ssl_s); - ssl_s = NULL; - XMEMSET(&test_ctx, 0, sizeof(test_ctx)); - ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, + struct test_memio_ctx test_ctx; + WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; + WOLFSSL *ssl_c = NULL, *ssl_s = NULL; + WOLFSSL_SESSION *sess = NULL; + int splitEarlyData = params[i].splitEarlyData; + int everyWriteWantWrite = params[i].everyWriteWantWrite; + struct test_tls13_wwrite_ctx wwrite_ctx_s, wwrite_ctx_c; + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + XMEMSET(&wwrite_ctx_c, 0, sizeof(wwrite_ctx_c)); + XMEMSET(&wwrite_ctx_s, 0, sizeof(wwrite_ctx_s)); + + fprintf(stderr, "\tEarly data with %s%s%s\n", params[i].tls_version, + splitEarlyData ? " (split early data)" : "", + everyWriteWantWrite ? " (every write WANT_WRITE)" : ""); + + ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, params[i].client_meth, params[i].server_meth), 0); - wolfSSL_SetLoggingPrefix("client"); - ExpectIntEQ(wolfSSL_set_session(ssl_c, sess), WOLFSSL_SUCCESS); + + /* Get a ticket so that we can do 0-RTT on the next connection */ + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + /* Make sure we read the ticket */ + ExpectIntEQ(wolfSSL_read(ssl_c, msgBuf, sizeof(msgBuf)), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); + ExpectNotNull(sess = wolfSSL_get1_session(ssl_c)); + + wolfSSL_free(ssl_c); + ssl_c = NULL; + wolfSSL_free(ssl_s); + ssl_s = NULL; + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, + &ssl_s, params[i].client_meth, params[i].server_meth), 0); + wolfSSL_SetLoggingPrefix("client"); + ExpectIntEQ(wolfSSL_set_session(ssl_c, sess), WOLFSSL_SUCCESS); #ifdef WOLFSSL_DTLS13 - if (params[i].isUdp) { - wolfSSL_SetLoggingPrefix("server"); + if (params[i].isUdp) { + wolfSSL_SetLoggingPrefix("server"); #ifdef WOLFSSL_DTLS13_NO_HRR_ON_RESUME - ExpectIntEQ(wolfSSL_dtls13_no_hrr_on_resume(ssl_s, 1), - WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_dtls13_no_hrr_on_resume(ssl_s, 1), + WOLFSSL_SUCCESS); #else - /* Let's test this but we generally don't recommend turning off - * the cookie exchange */ - ExpectIntEQ(wolfSSL_disable_hrr_cookie(ssl_s), WOLFSSL_SUCCESS); + /* Let's test this but we generally don't recommend turning off + * the cookie exchange */ + ExpectIntEQ(wolfSSL_disable_hrr_cookie(ssl_s), WOLFSSL_SUCCESS); #endif - } + } #endif - /* Test 0-RTT data */ - wolfSSL_SetLoggingPrefix("client"); - ExpectIntEQ(wolfSSL_write_early_data(ssl_c, msg, sizeof(msg), - &written), sizeof(msg)); + if (everyWriteWantWrite) { + wwrite_ctx_c.test_ctx = &test_ctx; + wwrite_ctx_s.test_ctx = &test_ctx; + wolfSSL_SetIOWriteCtx(ssl_c, &wwrite_ctx_c); + wolfSSL_SSLSetIOSend(ssl_c, test_tls13_mock_wantwrite_cb); + wolfSSL_SetIOWriteCtx(ssl_s, &wwrite_ctx_s); + wolfSSL_SSLSetIOSend(ssl_s, test_tls13_mock_wantwrite_cb); + } + /* Test 0-RTT data */ + wolfSSL_SetLoggingPrefix("client"); + + ExpectIntEQ(test_tls13_early_data_write_until_write_ok(ssl_c, msg, + sizeof(msg), &written), + sizeof(msg)); + ExpectIntEQ(written, sizeof(msg)); + + if (splitEarlyData) { + ExpectIntEQ(test_tls13_early_data_write_until_write_ok(ssl_c, msg, + sizeof(msg), &written), + sizeof(msg)); ExpectIntEQ(written, sizeof(msg)); + } - if (splitEarlyData) { - ExpectIntEQ(wolfSSL_write_early_data(ssl_c, msg, sizeof(msg), - &written), sizeof(msg)); - ExpectIntEQ(written, sizeof(msg)); - } - - /* Read first 0-RTT data (if split otherwise entire data) */ - wolfSSL_SetLoggingPrefix("server"); - ExpectIntEQ(wolfSSL_read_early_data(ssl_s, msgBuf, sizeof(msgBuf), - &read), sizeof(msg)); + /* Read first 0-RTT data (if split otherwise entire data) */ + wolfSSL_SetLoggingPrefix("server"); + ExpectIntEQ(test_tls13_early_data_read_until_write_ok(ssl_s, msgBuf, + sizeof(msgBuf), &read), + sizeof(msg)); + ExpectIntEQ(read, sizeof(msg)); + ExpectStrEQ(msg, msgBuf); + + /* Test 0.5-RTT data */ + ExpectIntEQ(test_tls13_write_until_write_ok(ssl_s, msg4, sizeof(msg4)), + sizeof(msg4)); + + if (splitEarlyData) { + /* Read second 0-RTT data */ + ExpectIntEQ(test_tls13_early_data_read_until_write_ok(ssl_s, msgBuf, + sizeof(msgBuf), &read), + sizeof(msg)); ExpectIntEQ(read, sizeof(msg)); ExpectStrEQ(msg, msgBuf); + } - /* Test 0.5-RTT data */ - ExpectIntEQ(wolfSSL_write(ssl_s, msg4, sizeof(msg4)), sizeof(msg4)); - - if (splitEarlyData) { - /* Read second 0-RTT data */ - ExpectIntEQ(wolfSSL_read_early_data(ssl_s, msgBuf, - sizeof(msgBuf), &read), sizeof(msg)); - ExpectIntEQ(read, sizeof(msg)); - ExpectStrEQ(msg, msgBuf); - } - - if (params[i].isUdp) { - wolfSSL_SetLoggingPrefix("client"); - ExpectIntEQ(wolfSSL_connect(ssl_c), -1); - ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), - WC_NO_ERR_TRACE(APP_DATA_READY)); - - /* Read server 0.5-RTT data */ - ExpectIntEQ(wolfSSL_read(ssl_c, msgBuf, sizeof(msgBuf)), - sizeof(msg4)); - ExpectStrEQ(msg4, msgBuf); - - /* Complete handshake */ - ExpectIntEQ(wolfSSL_connect(ssl_c), -1); - ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), - WOLFSSL_ERROR_WANT_READ); - /* Use wolfSSL_is_init_finished to check if handshake is - * complete. Normally a user would loop until it is true but - * here we control both sides so we just assert the expected - * value. wolfSSL_read_early_data does not provide handshake - * status to us with non-blocking IO and we can't use - * wolfSSL_accept as TLS layer may return ZERO_RETURN due to - * early data parsing logic. */ - wolfSSL_SetLoggingPrefix("server"); - ExpectFalse(wolfSSL_is_init_finished(ssl_s)); - ExpectIntEQ(wolfSSL_read_early_data(ssl_s, msgBuf, - sizeof(msgBuf), &read), 0); - ExpectIntEQ(read, 0); - ExpectTrue(wolfSSL_is_init_finished(ssl_s)); - - wolfSSL_SetLoggingPrefix("client"); - ExpectIntEQ(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS); - } - else { - wolfSSL_SetLoggingPrefix("client"); - ExpectIntEQ(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS); - - wolfSSL_SetLoggingPrefix("server"); - ExpectFalse(wolfSSL_is_init_finished(ssl_s)); - ExpectIntEQ(wolfSSL_read_early_data(ssl_s, msgBuf, - sizeof(msgBuf), &read), 0); - ExpectIntEQ(read, 0); - ExpectTrue(wolfSSL_is_init_finished(ssl_s)); - - /* Read server 0.5-RTT data */ - wolfSSL_SetLoggingPrefix("client"); - ExpectIntEQ(wolfSSL_read(ssl_c, msgBuf, sizeof(msgBuf)), - sizeof(msg4)); - ExpectStrEQ(msg4, msgBuf); - } + if (params[i].isUdp) { + wolfSSL_SetLoggingPrefix("client"); + ExpectIntEQ(test_tls13_connect_until_write_ok(ssl_c), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), + WC_NO_ERR_TRACE(APP_DATA_READY)); + + /* Read server 0.5-RTT data */ + ExpectIntEQ( + test_tls13_read_until_write_ok(ssl_c, msgBuf, sizeof(msgBuf)), + sizeof(msg4)); + ExpectStrEQ(msg4, msgBuf); + + /* Complete handshake */ + ExpectIntEQ(test_tls13_connect_until_write_ok(ssl_c), -1); + ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), + WOLFSSL_ERROR_WANT_READ); + /* Use wolfSSL_is_init_finished to check if handshake is + * complete. Normally a user would loop until it is true but + * here we control both sides so we just assert the expected + * value. wolfSSL_read_early_data does not provide handshake + * status to us with non-blocking IO and we can't use + * wolfSSL_accept as TLS layer may return ZERO_RETURN due to + * early data parsing logic. */ + wolfSSL_SetLoggingPrefix("server"); + ExpectFalse(wolfSSL_is_init_finished(ssl_s)); + ExpectIntEQ(test_tls13_early_data_read_until_write_ok(ssl_s, msgBuf, + sizeof(msgBuf), &read), + 0); + ExpectIntEQ(read, 0); + ExpectTrue(wolfSSL_is_init_finished(ssl_s)); - /* Test bi-directional write */ wolfSSL_SetLoggingPrefix("client"); - ExpectIntEQ(wolfSSL_write(ssl_c, msg2, sizeof(msg2)), sizeof(msg2)); + ExpectIntEQ(test_tls13_connect_until_write_ok(ssl_c), + WOLFSSL_SUCCESS); + } + else { + wolfSSL_SetLoggingPrefix("client"); + ExpectIntEQ(test_tls13_connect_until_write_ok(ssl_c), + WOLFSSL_SUCCESS); + wolfSSL_SetLoggingPrefix("server"); - ExpectIntEQ(wolfSSL_read(ssl_s, msgBuf, sizeof(msgBuf)), - sizeof(msg2)); - ExpectStrEQ(msg2, msgBuf); - ExpectIntEQ(wolfSSL_write(ssl_s, msg3, sizeof(msg3)), sizeof(msg3)); + ExpectFalse(wolfSSL_is_init_finished(ssl_s)); + ExpectIntEQ(test_tls13_early_data_read_until_write_ok(ssl_s, msgBuf, + sizeof(msgBuf), &read), + 0); + ExpectIntEQ(read, 0); + ExpectTrue(wolfSSL_is_init_finished(ssl_s)); + + /* Read server 0.5-RTT data */ wolfSSL_SetLoggingPrefix("client"); - ExpectIntEQ(wolfSSL_read(ssl_c, msgBuf, sizeof(msgBuf)), - sizeof(msg3)); - ExpectStrEQ(msg3, msgBuf); - - wolfSSL_SetLoggingPrefix(NULL); - ExpectTrue(wolfSSL_session_reused(ssl_c)); - ExpectTrue(wolfSSL_session_reused(ssl_s)); - - wolfSSL_SESSION_free(sess); - wolfSSL_free(ssl_c); - wolfSSL_free(ssl_s); - wolfSSL_CTX_free(ctx_c); - wolfSSL_CTX_free(ctx_s); + ExpectIntEQ( + test_tls13_read_until_write_ok(ssl_c, msgBuf, sizeof(msgBuf)), + sizeof(msg4)); + ExpectStrEQ(msg4, msgBuf); } + + /* Test bi-directional write */ + wolfSSL_SetLoggingPrefix("client"); + ExpectIntEQ(test_tls13_write_until_write_ok(ssl_c, msg2, sizeof(msg2)), + sizeof(msg2)); + wolfSSL_SetLoggingPrefix("server"); + ExpectIntEQ( + test_tls13_read_until_write_ok(ssl_s, msgBuf, sizeof(msgBuf)), + sizeof(msg2)); + ExpectStrEQ(msg2, msgBuf); + ExpectIntEQ(test_tls13_write_until_write_ok(ssl_s, msg3, sizeof(msg3)), + sizeof(msg3)); + wolfSSL_SetLoggingPrefix("client"); + ExpectIntEQ( + test_tls13_read_until_write_ok(ssl_c, msgBuf, sizeof(msgBuf)), + sizeof(msg3)); + ExpectStrEQ(msg3, msgBuf); + + wolfSSL_SetLoggingPrefix(NULL); + ExpectTrue(wolfSSL_session_reused(ssl_c)); + ExpectTrue(wolfSSL_session_reused(ssl_s)); + + wolfSSL_SESSION_free(sess); + wolfSSL_free(ssl_c); + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_c); + wolfSSL_CTX_free(ctx_s); } #endif return EXPECT_RESULT(); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index c975865caf..9401970ee3 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -7240,6 +7240,8 @@ WOLFSSL_LOCAL int pkcs8_encrypt(WOLFSSL_EVP_PKEY* pkey, word32* keySz); #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ +WOLFSSL_LOCAL void wolfssl_local_MaybeCheckAlertOnErr(WOLFSSL* ssl, int err); + #ifdef __cplusplus } /* extern "C" */ #endif