Skip to content

Commit 26da4b8

Browse files
committed
Hand pre-1.3 DTLS connections to the legacy handshake
wolfSSL_connect_TLSv13() and wolfSSL_accept_TLSv13() handed off to wolfSSL_connect() and wolfSSL_accept() only when their own mask check moved the version. wolfSSL_set_options(), wolfSSL_set_max_proto_version() and CTX setup now move a DTLS SSL to DTLS 1.2 before either entry point runs, so such an SSL went into the TLS 1.3 state machine. With ECH built in, SendTls13ClientHello() failed, since no ECH extension is added below TLS 1.3. Both entry points now hand any DTLS SSL below 1.3 to the legacy handshake, on every call. That also covers re-entry with non-blocking I/O after the hand-off, which used to run the TLS 1.3 state machine on the legacy connect or accept state. The hand-off clears tls1_3, since wolfSSL_connect() and wolfSSL_accept() route on that flag: setting a DTLS 1.3 session and then a DTLS 1.2 one left it set on a DTLS 1.2 SSL, and the two entry points called each other until the stack overflowed. The check only runs in builds with a pre-1.3 handshake. Tests: both entry points, driven directly over memio, complete a DTLS 1.2 handshake after SSL-level and CTX-level masking, and a client given a DTLS 1.3 session and then a DTLS 1.2 one completes a DTLS 1.2 handshake.
1 parent ef8ffa0 commit 26da4b8

2 files changed

Lines changed: 128 additions & 22 deletions

File tree

‎src/tls13.c‎

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16680,21 +16680,21 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl)
1668016680
}
1668116681

1668216682
#ifdef WOLFSSL_DTLS
16683-
if (ssl->options.connectState == CONNECT_BEGIN) {
16684-
byte minor = ssl->version.minor;
16685-
16686-
if ((ret = DtlsCheckVersionMask(ssl)) != 0) {
16687-
ssl->error = ret;
16688-
WOLFSSL_ERROR(ssl->error);
16689-
return WOLFSSL_FATAL_ERROR;
16690-
}
16691-
if (ssl->version.minor != minor) {
16683+
if (ssl->options.connectState == CONNECT_BEGIN &&
16684+
(ret = DtlsCheckVersionMask(ssl)) != 0) {
16685+
ssl->error = ret;
16686+
WOLFSSL_ERROR(ssl->error);
16687+
return WOLFSSL_FATAL_ERROR;
16688+
}
16689+
#if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
16690+
if (ssl->version.major == DTLS_MAJOR && !IsAtLeastTLSv1_3(ssl->version)) {
16691+
ssl->options.tls1_3 = 0;
1669216692
#ifdef WOLFSSL_EARLY_DATA
16693-
ssl->earlyData = no_early_data;
16693+
ssl->earlyData = no_early_data;
1669416694
#endif
16695-
return wolfSSL_connect(ssl);
16696-
}
16695+
return wolfSSL_connect(ssl);
1669716696
}
16697+
#endif
1669816698
#endif
1669916699

1670016700
/* make sure this wolfSSL object has arrays and rng setup. Protects
@@ -17976,17 +17976,18 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl)
1797617976
}
1797717977

1797817978
#ifdef WOLFSSL_DTLS
17979-
if (ssl->options.acceptState == TLS13_ACCEPT_BEGIN) {
17980-
byte minor = ssl->version.minor;
17981-
17982-
if ((ret = DtlsCheckVersionMask(ssl)) != 0) {
17983-
ssl->error = ret;
17984-
WOLFSSL_ERROR(ssl->error);
17985-
return WOLFSSL_FATAL_ERROR;
17986-
}
17987-
if (ssl->version.minor != minor)
17988-
return wolfSSL_accept(ssl);
17979+
if (ssl->options.acceptState == TLS13_ACCEPT_BEGIN &&
17980+
(ret = DtlsCheckVersionMask(ssl)) != 0) {
17981+
ssl->error = ret;
17982+
WOLFSSL_ERROR(ssl->error);
17983+
return WOLFSSL_FATAL_ERROR;
1798917984
}
17985+
#if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
17986+
if (ssl->version.major == DTLS_MAJOR && !IsAtLeastTLSv1_3(ssl->version)) {
17987+
ssl->options.tls1_3 = 0;
17988+
return wolfSSL_accept(ssl);
17989+
}
17990+
#endif
1799017991
#endif
1799117992

1799217993
/* make sure this wolfSSL object has arrays and rng setup. Protects

‎tests/api/test_dtls.c‎

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16217,6 +16217,106 @@ static int test_dtls13_ctx_min_proto_zero(void)
1621716217
return EXPECT_RESULT();
1621816218
}
1621916219

16220+
/* The TLS 1.3 entry points hand an SSL already at DTLS 1.2 to the DTLS 1.2
16221+
* handshake, whether the SSL or the CTX mask moved it. */
16222+
static int test_dtls13_mask_tls13_entry(int onCtx)
16223+
{
16224+
EXPECT_DECLS;
16225+
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
16226+
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
16227+
struct test_memio_ctx test_ctx;
16228+
int retC = WOLFSSL_FATAL_ERROR;
16229+
int retS = WOLFSSL_FATAL_ERROR;
16230+
int i;
16231+
16232+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
16233+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, NULL, NULL,
16234+
wolfDTLS_client_method, wolfDTLS_server_method), 0);
16235+
if (onCtx) {
16236+
(void)wolfSSL_CTX_set_options(ctx_c, WOLFSSL_OP_NO_TLSv1_3);
16237+
(void)wolfSSL_CTX_set_options(ctx_s, WOLFSSL_OP_NO_TLSv1_3);
16238+
}
16239+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
16240+
wolfDTLS_client_method, wolfDTLS_server_method), 0);
16241+
if (!onCtx && ssl_c != NULL && ssl_s != NULL) {
16242+
(void)wolfSSL_set_options(ssl_c, WOLFSSL_OP_NO_TLSv1_3);
16243+
(void)wolfSSL_set_options(ssl_s, WOLFSSL_OP_NO_TLSv1_3);
16244+
}
16245+
ExpectIntEQ(wolfSSL_version(ssl_c), DTLS1_2_VERSION);
16246+
for (i = 0; EXPECT_SUCCESS() && i < 10 &&
16247+
(retC != WOLFSSL_SUCCESS || retS != WOLFSSL_SUCCESS); i++) {
16248+
if (retC != WOLFSSL_SUCCESS) {
16249+
retC = wolfSSL_connect_TLSv13(ssl_c);
16250+
ExpectIntEQ(ssl_c->options.tls1_3, 0);
16251+
}
16252+
if (retS != WOLFSSL_SUCCESS)
16253+
retS = wolfSSL_accept_TLSv13(ssl_s);
16254+
}
16255+
ExpectIntEQ(retC, WOLFSSL_SUCCESS);
16256+
ExpectIntEQ(retS, WOLFSSL_SUCCESS);
16257+
ExpectIntEQ(wolfSSL_version(ssl_c), DTLS1_2_VERSION);
16258+
ExpectIntEQ(wolfSSL_version(ssl_s), DTLS1_2_VERSION);
16259+
16260+
wolfSSL_free(ssl_c);
16261+
wolfSSL_free(ssl_s);
16262+
wolfSSL_CTX_free(ctx_c);
16263+
wolfSSL_CTX_free(ctx_s);
16264+
return EXPECT_RESULT();
16265+
}
16266+
16267+
#ifdef HAVE_SESSION_TICKET
16268+
/* Setting a DTLS 1.3 session and then a DTLS 1.2 one leaves tls1_3 set on a
16269+
* DTLS 1.2 SSL; the hand-off between the entry points must not loop. */
16270+
static int test_dtls13_stale_tls13_session(void)
16271+
{
16272+
EXPECT_DECLS;
16273+
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
16274+
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
16275+
WOLFSSL_SESSION *sess13 = NULL, *sess12 = NULL;
16276+
struct test_memio_ctx test_ctx;
16277+
char buf[8];
16278+
16279+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
16280+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
16281+
wolfDTLS_client_method, wolfDTLS_server_method), 0);
16282+
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
16283+
ExpectIntEQ(wolfSSL_read(ssl_c, buf, sizeof(buf)), WOLFSSL_FATAL_ERROR);
16284+
ExpectNotNull(sess13 = wolfSSL_get1_session(ssl_c));
16285+
wolfSSL_free(ssl_c);
16286+
ssl_c = NULL;
16287+
wolfSSL_free(ssl_s);
16288+
ssl_s = NULL;
16289+
wolfSSL_CTX_free(ctx_s);
16290+
ctx_s = NULL;
16291+
16292+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
16293+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
16294+
wolfDTLS_client_method, wolfDTLSv1_2_server_method), 0);
16295+
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
16296+
ExpectNotNull(sess12 = wolfSSL_get1_session(ssl_c));
16297+
wolfSSL_free(ssl_c);
16298+
ssl_c = NULL;
16299+
wolfSSL_free(ssl_s);
16300+
ssl_s = NULL;
16301+
16302+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
16303+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
16304+
wolfDTLS_client_method, wolfDTLSv1_2_server_method), 0);
16305+
ExpectIntEQ(wolfSSL_set_session(ssl_c, sess13), WOLFSSL_SUCCESS);
16306+
ExpectIntEQ(wolfSSL_set_session(ssl_c, sess12), WOLFSSL_SUCCESS);
16307+
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
16308+
ExpectIntEQ(wolfSSL_version(ssl_c), DTLS1_2_VERSION);
16309+
16310+
wolfSSL_SESSION_free(sess13);
16311+
wolfSSL_SESSION_free(sess12);
16312+
wolfSSL_free(ssl_c);
16313+
wolfSSL_free(ssl_s);
16314+
wolfSSL_CTX_free(ctx_c);
16315+
wolfSSL_CTX_free(ctx_s);
16316+
return EXPECT_RESULT();
16317+
}
16318+
#endif
16319+
1622016320
/* wolfSSL_negotiate() applies the mask too, on the server here. */
1622116321
static int test_dtls13_mask_negotiate(void)
1622216322
{
@@ -16342,6 +16442,11 @@ int test_dtls13_no_tls13_option(void)
1634216442
DTLS1_VERSION), TEST_SUCCESS);
1634316443
#endif
1634416444
}
16445+
for (onCtx = 0; onCtx <= 1; onCtx++)
16446+
ExpectIntEQ(test_dtls13_mask_tls13_entry(onCtx), TEST_SUCCESS);
16447+
#ifdef HAVE_SESSION_TICKET
16448+
ExpectIntEQ(test_dtls13_stale_tls13_session(), TEST_SUCCESS);
16449+
#endif
1634516450
ExpectIntEQ(test_dtls13_ctx_min_proto_zero(), TEST_SUCCESS);
1634616451
#ifdef HAVE_SNI
1634716452
ExpectIntEQ(test_dtls13_mask_in_client_hello(), TEST_SUCCESS);

0 commit comments

Comments
 (0)