From ef73b3b2337fdde653600fa9b6f35f998d456c32 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 15 Apr 2026 14:48:54 +0200 Subject: [PATCH] tests: add EMS resumption downgrade negative test (F-2915) Covers the HandleResumeHistory check that RFC 7627 Section 5.3 requires: if the original session used Extended Master Secret, the server MUST abort when a resumption ClientHello is received without EMS. The new memio test performs a TLS 1.2 handshake with EMS, saves the session, disables EMS on a fresh client, resumes with the saved session, and asserts the server returns EXT_MASTER_SECRET_NEEDED_E. --- tests/api.c | 1 + tests/api/test_tls_ext.c | 50 ++++++++++++++++++++++++++++++++++++++++ tests/api/test_tls_ext.h | 1 + 3 files changed, 52 insertions(+) diff --git a/tests/api.c b/tests/api.c index 05a7688d7f..b9f2541570 100644 --- a/tests/api.c +++ b/tests/api.c @@ -37503,6 +37503,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_select_next_proto), #endif TEST_DECL(test_tls_ems_downgrade), + TEST_DECL(test_tls_ems_resumption_downgrade), TEST_DECL(test_wolfSSL_DisableExtendedMasterSecret), TEST_DECL(test_certificate_authorities_certificate_request), TEST_DECL(test_certificate_authorities_client_hello), diff --git a/tests/api/test_tls_ext.c b/tests/api/test_tls_ext.c index ad6053f727..4dd736f5eb 100644 --- a/tests/api/test_tls_ext.c +++ b/tests/api/test_tls_ext.c @@ -103,6 +103,56 @@ int test_tls_ems_downgrade(void) } +/* F-2915: resumption of an EMS session without EMS must abort with + * EXT_MASTER_SECRET_NEEDED_E (RFC 7627 Section 5.3). */ +int test_tls_ems_resumption_downgrade(void) +{ + EXPECT_DECLS; +#if !defined(WOLFSSL_NO_TLS12) && defined(HAVE_EXTENDED_MASTER) && \ + defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ + !defined(NO_SESSION_CACHE) + struct test_memio_ctx test_ctx; + WOLFSSL_CTX *ctx_c = NULL; + WOLFSSL_CTX *ctx_s = NULL; + WOLFSSL *ssl_c = NULL; + WOLFSSL *ssl_s = NULL; + WOLFSSL_SESSION *session = NULL; + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + + ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, + wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + + ExpectNotNull(session = wolfSSL_get1_session(ssl_c)); + + wolfSSL_free(ssl_c); + ssl_c = NULL; + wolfSSL_free(ssl_s); + ssl_s = NULL; + test_memio_clear_buffer(&test_ctx, 0); + test_memio_clear_buffer(&test_ctx, 1); + + ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, + wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); + ExpectIntEQ(wolfSSL_set_session(ssl_c, session), WOLFSSL_SUCCESS); + /* Drop EMS from the resumption ClientHello to simulate a downgrade. */ + ExpectIntEQ(wolfSSL_DisableExtendedMasterSecret(ssl_c), WOLFSSL_SUCCESS); + + ExpectIntNE(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + ExpectIntEQ(wolfSSL_get_error(ssl_s, 0), + WC_NO_ERR_TRACE(EXT_MASTER_SECRET_NEEDED_E)); + + wolfSSL_SESSION_free(session); + wolfSSL_free(ssl_c); + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_c); + wolfSSL_CTX_free(ctx_s); +#endif + return EXPECT_RESULT(); +} + + int test_wolfSSL_DisableExtendedMasterSecret(void) { EXPECT_DECLS; diff --git a/tests/api/test_tls_ext.h b/tests/api/test_tls_ext.h index ec7a5223be..8d9d8fcb9f 100644 --- a/tests/api/test_tls_ext.h +++ b/tests/api/test_tls_ext.h @@ -23,6 +23,7 @@ #define TESTS_API_TEST_TLS_EXT_H int test_tls_ems_downgrade(void); +int test_tls_ems_resumption_downgrade(void); int test_wolfSSL_DisableExtendedMasterSecret(void); int test_certificate_authorities_certificate_request(void); int test_certificate_authorities_client_hello(void);