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_write = wolfssl_encryption_initial;
|
||||||
ssl->quic.enc_level_latest_recvd = wolfssl_encryption_initial;
|
ssl->quic.enc_level_latest_recvd = wolfssl_encryption_initial;
|
||||||
|
ssl->quic.early_data_enabled = 0;
|
||||||
|
|
||||||
while ((qd = ssl->quic.input_head)) {
|
while ((qd = ssl->quic.input_head)) {
|
||||||
ssl->quic.input_head = qd->next;
|
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) {
|
else if (ssl->options.handShakeState != NULL_STATE) {
|
||||||
WOLFSSL_MSG("wolfSSL_set_quic_early_data_enabled: handshake started");
|
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 {
|
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 */
|
#endif /* WOLFSSL_EARLY_DATA */
|
||||||
|
@ -576,19 +577,52 @@ int wolfSSL_quic_do_handshake(WOLFSSL* ssl)
|
||||||
* and the client Finished arrives.
|
* and the client Finished arrives.
|
||||||
* This confuses the QUIC state handling.
|
* 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);
|
ret = wolfSSL_SSL_do_handshake(ssl);
|
||||||
if (ret != WOLFSSL_SUCCESS)
|
if (ret <= 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
WOLFSSL_LEAVE("wolfSSL_quic_do_handshake", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wolfSSL_quic_read_write(WOLFSSL* ssl)
|
int wolfSSL_quic_read_write(WOLFSSL* ssl)
|
||||||
{
|
{
|
||||||
int ret = WOLFSSL_SUCCESS, nret;
|
int ret = WOLFSSL_SUCCESS;
|
||||||
|
|
||||||
WOLFSSL_ENTER("wolfSSL_quic_read_write");
|
WOLFSSL_ENTER("wolfSSL_quic_read_write");
|
||||||
|
|
||||||
|
@ -604,16 +638,7 @@ int wolfSSL_quic_read_write(WOLFSSL* ssl)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ssl->quic.input_head != NULL
|
ret = wolfSSL_process_quic_post_handshake(ssl);
|
||||||
|| ssl->buffers.inputBuffer.length > 0) {
|
|
||||||
if ((nret = ProcessReply(ssl)) < 0) {
|
|
||||||
ret = nret;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (ssl->buffers.outputBuffer.length > 0) {
|
|
||||||
SendBuffered(ssl);
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
WOLFSSL_LEAVE("wolfSSL_quic_read_write", ret);
|
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) {
|
if (ssl->options.handShakeState != HANDSHAKE_DONE) {
|
||||||
WOLFSSL_MSG("WOLFSSL_QUIC_POST_HS handshake is not done yet");
|
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;
|
ret = WOLFSSL_FAILURE;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -644,7 +667,7 @@ int wolfSSL_process_quic_post_handshake(WOLFSSL* ssl)
|
||||||
|| ssl->buffers.inputBuffer.length > 0) {
|
|| ssl->buffers.inputBuffer.length > 0) {
|
||||||
if ((nret = ProcessReply(ssl)) < 0) {
|
if ((nret = ProcessReply(ssl)) < 0) {
|
||||||
ret = nret;
|
ret = nret;
|
||||||
goto cleanup;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (ssl->buffers.outputBuffer.length > 0) {
|
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 */
|
#endif /* WOLFSSL_DTLS13 && WOLFSSL_EARLY_DATA */
|
||||||
#if defined(WOLFSSL_QUIC) && defined(WOLFSSL_EARLY_DATA)
|
#if defined(WOLFSSL_QUIC) && defined(WOLFSSL_EARLY_DATA)
|
||||||
if (WOLFSSL_IS_QUIC(ssl) && ssl->earlyData > early_data_ext) {
|
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 */
|
as soon we receive the client's finished message */
|
||||||
ssl->earlyData = done_early_data;
|
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)) {
|
if (!QuicConversation_step(conv)) {
|
||||||
int c_err = wolfSSL_get_error(conv->client->ssl, 0);
|
int c_err = wolfSSL_get_error(conv->client->ssl, 0);
|
||||||
int s_err = wolfSSL_get_error(conv->server->ssl, 0);
|
int s_err = wolfSSL_get_error(conv->server->ssl, 0);
|
||||||
if (c_err == 0
|
if (c_err == 0 && s_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. */
|
|
||||||
break; /* handshake done */
|
break; /* handshake done */
|
||||||
}
|
}
|
||||||
printf("Neither tclient nor server have anything to send, "
|
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);
|
AssertIntEQ(wolfSSL_set_session(tclient.ssl, session), WOLFSSL_SUCCESS);
|
||||||
/* enable early data -*/
|
/* enable early data -*/
|
||||||
wolfSSL_set_quic_early_data_enabled(tserver.ssl, 1);
|
wolfSSL_set_quic_early_data_enabled(tserver.ssl, 1);
|
||||||
/* client will send, but server will not receive, since
|
/* client will send, and server will receive implicitly */
|
||||||
* QuicConversation_do() uses wolfSSL_accept() */
|
|
||||||
QuicConversation_init(&conv, &tclient, &tserver);
|
QuicConversation_init(&conv, &tclient, &tserver);
|
||||||
QuicConversation_start(&conv, early_data, sizeof(early_data), &ed_written);
|
QuicConversation_start(&conv, early_data, sizeof(early_data), &ed_written);
|
||||||
QuicConversation_do(&conv);
|
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(&tclient);
|
||||||
QuicTestContext_free(&tserver);
|
QuicTestContext_free(&tserver);
|
||||||
|
|
|
@ -4981,6 +4981,7 @@ struct WOLFSSL {
|
||||||
WOLFSSL_ENCRYPTION_LEVEL enc_level_write;
|
WOLFSSL_ENCRYPTION_LEVEL enc_level_write;
|
||||||
WOLFSSL_ENCRYPTION_LEVEL enc_level_write_next;
|
WOLFSSL_ENCRYPTION_LEVEL enc_level_write_next;
|
||||||
int transport_version;
|
int transport_version;
|
||||||
|
int early_data_enabled;
|
||||||
const QuicTransportParam* transport_local;
|
const QuicTransportParam* transport_local;
|
||||||
const QuicTransportParam* transport_peer;
|
const QuicTransportParam* transport_peer;
|
||||||
const QuicTransportParam* transport_peer_draft;
|
const QuicTransportParam* transport_peer_draft;
|
||||||
|
|
Loading…
Reference in New Issue