QUIC session resumption and early data handshake handling.

In test with ngtcp2 example client using openssl, session resumption
against a QUIC wolfssl server failed. The error was tracked down to
wolfSSL believing EaryData needs to be handled and returning SUCCESS
from wolfSSL_SSL_do_handshake() after the server Finished had been
sent.

However the handshake was not complete and ngtcp2 invoked the
post_handshake processing for new data arriving from the client.
This failed a check in post processing that the ssl->handShakeState
actually was HANDSHAKE_DONE.

The workaround in this PR repeats do_handshake until the ssl
state acually says it is complete. This way, session resumption works.

Either this alternative do_handshake() is merged for QUIC protocol
hanlders. Or we need to fix the 'normal' do_handshake() to no return
SUCCESS when early data is expected on a QUIC WOLFSSL.
This commit is contained in:
Stefan Eissing
2022-08-10 15:17:30 +02:00
parent eceee6ac95
commit ea04ffc99f
3 changed files with 44 additions and 1 deletions

View File

@ -554,6 +554,37 @@ void wolfSSL_set_quic_early_data_enabled(WOLFSSL* ssl, int enabled)
}
#endif /* WOLFSSL_EARLY_DATA */
int wolfSSL_quic_do_handshake(WOLFSSL* ssl)
{
int ret = WOLFSSL_SUCCESS;
WOLFSSL_ENTER("wolfSSL_quic_do_handshake");
if (!wolfSSL_is_quic(ssl)) {
WOLFSSL_MSG("WOLFSSL_QUIC_DO_HANDSHAKE not a QUIC SSL");
ret = WOLFSSL_FAILURE;
goto cleanup;
}
while (ssl->options.handShakeState != HANDSHAKE_DONE) {
/* Peculiar: do_handshake() is successful, but the state
* indicates that we are not DONE. This seems to happen
* when resuming sessions and an EARLY_DATA indicator
* is presented by the client.
* Theory: wolfSSL expects the APP to read the early data
* and silently continues the handshake when the EndOfEarlyData
* and the client Finished arrives.
* This confuses the QUIC state handling.
*/
ret = wolfSSL_SSL_do_handshake(ssl);
if (ret != WOLFSSL_SUCCESS)
goto cleanup;
}
cleanup:
WOLFSSL_LEAVE("wolfSSL_quic_do_handshake", ret);
return ret;
}
int wolfSSL_quic_read_write(WOLFSSL* ssl)
{
@ -568,7 +599,7 @@ int wolfSSL_quic_read_write(WOLFSSL* ssl)
}
if (ssl->options.handShakeState != HANDSHAKE_DONE) {
ret = wolfSSL_SSL_do_handshake(ssl);
ret = wolfSSL_quic_do_handshake(ssl);
if (ret != WOLFSSL_SUCCESS)
goto cleanup;
}
@ -603,6 +634,8 @@ 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;
}

View File

@ -8063,6 +8063,13 @@ int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
ssl->earlyData = done_early_data;
}
#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
as soon we receive the client's finished message */
ssl->earlyData = done_early_data;
}
#endif /* WOLFSSL_QUIC && WOLFSSL_EARLY_DATA */
WOLFSSL_LEAVE("DoTls13Finished", 0);
WOLFSSL_END(WC_FUNC_FINISHED_DO);

View File

@ -189,6 +189,9 @@ WOLFSSL_API
int wolfSSL_provide_quic_data(WOLFSSL* ssl, WOLFSSL_ENCRYPTION_LEVEL level,
const uint8_t* data, size_t len);
WOLFSSL_API
int wolfSSL_quic_do_handshake(WOLFSSL* ssl);
/**
* Process any CRYPTO data added post-handshake.
*/