diff --git a/src/ssl_api_hs.c b/src/ssl_api_hs.c index 521bc38b8a5..257951af4a1 100644 --- a/src/ssl_api_hs.c +++ b/src/ssl_api_hs.c @@ -943,6 +943,14 @@ int wolfSSL_accept(WOLFSSL* ssl) if ((!IsDtlsNotSctpMode(ssl)) || (IsSCR(ssl))) { ssl->options.dtlsStateful = 1; } + #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) + if (!ssl->options.disableECH && ssl->ctx->echConfigs != NULL) { + WOLFSSL_MSG("ECH configs set but ECH is not supported with DTLS"); + ssl->error = BAD_STATE_E; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + #endif } #endif diff --git a/src/tls.c b/src/tls.c index 69a41fc7f74..048d246dc86 100644 --- a/src/tls.c +++ b/src/tls.c @@ -17134,6 +17134,15 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) ret = GREASE_ECH_USE(&(ssl->extensions), ssl->heap, ssl->rng); } + #ifdef WOLFSSL_DTLS13 + else if (ssl->options.dtls) { + /* ECH is not supported over DTLS, GREASE ECH is fine */ + WOLFSSL_MSG("ECH configs set but ECH is not supported " + "with DTLS"); + WOLFSSL_ERROR_VERBOSE(BAD_STATE_E); + ret = BAD_STATE_E; + } + #endif else if (ssl->echConfigs != NULL) { ret = ECH_USE(ssl->echConfigs, &(ssl->extensions), ssl->heap, ssl->rng); diff --git a/src/tls13.c b/src/tls13.c index 68154208bcf..142e2a33222 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -18025,6 +18025,14 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) ssl->options.dtls = 1; if (!IsDtlsNotSctpMode(ssl) || !ssl->options.sendCookie) ssl->options.dtlsStateful = 1; + #ifdef HAVE_ECH + if (!ssl->options.disableECH && ssl->ctx->echConfigs != NULL) { + WOLFSSL_MSG("ECH configs set but ECH is not supported with DTLS"); + ssl->error = BAD_STATE_E; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + #endif } #endif diff --git a/tests/api.c b/tests/api.c index be6253b80bd..538d53f58a4 100644 --- a/tests/api.c +++ b/tests/api.c @@ -19891,6 +19891,87 @@ static int test_wolfSSL_Tls13_ECH_read_ahead(void) #endif return EXPECT_RESULT(); } + +#ifdef WOLFSSL_DTLS +/* ECH is not supported over DTLS: a client with ECH configs and a server with + * generated ECH configs must fail before anything is sent */ +static int test_wolfSSL_Dtls_ECH_unsupported_ex(method_provider c_method, + method_provider s_method) +{ + EXPECT_DECLS; + test_ssl_memio_ctx test_ctx; + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + + test_ctx.s_cb.method = s_method; + test_ctx.c_cb.method = c_method; + + test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; + test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready; + test_ctx.c_cb.ssl_ready = test_ech_client_ssl_ready; + + ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); + + ExpectIntEQ(wolfSSL_connect(test_ctx.c_ssl), WOLFSSL_FATAL_ERROR); + ExpectIntEQ(wolfSSL_get_error(test_ctx.c_ssl, WOLFSSL_FATAL_ERROR), + WC_NO_ERR_TRACE(BAD_STATE_E)); + /* no ClientHello was sent */ + ExpectIntEQ(test_ctx.s_len, 0); + + ExpectIntEQ(wolfSSL_accept(test_ctx.s_ssl), WOLFSSL_FATAL_ERROR); + ExpectIntEQ(wolfSSL_get_error(test_ctx.s_ssl, WOLFSSL_FATAL_ERROR), + WC_NO_ERR_TRACE(BAD_STATE_E)); + /* no reply was sent */ + ExpectIntEQ(test_ctx.c_len, 0); + + test_ssl_memio_cleanup(&test_ctx); + + /* disabling ECH on the objects lets the same setup connect */ + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + + test_ctx.s_cb.method = s_method; + test_ctx.c_cb.method = c_method; + + test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready; + test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready; + test_ctx.c_cb.ssl_ready = test_ech_client_ssl_ready; + + ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); + + wolfSSL_SetEchEnable(test_ctx.s_ssl, 0); + wolfSSL_SetEchEnable(test_ctx.c_ssl, 0); + + ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS); + ExpectIntEQ(wolfSSL_GetEchStatus(test_ctx.c_ssl), + WOLFSSL_ECH_STATUS_NOT_OFFERED); + ExpectIntEQ(wolfSSL_GetEchStatus(test_ctx.s_ssl), + WOLFSSL_ECH_STATUS_NOT_OFFERED); + + test_ssl_memio_cleanup(&test_ctx); + + return EXPECT_RESULT(); +} + +static int test_wolfSSL_Dtls_ECH_unsupported(void) +{ + EXPECT_DECLS; + +#ifndef WOLFSSL_NO_TLS12 + /* DTLS 1.2 and version-flexible peers: with ECH on, each side fails before + * sending anything */ + ExpectIntEQ(test_wolfSSL_Dtls_ECH_unsupported_ex( + wolfDTLS_client_method, wolfDTLSv1_2_server_method), TEST_SUCCESS); + ExpectIntEQ(test_wolfSSL_Dtls_ECH_unsupported_ex( + wolfDTLSv1_2_client_method, wolfDTLS_server_method), TEST_SUCCESS); +#endif +#ifdef WOLFSSL_DTLS13 + ExpectIntEQ(test_wolfSSL_Dtls_ECH_unsupported_ex( + wolfDTLS_client_method, wolfDTLSv1_3_server_method), TEST_SUCCESS); +#endif + + return EXPECT_RESULT(); +} +#endif /* WOLFSSL_DTLS */ #endif /* HAVE_SSL_MEMIO_TESTS_DEPENDENCIES */ /* verify that ECH can be enabled/disabled without issue */ @@ -47274,6 +47355,9 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_Tls13_ECH_sni_parse), TEST_DECL(test_wolfSSL_Tls13_ECH_read_ahead), #endif +#if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) + TEST_DECL(test_wolfSSL_Dtls_ECH_unsupported), +#endif #if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_TEST_ECH) && \ !defined(WOLFSSL_NO_TLS12) TEST_DECL(test_wolfSSL_Tls13_ECH_tamper_client),