mirror of https://github.com/wolfSSL/wolfssl.git
QUIC fixes for handling of early data
- new internal field for keeping early data enabled status, as QUIC does not call SSL_write_early_data() itself. - using read_/write_early_data() methods in QUIC handshake when early data is enabled. This triggers the internals that emit the proper early data indication handlings.pull/5458/head
parent
dd2a6410d1
commit
53fd4b37f2
61
src/quic.c
61
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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
12
tests/quic.c
12
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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue