Skip to content

Commit aed715c

Browse files
committed
dtls 1.3: allow to skip cookie exchange on resumption
tls 1.3: do cookie exchange when asked too even when found a matching cipher
1 parent 37884f8 commit aed715c

11 files changed

Lines changed: 186 additions & 73 deletions

File tree

.github/workflows/os-check.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@ jobs:
1616
'--enable-all --enable-asn=original',
1717
'--enable-harden-tls',
1818
'--enable-tls13 --enable-session-ticket --enable-dtls --enable-dtls13
19-
--enable-opensslextra --enable-sessioncerts
20-
CPPFLAGS=''-DWOLFSSL_DTLS_NO_HVR_ON_RESUME -DHAVE_EXT_CACHE
21-
-DWOLFSSL_TICKET_HAVE_ID -DHAVE_EX_DATA -DSESSION_CACHE_DYNAMIC_MEM'' ',
19+
--enable-opensslextra --enable-sessioncerts
20+
CPPFLAGS=''-DWOLFSSL_DTLS_NO_HVR_ON_RESUME -DHAVE_EXT_CACHE
21+
-DWOLFSSL_TICKET_HAVE_ID -DHAVE_EX_DATA -DSESSION_CACHE_DYNAMIC_MEM'' ',
2222
'--enable-all --enable-secure-renegotiation',
2323
'--enable-all --enable-haproxy --enable-quic',
24+
'--enable-dtls --enable-dtls13 --enable-earlydata
25+
--enable-session-ticket --enable-psk
26+
CPPFLAGS=''-DWOLFSSL_DTLS13_NO_HRR_ON_RESUME'' ',
2427
]
2528
name: make check
2629
runs-on: ${{ matrix.os }}

examples/client/client.c

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ static const char *wolfsentry_config_path = NULL;
8989
#ifdef WOLFSSL_ALT_TEST_STRINGS
9090
#define TEST_STR_TERM "\n"
9191
#else
92-
#define TEST_STR_TERM
92+
#define TEST_STR_TERM "\n"
9393
#endif
9494

9595
static const char kHelloMsg[] = "hello wolfssl!" TEST_STR_TERM;
@@ -466,26 +466,6 @@ static void EarlyData(WOLFSSL_CTX* ctx, WOLFSSL* ssl, const char* msg,
466466
wolfSSL_CTX_free(ctx); ctx = NULL;
467467
err_sys("SSL_write_early_data failed");
468468
}
469-
do {
470-
err = 0; /* reset error */
471-
ret = wolfSSL_write_early_data(ssl, msg, msgSz, &msgSz);
472-
if (ret <= 0) {
473-
err = wolfSSL_get_error(ssl, 0);
474-
#ifdef WOLFSSL_ASYNC_CRYPT
475-
if (err == WC_PENDING_E) {
476-
ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
477-
if (ret < 0) break;
478-
}
479-
#endif
480-
}
481-
} while (err == WC_PENDING_E);
482-
if (ret != msgSz) {
483-
LOG_ERROR("SSL_write_early_data msg error %d, %s\n", err,
484-
wolfSSL_ERR_error_string(err, buffer));
485-
wolfSSL_free(ssl);
486-
wolfSSL_CTX_free(ctx);
487-
err_sys("SSL_write_early_data failed");
488-
}
489469
}
490470
#endif
491471

examples/server/server.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3358,7 +3358,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
33583358
err = 0; /* reset error */
33593359
ret = wolfSSL_read_early_data(ssl, input, sizeof(input)-1,
33603360
&len);
3361-
if (ret != WOLFSSL_SUCCESS) {
3361+
if (ret <= 0) {
33623362
err = SSL_get_error(ssl, 0);
33633363
#ifdef WOLFSSL_ASYNC_CRYPT
33643364
if (err == WC_PENDING_E) {

src/dtls.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@
2121

2222
/*
2323
* WOLFSSL_DTLS_NO_HVR_ON_RESUME
24+
* WOLFSSL_DTLS13_NO_HRR_ON_RESUME
2425
* If defined, a DTLS server will not do a cookie exchange on successful
2526
* client resumption: the resumption will be faster (one RTT less) and
26-
* will consume less bandwidth (one ClientHello and one HelloVerifyRequest
27-
* less). On the other hand, if a valid SessionID is collected, forged
28-
* clientHello messages will consume resources on the server.
27+
* will consume less bandwidth (one ClientHello and one
28+
* HelloVerifyRequest/HelloRetryRequest less). On the other hand, if a valid
29+
* SessionID/ticket/psk is collected, forged clientHello messages will
30+
* consume resources on the server.
2931
* WOLFSSL_DTLS_CH_FRAG
3032
* Allow a server to process a fragmented second/verified (one containing a
3133
* valid cookie response) ClientHello message. The first/unverified (one
@@ -769,6 +771,15 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch)
769771
}
770772
}
771773

774+
#ifdef WOLFSSL_DTLS13_NO_HRR_ON_RESUME
775+
if (ssl->options.dtls13NoHrrOnResume && usePSK && pskInfo.isValid &&
776+
!cs.doHelloRetry) {
777+
/* Skip HRR on resumption */
778+
((WOLFSSL*)ssl)->options.dtlsStateful = 1;
779+
goto dtls13_cleanup;
780+
}
781+
#endif
782+
772783
#ifdef HAVE_SUPPORTED_CURVES
773784
if (cs.doHelloRetry) {
774785
ret = TLSX_KeyShare_SetSupported(ssl, &parsedExts);
@@ -949,7 +960,7 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, word32 helloSz,
949960
ret = COOKIE_ERROR;
950961
else
951962
#endif
952-
ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13);
963+
ret = SendStatelessReply(ssl, &ch, isTls13);
953964
}
954965
else {
955966
byte cookieGood;
@@ -970,7 +981,7 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, word32 helloSz,
970981
ret = COOKIE_ERROR;
971982
else
972983
#endif
973-
ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13);
984+
ret = SendStatelessReply(ssl, &ch, isTls13);
974985
}
975986
else {
976987
ssl->options.dtlsStateful = 1;

src/dtls13.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2842,5 +2842,15 @@ int wolfSSL_dtls13_allow_ch_frag(WOLFSSL *ssl, int enabled)
28422842
}
28432843
#endif
28442844

2845+
#ifdef WOLFSSL_DTLS13_NO_HRR_ON_RESUME
2846+
int wolfSSL_dtls13_hrr_on_resume(WOLFSSL *ssl, int enabled)
2847+
{
2848+
if (ssl->options.side == WOLFSSL_CLIENT_END) {
2849+
return WOLFSSL_FAILURE;
2850+
}
2851+
ssl->options.dtls13NoHrrOnResume = !!enabled;
2852+
return WOLFSSL_SUCCESS;
2853+
}
2854+
#endif
28452855

28462856
#endif /* WOLFSSL_DTLS13 */

src/internal.c

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20179,20 +20179,8 @@ static int DtlsShouldDrop(WOLFSSL* ssl, int retcode)
2017920179
#ifndef NO_WOLFSSL_SERVER
2018020180
if (ssl->options.side == WOLFSSL_SERVER_END
2018120181
&& ssl->curRL.type != handshake && !IsSCR(ssl)) {
20182-
int beforeCookieVerified = 0;
20183-
if (!IsAtLeastTLSv1_3(ssl->version)) {
20184-
beforeCookieVerified =
20185-
ssl->options.acceptState < ACCEPT_FIRST_REPLY_DONE;
20186-
}
20187-
#ifdef WOLFSSL_DTLS13
20188-
else {
20189-
beforeCookieVerified =
20190-
ssl->options.acceptState < TLS13_ACCEPT_SECOND_REPLY_DONE;
20191-
}
20192-
#endif /* WOLFSSL_DTLS13 */
20193-
20194-
if (beforeCookieVerified) {
20195-
WOLFSSL_MSG("Drop non-handshake record before handshake");
20182+
if (!ssl->options.dtlsStateful) {
20183+
WOLFSSL_MSG("Drop non-handshake record when not stateful");
2019620184
return 1;
2019720185
}
2019820186
}
@@ -34435,6 +34423,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
3443534423

3443634424
#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
3443734425
if (cs.doHelloRetry) {
34426+
/* Make sure we don't send HRR twice */
34427+
if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE)
34428+
return INVALID_PARAMETER;
3443834429
ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
3443934430
return TLSX_KeyShare_SetSupported(ssl, &ssl->extensions);
3444034431
}

src/ssl.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16790,11 +16790,13 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
1679016790
#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || WOLFSSL_WPAS_SMALL */
1679116791

1679216792
/* return true if connection established */
16793-
int wolfSSL_is_init_finished(WOLFSSL* ssl)
16793+
int wolfSSL_is_init_finished(const WOLFSSL* ssl)
1679416794
{
1679516795
if (ssl == NULL)
1679616796
return 0;
1679716797

16798+
/* Can't use ssl->options.connectState and ssl->options.acceptState because
16799+
* they differ in meaning for TLS <=1.2 and 1.3 */
1679816800
if (ssl->options.handShakeState == HANDSHAKE_DONE)
1679916801
return 1;
1680016802

@@ -31935,12 +31937,7 @@ int wolfSSL_SSL_in_init(WOLFSSL *ssl)
3193531937
{
3193631938
WOLFSSL_ENTER("wolfSSL_SSL_in_init");
3193731939

31938-
if (ssl == NULL)
31939-
return WOLFSSL_FAILURE;
31940-
31941-
/* Can't use ssl->options.connectState and ssl->options.acceptState because
31942-
* they differ in meaning for TLS <=1.2 and 1.3 */
31943-
return ssl->options.handShakeState != HANDSHAKE_DONE;
31940+
return !wolfSSL_is_init_finished(ssl);
3194431941
}
3194531942

3194631943
int wolfSSL_SSL_in_connect_init(WOLFSSL* ssl)

src/tls13.c

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6197,6 +6197,8 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz,
61976197
if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
61986198
return ret;
61996199

6200+
ssl->keys.encryptionOn = 1;
6201+
62006202
#ifdef WOLFSSL_DTLS13
62016203
if (ssl->options.dtls) {
62026204
ret = Dtls13NewEpoch(ssl,
@@ -6909,7 +6911,11 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
69096911
}
69106912
}
69116913
else {
6912-
ERROR_OUT(HRR_COOKIE_ERROR, exit_dch);
6914+
#if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_DTLS13_NO_HRR_ON_RESUME)
6915+
/* Don't error out as we may be resuming. We confirm this later. */
6916+
if (!ssl->options.dtls)
6917+
#endif
6918+
ERROR_OUT(HRR_COOKIE_ERROR, exit_dch);
69136919
}
69146920
}
69156921
#endif
@@ -6975,14 +6981,16 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
69756981
goto exit_dch;
69766982
}
69776983
}
6978-
else
69796984
#endif
69806985
#ifdef HAVE_SUPPORTED_CURVES
69816986
if (args->usingPSK == 2) {
69826987
/* Pick key share and Generate a new key if not present. */
69836988
int doHelloRetry = 0;
69846989
ret = TLSX_KeyShare_Establish(ssl, &doHelloRetry);
69856990
if (doHelloRetry) {
6991+
/* Make sure we don't send HRR twice */
6992+
if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE)
6993+
ERROR_OUT(INVALID_PARAMETER, exit_dch);
69866994
ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
69876995
if (ret != WC_PENDING_E)
69886996
ret = 0; /* for hello_retry return 0 */
@@ -7075,32 +7083,58 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
70757083
ret = INPUT_CASE_ERROR;
70767084
} /* switch (ssl->options.asyncState) */
70777085

7078-
#if defined(WOLFSSL_SEND_HRR_COOKIE)
7079-
if (ret == 0 && ssl->options.sendCookie && ssl->options.cookieGood &&
7080-
(ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE
7086+
#ifdef WOLFSSL_SEND_HRR_COOKIE
7087+
if (ret == 0 && ssl->options.sendCookie) {
7088+
if (ssl->options.cookieGood &&
7089+
ssl->options.acceptState == TLS13_ACCEPT_FIRST_REPLY_DONE) {
7090+
/* Processing second ClientHello. Clear HRR state. */
7091+
ssl->options.serverState = NULL_STATE;
7092+
}
7093+
7094+
if (ssl->options.cookieGood &&
7095+
ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
7096+
/* If we already verified the peer with a cookie then we can't
7097+
* do another HRR for cipher negotiation. Send alert and restart
7098+
* the entire handshake. */
7099+
ERROR_OUT(INVALID_PARAMETER, exit_dch);
7100+
}
70817101
#ifdef WOLFSSL_DTLS13
7082-
/* DTLS cookie exchange should be done in stateless code in
7083-
* DoClientHelloStateless. If we verified the cookie then
7084-
* always advance the state. */
7085-
|| ssl->options.dtls
7102+
if (ssl->options.dtls &&
7103+
ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
7104+
/* Cookie and key share negotiation should be handled in
7105+
* DoClientHelloStateless. If we enter here then something went
7106+
* wrong in our logic. */
7107+
ERROR_OUT(BAD_HELLO, exit_dch);
7108+
}
70867109
#endif
7087-
))
7088-
ssl->options.serverState = SERVER_HELLO_COMPLETE;
7110+
/* Send a cookie */
7111+
if (!ssl->options.cookieGood &&
7112+
ssl->options.serverState != SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
7113+
#ifdef WOLFSSL_DTLS13
7114+
if (ssl->options.dtls) {
7115+
#ifdef WOLFSSL_DTLS13_NO_HRR_ON_RESUME
7116+
/* We can skip cookie on resumption */
7117+
if (!ssl->options.dtls || !ssl->options.dtls13NoHrrOnResume ||
7118+
!args->usingPSK)
7119+
#endif
7120+
ERROR_OUT(BAD_HELLO, exit_dch);
7121+
}
7122+
else
70897123
#endif
7124+
{
7125+
/* Need to remove the keyshare ext if we found a common group
7126+
* and are not doing curve negotiation. */
7127+
TLSX_Remove(&ssl->extensions, TLSX_KEY_SHARE, ssl->heap);
7128+
ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE;
7129+
}
70907130

7091-
#if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE)
7092-
if (ret == 0 && ssl->options.dtls && ssl->options.sendCookie &&
7093-
ssl->options.serverState <= SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
7094-
/* Cookie and key share negotiation should be handled in
7095-
* DoClientHelloStateless. If we enter here then something went wrong
7096-
* in our logic. */
7097-
ERROR_OUT(BAD_HELLO, exit_dch);
7131+
}
70987132
}
70997133
#endif /* WOLFSSL_DTLS13 */
71007134

71017135
#ifdef WOLFSSL_DTLS_CID
71027136
/* do not modify CID state if we are sending an HRR */
7103-
if (ssl->options.useDtlsCID &&
7137+
if (ret == 0 && ssl->options.dtls && ssl->options.useDtlsCID &&
71047138
ssl->options.serverState != SERVER_HELLO_RETRY_REQUEST_COMPLETE)
71057139
DtlsCIDOnExtensionsParsed(ssl);
71067140
#endif /* WOLFSSL_DTLS_CID */

0 commit comments

Comments
 (0)