diff --git a/src/quic.c b/src/quic.c index 1ff468f74..c56fbfecd 100644 --- a/src/quic.c +++ b/src/quic.c @@ -273,6 +273,7 @@ void wolfSSL_quic_clear(WOLFSSL* ssl) } ssl->quic.enc_level_write = wolfssl_encryption_initial; ssl->quic.enc_level_latest_recvd = wolfssl_encryption_initial; + ssl->quic.early_data_enabled = 0; while ((qd = ssl->quic.input_head)) { ssl->quic.input_head = qd->next; @@ -545,11 +546,11 @@ void wolfSSL_set_quic_early_data_enabled(WOLFSSL* ssl, int enabled) else if (ssl->options.handShakeState != NULL_STATE) { WOLFSSL_MSG("wolfSSL_set_quic_early_data_enabled: handshake started"); } - else if (ssl->options.side == WOLFSSL_CLIENT_END) { - WOLFSSL_MSG("wolfSSL_set_quic_early_data_enabled: on client side"); - } else { - wolfSSL_set_max_early_data(ssl, enabled ? UINT32_MAX : 0); + ssl->quic.early_data_enabled = enabled; + if (ssl->options.side != WOLFSSL_CLIENT_END) { + wolfSSL_set_max_early_data(ssl, enabled ? UINT32_MAX : 0); + } } } #endif /* WOLFSSL_EARLY_DATA */ @@ -576,19 +577,52 @@ int wolfSSL_quic_do_handshake(WOLFSSL* ssl) * and the client Finished arrives. * This confuses the QUIC state handling. */ +#ifdef WOLFSSL_EARLY_DATA + if (ssl->quic.early_data_enabled) { + byte buffer[256]; + int len; + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ssl->options.resuming) { + ret = wolfSSL_write_early_data(ssl, buffer, 0, &len); + } + } + else if (/*disables code*/(1)) { + ret = wolfSSL_read_early_data(ssl, buffer, + sizeof(buffer), &len); + if (ret < 0 && ssl->error == ZERO_RETURN) { + /* this is expected, since QUIC handles the actual early + * data separately. */ + ret = WOLFSSL_SUCCESS; + } + } + if (ret < 0) { + goto cleanup; + } + } +#endif /* WOLFSSL_EARLY_DATA */ + ret = wolfSSL_SSL_do_handshake(ssl); - if (ret != WOLFSSL_SUCCESS) + if (ret <= 0) goto cleanup; } cleanup: + if (ret <= 0 + && ssl->options.handShakeState == HANDSHAKE_DONE + && (ssl->error == ZERO_RETURN || ssl->error == WANT_READ)) { + ret = WOLFSSL_SUCCESS; + } + if (ret == WOLFSSL_SUCCESS) { + ssl->error = WOLFSSL_ERROR_NONE; + } WOLFSSL_LEAVE("wolfSSL_quic_do_handshake", ret); return ret; } int wolfSSL_quic_read_write(WOLFSSL* ssl) { - int ret = WOLFSSL_SUCCESS, nret; + int ret = WOLFSSL_SUCCESS; WOLFSSL_ENTER("wolfSSL_quic_read_write"); @@ -604,16 +638,7 @@ int wolfSSL_quic_read_write(WOLFSSL* ssl) goto cleanup; } - while (ssl->quic.input_head != NULL - || ssl->buffers.inputBuffer.length > 0) { - if ((nret = ProcessReply(ssl)) < 0) { - ret = nret; - goto cleanup; - } - } - while (ssl->buffers.outputBuffer.length > 0) { - SendBuffered(ssl); - } + ret = wolfSSL_process_quic_post_handshake(ssl); cleanup: WOLFSSL_LEAVE("wolfSSL_quic_read_write", ret); @@ -634,8 +659,6 @@ int wolfSSL_process_quic_post_handshake(WOLFSSL* ssl) if (ssl->options.handShakeState != HANDSHAKE_DONE) { WOLFSSL_MSG("WOLFSSL_QUIC_POST_HS handshake is not done yet"); - fprintf(stderr, "WOLFSSL_QUIC_POST_HS, handShakeState is %d\n", - ssl->options.handShakeState); ret = WOLFSSL_FAILURE; goto cleanup; } @@ -644,7 +667,7 @@ int wolfSSL_process_quic_post_handshake(WOLFSSL* ssl) || ssl->buffers.inputBuffer.length > 0) { if ((nret = ProcessReply(ssl)) < 0) { ret = nret; - goto cleanup; + break; } } while (ssl->buffers.outputBuffer.length > 0) { diff --git a/src/tls13.c b/src/tls13.c index ea98ba57f..09c311dea 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -8065,7 +8065,7 @@ int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* WOLFSSL_DTLS13 && WOLFSSL_EARLY_DATA */ #if defined(WOLFSSL_QUIC) && defined(WOLFSSL_EARLY_DATA) if (WOLFSSL_IS_QUIC(ssl) && ssl->earlyData > early_data_ext) { - /* QUIC has no EndOfearlydata messages. We stop processing EarlyData + /* QUIC has no EndOfEarlyData messages. We stop processing EarlyData as soon we receive the client's finished message */ ssl->earlyData = done_early_data; } diff --git a/tests/quic.c b/tests/quic.c index d47f1f63e..1e4b160d4 100644 --- a/tests/quic.c +++ b/tests/quic.c @@ -999,12 +999,7 @@ static void QuicConversation_do(QuicConversation *conv) if (!QuicConversation_step(conv)) { int c_err = wolfSSL_get_error(conv->client->ssl, 0); int s_err = wolfSSL_get_error(conv->server->ssl, 0); - if (c_err == 0 - && (s_err == 0 - || (conv->sent_early_data && s_err == SSL_ERROR_WANT_READ))) { - /* Since QUIC does not use EndOfEarlyData messages, we may - * encounter WANT_READ on the server side. QUIC protocol stacks - * detect EOF here differently, so this should be fine. */ + if (c_err == 0 && s_err == 0) { break; /* handshake done */ } printf("Neither tclient nor server have anything to send, " @@ -1237,12 +1232,11 @@ static int test_quic_early_data(int verbose) { AssertIntEQ(wolfSSL_set_session(tclient.ssl, session), WOLFSSL_SUCCESS); /* enable early data -*/ wolfSSL_set_quic_early_data_enabled(tserver.ssl, 1); - /* client will send, but server will not receive, since - * QuicConversation_do() uses wolfSSL_accept() */ + /* client will send, and server will receive implicitly */ QuicConversation_init(&conv, &tclient, &tserver); QuicConversation_start(&conv, early_data, sizeof(early_data), &ed_written); QuicConversation_do(&conv); - AssertIntEQ(wolfSSL_get_early_data_status(tclient.ssl), WOLFSSL_EARLY_DATA_REJECTED); + AssertIntEQ(wolfSSL_get_early_data_status(tclient.ssl), WOLFSSL_EARLY_DATA_ACCEPTED); QuicTestContext_free(&tclient); QuicTestContext_free(&tserver); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index e8119c698..43c24583e 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -4981,6 +4981,7 @@ struct WOLFSSL { WOLFSSL_ENCRYPTION_LEVEL enc_level_write; WOLFSSL_ENCRYPTION_LEVEL enc_level_write_next; int transport_version; + int early_data_enabled; const QuicTransportParam* transport_local; const QuicTransportParam* transport_peer; const QuicTransportParam* transport_peer_draft;