Merge pull request #6929 from julek-wolfssl/dtls13-early-data-server-side

dtls 1.3: allow to skip cookie exchange on resumption
This commit is contained in:
JacobBarthelmeh
2023-11-06 13:30:21 -07:00
committed by GitHub
11 changed files with 188 additions and 75 deletions

View File

@@ -21,11 +21,13 @@
/*
* WOLFSSL_DTLS_NO_HVR_ON_RESUME
* WOLFSSL_DTLS13_NO_HRR_ON_RESUME
* If defined, a DTLS server will not do a cookie exchange on successful
* client resumption: the resumption will be faster (one RTT less) and
* will consume less bandwidth (one ClientHello and one HelloVerifyRequest
* less). On the other hand, if a valid SessionID is collected, forged
* clientHello messages will consume resources on the server.
* will consume less bandwidth (one ClientHello and one
* HelloVerifyRequest/HelloRetryRequest less). On the other hand, if a valid
* SessionID/ticket/psk is collected, forged clientHello messages will
* consume resources on the server.
* WOLFSSL_DTLS_CH_FRAG
* Allow a server to process a fragmented second/verified (one containing a
* valid cookie response) ClientHello message. The first/unverified (one
@@ -769,6 +771,15 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch)
}
}
#ifdef WOLFSSL_DTLS13_NO_HRR_ON_RESUME
if (ssl->options.dtls13NoHrrOnResume && usePSK && pskInfo.isValid &&
!cs.doHelloRetry) {
/* Skip HRR on resumption */
((WOLFSSL*)ssl)->options.dtlsStateful = 1;
goto dtls13_cleanup;
}
#endif
#ifdef HAVE_SUPPORTED_CURVES
if (cs.doHelloRetry) {
ret = TLSX_KeyShare_SetSupported(ssl, &parsedExts);
@@ -949,7 +960,7 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, word32 helloSz,
ret = COOKIE_ERROR;
else
#endif
ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13);
ret = SendStatelessReply(ssl, &ch, isTls13);
}
else {
byte cookieGood;
@@ -970,7 +981,7 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, word32 helloSz,
ret = COOKIE_ERROR;
else
#endif
ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13);
ret = SendStatelessReply(ssl, &ch, isTls13);
}
else {
ssl->options.dtlsStateful = 1;

View File

@@ -2844,5 +2844,15 @@ int wolfSSL_dtls13_allow_ch_frag(WOLFSSL *ssl, int enabled)
}
#endif
#ifdef WOLFSSL_DTLS13_NO_HRR_ON_RESUME
int wolfSSL_dtls13_no_hrr_on_resume(WOLFSSL *ssl, int enabled)
{
if (ssl->options.side == WOLFSSL_CLIENT_END) {
return WOLFSSL_FAILURE;
}
ssl->options.dtls13NoHrrOnResume = !!enabled;
return WOLFSSL_SUCCESS;
}
#endif
#endif /* WOLFSSL_DTLS13 */

View File

@@ -20185,20 +20185,8 @@ static int DtlsShouldDrop(WOLFSSL* ssl, int retcode)
#ifndef NO_WOLFSSL_SERVER
if (ssl->options.side == WOLFSSL_SERVER_END
&& ssl->curRL.type != handshake && !IsSCR(ssl)) {
int beforeCookieVerified = 0;
if (!IsAtLeastTLSv1_3(ssl->version)) {
beforeCookieVerified =
ssl->options.acceptState < ACCEPT_FIRST_REPLY_DONE;
}
#ifdef WOLFSSL_DTLS13
else {
beforeCookieVerified =
ssl->options.acceptState < TLS13_ACCEPT_SECOND_REPLY_DONE;
}
#endif /* WOLFSSL_DTLS13 */
if (beforeCookieVerified) {
WOLFSSL_MSG("Drop non-handshake record before handshake");
if (!ssl->options.dtlsStateful) {
WOLFSSL_MSG("Drop non-handshake record when not stateful");
return 1;
}
}
@@ -34441,6 +34429,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
if (cs.doHelloRetry) {
/* Make sure we don't send HRR twice */
if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE)
return INVALID_PARAMETER;
ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
return TLSX_KeyShare_SetSupported(ssl, &ssl->extensions);
}

View File

@@ -16793,11 +16793,13 @@ cleanup:
#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || WOLFSSL_WPAS_SMALL */
/* return true if connection established */
int wolfSSL_is_init_finished(WOLFSSL* ssl)
int wolfSSL_is_init_finished(const WOLFSSL* ssl)
{
if (ssl == NULL)
return 0;
/* Can't use ssl->options.connectState and ssl->options.acceptState because
* they differ in meaning for TLS <=1.2 and 1.3 */
if (ssl->options.handShakeState == HANDSHAKE_DONE)
return 1;
@@ -31970,12 +31972,7 @@ int wolfSSL_SSL_in_init(WOLFSSL *ssl)
{
WOLFSSL_ENTER("wolfSSL_SSL_in_init");
if (ssl == NULL)
return WOLFSSL_FAILURE;
/* Can't use ssl->options.connectState and ssl->options.acceptState because
* they differ in meaning for TLS <=1.2 and 1.3 */
return ssl->options.handShakeState != HANDSHAKE_DONE;
return !wolfSSL_is_init_finished(ssl);
}
int wolfSSL_SSL_in_connect_init(WOLFSSL* ssl)

View File

@@ -6204,6 +6204,8 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz,
if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
return ret;
ssl->keys.encryptionOn = 1;
#ifdef WOLFSSL_DTLS13
if (ssl->options.dtls) {
ret = Dtls13NewEpoch(ssl,
@@ -6916,7 +6918,11 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
}
}
else {
ERROR_OUT(HRR_COOKIE_ERROR, exit_dch);
#if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_DTLS13_NO_HRR_ON_RESUME)
/* Don't error out as we may be resuming. We confirm this later. */
if (!ssl->options.dtls)
#endif
ERROR_OUT(HRR_COOKIE_ERROR, exit_dch);
}
}
#endif
@@ -6982,7 +6988,6 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
goto exit_dch;
}
}
else
#endif
#ifdef HAVE_SUPPORTED_CURVES
if (args->usingPSK == 2) {
@@ -6990,6 +6995,9 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
int doHelloRetry = 0;
ret = TLSX_KeyShare_Establish(ssl, &doHelloRetry);
if (doHelloRetry) {
/* Make sure we don't send HRR twice */
if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE)
ERROR_OUT(INVALID_PARAMETER, exit_dch);
ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
if (ret != WC_PENDING_E)
ret = 0; /* for hello_retry return 0 */
@@ -7082,32 +7090,58 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
ret = INPUT_CASE_ERROR;
} /* switch (ssl->options.asyncState) */
#if defined(WOLFSSL_SEND_HRR_COOKIE)
if (ret == 0 && ssl->options.sendCookie && ssl->options.cookieGood &&
(ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE
#ifdef WOLFSSL_DTLS13
/* DTLS cookie exchange should be done in stateless code in
* DoClientHelloStateless. If we verified the cookie then
* always advance the state. */
|| ssl->options.dtls
#endif
))
ssl->options.serverState = SERVER_HELLO_COMPLETE;
#endif
#ifdef WOLFSSL_SEND_HRR_COOKIE
if (ret == 0 && ssl->options.sendCookie) {
if (ssl->options.cookieGood &&
ssl->options.acceptState == TLS13_ACCEPT_FIRST_REPLY_DONE) {
/* Processing second ClientHello. Clear HRR state. */
ssl->options.serverState = NULL_STATE;
}
#if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE)
if (ret == 0 && ssl->options.dtls && ssl->options.sendCookie &&
ssl->options.serverState <= SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
/* Cookie and key share negotiation should be handled in
* DoClientHelloStateless. If we enter here then something went wrong
* in our logic. */
ERROR_OUT(BAD_HELLO, exit_dch);
if (ssl->options.cookieGood &&
ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
/* If we already verified the peer with a cookie then we can't
* do another HRR for cipher negotiation. Send alert and restart
* the entire handshake. */
ERROR_OUT(INVALID_PARAMETER, exit_dch);
}
#ifdef WOLFSSL_DTLS13
if (ssl->options.dtls &&
ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
/* Cookie and key share negotiation should be handled in
* DoClientHelloStateless. If we enter here then something went
* wrong in our logic. */
ERROR_OUT(BAD_HELLO, exit_dch);
}
#endif
/* Send a cookie */
if (!ssl->options.cookieGood &&
ssl->options.serverState != SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
#ifdef WOLFSSL_DTLS13
if (ssl->options.dtls) {
#ifdef WOLFSSL_DTLS13_NO_HRR_ON_RESUME
/* We can skip cookie on resumption */
if (!ssl->options.dtls || !ssl->options.dtls13NoHrrOnResume ||
!args->usingPSK)
#endif
ERROR_OUT(BAD_HELLO, exit_dch);
}
else
#endif
{
/* Need to remove the keyshare ext if we found a common group
* and are not doing curve negotiation. */
TLSX_Remove(&ssl->extensions, TLSX_KEY_SHARE, ssl->heap);
ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
}
}
}
#endif /* WOLFSSL_DTLS13 */
#ifdef WOLFSSL_DTLS_CID
/* do not modify CID state if we are sending an HRR */
if (ssl->options.useDtlsCID &&
if (ret == 0 && ssl->options.dtls && ssl->options.useDtlsCID &&
ssl->options.serverState != SERVER_HELLO_RETRY_REQUEST_COMPLETE)
DtlsCIDOnExtensionsParsed(ssl);
#endif /* WOLFSSL_DTLS_CID */