From f574ceda714786deb156e53e6f2129bfdc561ddd Mon Sep 17 00:00:00 2001 From: Kareem Date: Wed, 22 Jul 2026 15:55:24 -0700 Subject: [PATCH 1/2] Add Enable/DisableNormalMasterSecret APIs to enforce EMS requirement at runtime. Disable server EMS when DisableExtendedMasterSecret is called, not just client EMS. --- src/internal.c | 8 +- src/ssl_api_ext.c | 119 ++++++++++++++++++++++++++- src/tls.c | 17 +++- tests/api.c | 3 + tests/api/test_tls_ext.c | 173 +++++++++++++++++++++++++++++++++++++++ tests/api/test_tls_ext.h | 3 + wolfssl/error-ssl.h | 2 +- wolfssl/internal.h | 13 +++ wolfssl/ssl.h | 4 + 9 files changed, 336 insertions(+), 6 deletions(-) diff --git a/src/internal.c b/src/internal.c index 5914aa42033..acfc8838ba0 100644 --- a/src/internal.c +++ b/src/internal.c @@ -8166,6 +8166,8 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #ifdef HAVE_EXTENDED_MASTER ssl->options.haveEMS = ctx->haveEMS; + ssl->options.disableEMS = ctx->disableEMS; + ssl->options.requireEMS = ctx->requireEMS; #endif ssl->options.useClientOrder = ctx->useClientOrder; ssl->options.mutualAuth = ctx->mutualAuth; @@ -28857,7 +28859,7 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) return "Initialize ctx mutex error"; case EXT_MASTER_SECRET_NEEDED_E: - return "Extended Master Secret must be enabled to resume EMS session"; + return "Extended Master Secret required but not negotiated with peer"; case DTLS_POOL_SZ_E: return "Maximum DTLS pool size exceeded"; @@ -40095,7 +40097,9 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl) i += hashSigAlgoSz; } #ifdef HAVE_EXTENDED_MASTER - else if (extId == HELLO_EXT_EXTMS) + /* Honor a user request to disable EMS on the server by + * ignoring the peer's extension. */ + else if (extId == HELLO_EXT_EXTMS && !ssl->options.disableEMS) ssl->options.haveEMS = 1; #endif else diff --git a/src/ssl_api_ext.c b/src/ssl_api_ext.c index 2e4a8952f10..fb297c2a600 100644 --- a/src/ssl_api_ext.c +++ b/src/ssl_api_ext.c @@ -1276,9 +1276,12 @@ int wolfSSL_set_SessionTicket_cb(WOLFSSL* ssl, #ifdef HAVE_EXTENDED_MASTER -#ifndef NO_WOLFSSL_CLIENT /* Disable the Extended Master Secret extension on the context. + * + * For a client this stops the extension being advertised. For a server this + * causes the peer's Extended Master Secret request to be ignored so that a + * standard master secret is negotiated. * * @param [in] ctx SSL/TLS context object. * @return WOLFSSL_SUCCESS on success. @@ -1290,12 +1293,19 @@ int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx) return BAD_FUNC_ARG; ctx->haveEMS = 0; + ctx->disableEMS = 1; + /* Disabling EMS is mutually exclusive with requiring it. */ + ctx->requireEMS = 0; return WOLFSSL_SUCCESS; } /* Disable the Extended Master Secret extension on the object. + * + * For a client this stops the extension being advertised. For a server this + * causes the peer's Extended Master Secret request to be ignored so that a + * standard master secret is negotiated. * * @param [in] ssl SSL/TLS object. * @return WOLFSSL_SUCCESS on success. @@ -1307,11 +1317,116 @@ int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl) return BAD_FUNC_ARG; ssl->options.haveEMS = 0; + ssl->options.disableEMS = 1; + /* Disabling EMS is mutually exclusive with requiring it. */ + ssl->options.requireEMS = 0; + + return WOLFSSL_SUCCESS; +} + + +/* Disable the standard (non-extended) master secret on the context. + * + * The Extended Master Secret extension (RFC 7627) becomes mandatory: if it is + * not negotiated with the peer the connection is aborted with + * EXT_MASTER_SECRET_NEEDED_E rather than falling back to a standard master + * secret. This only applies to TLS 1.2 and earlier; TLS 1.3 always uses a + * secure key schedule and is unaffected. + * + * @param [in] ctx SSL/TLS context object. + * @return WOLFSSL_SUCCESS on success. + * @return BAD_FUNC_ARG when ctx is NULL. + */ +int wolfSSL_CTX_DisableNormalMasterSecret(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->requireEMS = 1; + /* Requiring EMS is mutually exclusive with disabling it. */ + ctx->disableEMS = 0; + /* A client must advertise the extension for it to be negotiated. Undo any + * previous disable so the extension is offered. A server keeps its EMS + * state driven by the incoming ClientHello. */ + if (ctx->method != NULL && ctx->method->side == WOLFSSL_CLIENT_END) + ctx->haveEMS = 1; + + return WOLFSSL_SUCCESS; +} + + +/* Disable the standard (non-extended) master secret on the object. + * + * The Extended Master Secret extension (RFC 7627) becomes mandatory: if it is + * not negotiated with the peer the connection is aborted with + * EXT_MASTER_SECRET_NEEDED_E rather than falling back to a standard master + * secret. This only applies to TLS 1.2 and earlier; TLS 1.3 always uses a + * secure key schedule and is unaffected. + * + * @param [in] ssl SSL/TLS object. + * @return WOLFSSL_SUCCESS on success. + * @return BAD_FUNC_ARG when ssl is NULL. + */ +int wolfSSL_DisableNormalMasterSecret(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->options.requireEMS = 1; + /* Requiring EMS is mutually exclusive with disabling it. */ + ssl->options.disableEMS = 0; + /* A client must advertise the extension for it to be negotiated. Undo any + * previous disable so the extension is offered. A server keeps its EMS + * state driven by the incoming ClientHello. */ + if (ssl->options.side == WOLFSSL_CLIENT_END) + ssl->options.haveEMS = 1; + + return WOLFSSL_SUCCESS; +} + + +/* Re-enable the standard (non-extended) master secret on the context. + * + * Undoes wolfSSL_CTX_DisableNormalMasterSecret so that a standard master + * secret is once again acceptable when the Extended Master Secret extension + * (RFC 7627) is not negotiated. Extended Master Secret support itself is left + * unchanged. + * + * @param [in] ctx SSL/TLS context object. + * @return WOLFSSL_SUCCESS on success. + * @return BAD_FUNC_ARG when ctx is NULL. + */ +int wolfSSL_CTX_EnableNormalMasterSecret(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->requireEMS = 0; + + return WOLFSSL_SUCCESS; +} + + +/* Re-enable the standard (non-extended) master secret on the object. + * + * Undoes wolfSSL_DisableNormalMasterSecret so that a standard master secret is + * once again acceptable when the Extended Master Secret extension (RFC 7627) + * is not negotiated. Extended Master Secret support itself is left unchanged. + * + * @param [in] ssl SSL/TLS object. + * @return WOLFSSL_SUCCESS on success. + * @return BAD_FUNC_ARG when ssl is NULL. + */ +int wolfSSL_EnableNormalMasterSecret(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->options.requireEMS = 0; return WOLFSSL_SUCCESS; } -#endif #endif #endif /* !NO_TLS */ diff --git a/src/tls.c b/src/tls.c index 661410b8e4c..82106df8027 100644 --- a/src/tls.c +++ b/src/tls.c @@ -705,6 +705,19 @@ int MakeTlsMasterSecret(WOLFSSL* ssl) { int ret; +#ifdef HAVE_EXTENDED_MASTER + /* The user disabled the standard master secret and requires the Extended + * Master Secret extension (RFC 7627). If it was not negotiated with the + * peer, abort rather than derive a standard master secret. Only reachable + * for TLS 1.2 and earlier; TLS 1.3 uses a separate key schedule. */ + if (ssl->options.requireEMS && !ssl->options.haveEMS) { + WOLFSSL_MSG("EMS required but not negotiated with peer"); + SendAlert(ssl, alert_fatal, handshake_failure); + WOLFSSL_ERROR_VERBOSE(EXT_MASTER_SECRET_NEEDED_E); + return EXT_MASTER_SECRET_NEEDED_E; + } +#endif + #if defined(WOLFSSL_SNIFFER) && defined(WOLFSSL_SNIFFER_KEYLOGFILE) /* If this is called from a sniffer session with keylog file support, obtain * the master secret from the callback */ @@ -18286,7 +18299,9 @@ WOLFSSL_TEST_VIS int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, return BUFFER_ERROR; #ifndef NO_WOLFSSL_SERVER - if (isRequest) + /* Honor a user request to disable EMS on the server by + * ignoring the peer's extension rather than enabling it. */ + if (isRequest && !ssl->options.disableEMS) ssl->options.haveEMS = 1; #endif pendingEMS = 1; diff --git a/tests/api.c b/tests/api.c index 7cf9225e49a..fcc7bfdc0cc 100644 --- a/tests/api.c +++ b/tests/api.c @@ -38104,6 +38104,8 @@ TEST_CASE testCases[] = { TEST_DECL(test_tls_ems_downgrade), TEST_DECL(test_tls_ems_resumption_downgrade), TEST_DECL(test_tls_ems_resumption_server_downgrade), + TEST_DECL(test_tls_ems_server_disable), + TEST_DECL(test_tls_require_ems), TEST_DECL(test_tls12_chacha20_poly1305_bad_tag), TEST_DECL(test_tls13_null_cipher_bad_hmac), TEST_DECL(test_scr_verify_data_mismatch), @@ -38112,6 +38114,7 @@ TEST_CASE testCases[] = { TEST_DECL(test_tls13_hrr_cipher_suite_mismatch), TEST_DECL(test_tls13_ticket_age_out_of_window), TEST_DECL(test_wolfSSL_DisableExtendedMasterSecret), + TEST_DECL(test_wolfSSL_DisableNormalMasterSecret), TEST_DECL(test_certificate_authorities_certificate_request), TEST_DECL(test_certificate_authorities_client_hello), TEST_DECL(test_TLSX_TCA_Find), diff --git a/tests/api/test_tls_ext.c b/tests/api/test_tls_ext.c index 34d95f12125..6a4886b8f0c 100644 --- a/tests/api/test_tls_ext.c +++ b/tests/api/test_tls_ext.c @@ -313,6 +313,129 @@ int test_tls_ems_resumption_server_downgrade(void) } +/* wolfSSL_DisableExtendedMasterSecret must disable EMS on the server as well + * as the client. When the server disables EMS it ignores the client's + * extended_master_secret extension and both peers fall back to a standard + * master secret while the handshake still completes. */ +int test_tls_ems_server_disable(void) +{ + EXPECT_DECLS; +#if !defined(WOLFSSL_NO_TLS12) && defined(HAVE_EXTENDED_MASTER) && \ + !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ + defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) + struct test_memio_ctx test_ctx; + WOLFSSL_CTX *ctx_c = NULL; + WOLFSSL_CTX *ctx_s = NULL; + WOLFSSL *ssl_c = NULL; + WOLFSSL *ssl_s = 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); + + /* The client still advertises EMS; the server disables it. */ + ExpectIntEQ(wolfSSL_DisableExtendedMasterSecret(ssl_s), WOLFSSL_SUCCESS); + + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + + /* Neither side ends up using EMS. */ + if (ssl_s != NULL) + ExpectIntEQ(ssl_s->options.haveEMS, 0); + if (ssl_c != NULL) + ExpectIntEQ(ssl_c->options.haveEMS, 0); + + wolfSSL_free(ssl_c); + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_c); + wolfSSL_CTX_free(ctx_s); +#endif + return EXPECT_RESULT(); +} + + +#if !defined(WOLFSSL_NO_TLS12) && defined(HAVE_EXTENDED_MASTER) && \ + !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ + defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) +/* Exercise wolfSSL_DisableNormalMasterSecret. When serverSide is set the + * server requires EMS, otherwise the client does. When peerDisables is set the + * opposite side disables EMS, so the extension cannot be negotiated and the + * requiring side must abort with EXT_MASTER_SECRET_NEEDED_E. */ +static int test_tls_require_ems_ex(int serverSide, int peerDisables) +{ + EXPECT_DECLS; + struct test_memio_ctx test_ctx; + WOLFSSL_CTX *ctx_c = NULL; + WOLFSSL_CTX *ctx_s = NULL; + WOLFSSL *ssl_c = NULL; + WOLFSSL *ssl_s = 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); + + if (serverSide) + ExpectIntEQ(wolfSSL_DisableNormalMasterSecret(ssl_s), WOLFSSL_SUCCESS); + else + ExpectIntEQ(wolfSSL_DisableNormalMasterSecret(ssl_c), WOLFSSL_SUCCESS); + + if (peerDisables) { + if (serverSide) + ExpectIntEQ(wolfSSL_DisableExtendedMasterSecret(ssl_c), + WOLFSSL_SUCCESS); + else + ExpectIntEQ(wolfSSL_DisableExtendedMasterSecret(ssl_s), + WOLFSSL_SUCCESS); + + /* EMS cannot be negotiated so the requiring side must abort. */ + ExpectIntNE(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + if (serverSide) + ExpectIntEQ(wolfSSL_get_error(ssl_s, 0), + WC_NO_ERR_TRACE(EXT_MASTER_SECRET_NEEDED_E)); + else + ExpectIntEQ(wolfSSL_get_error(ssl_c, 0), + WC_NO_ERR_TRACE(EXT_MASTER_SECRET_NEEDED_E)); + } + else { + /* Peer supports EMS so the handshake completes using EMS. */ + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + if (ssl_c != NULL) + ExpectIntEQ(ssl_c->options.haveEMS, 1); + if (ssl_s != NULL) + ExpectIntEQ(ssl_s->options.haveEMS, 1); + } + + wolfSSL_free(ssl_c); + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_c); + wolfSSL_CTX_free(ctx_s); + return EXPECT_RESULT(); +} +#endif + +/* wolfSSL_DisableNormalMasterSecret makes the Extended Master Secret extension + * mandatory: the handshake succeeds when the peer supports EMS and is aborted + * with EXT_MASTER_SECRET_NEEDED_E otherwise, on both client and server. */ +int test_tls_require_ems(void) +{ + EXPECT_DECLS; +#if !defined(WOLFSSL_NO_TLS12) && defined(HAVE_EXTENDED_MASTER) && \ + !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ + defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) + /* Client requires EMS, server supports it -> success. */ + ExpectIntEQ(test_tls_require_ems_ex(0, 0), TEST_SUCCESS); + /* Client requires EMS, server disabled it -> abort. */ + ExpectIntEQ(test_tls_require_ems_ex(0, 1), TEST_SUCCESS); + /* Server requires EMS, client offers it -> success. */ + ExpectIntEQ(test_tls_require_ems_ex(1, 0), TEST_SUCCESS); + /* Server requires EMS, client disabled it -> abort. */ + ExpectIntEQ(test_tls_require_ems_ex(1, 1), TEST_SUCCESS); +#endif + return EXPECT_RESULT(); +} + + #if !defined(WOLFSSL_NO_TLS12) && \ defined(BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) && \ defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) @@ -803,6 +926,56 @@ int test_wolfSSL_DisableExtendedMasterSecret(void) } +int test_wolfSSL_DisableNormalMasterSecret(void) +{ + EXPECT_DECLS; +#if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT) && \ + !defined(NO_TLS) + WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); + WOLFSSL *ssl = wolfSSL_new(ctx); + + ExpectNotNull(ctx); + ExpectNotNull(ssl); + + /* error cases */ + ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_DisableNormalMasterSecret(NULL)); + ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_DisableNormalMasterSecret(NULL)); + ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_EnableNormalMasterSecret(NULL)); + ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_EnableNormalMasterSecret(NULL)); + + /* success cases */ + ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_DisableNormalMasterSecret(ctx)); + ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_DisableNormalMasterSecret(ssl)); + + /* Requiring EMS must (re)enable advertising it on a client. */ + ExpectIntEQ(ctx->haveEMS, 1); + ExpectIntEQ(ssl->options.haveEMS, 1); + ExpectIntEQ(ctx->requireEMS, 1); + ExpectIntEQ(ssl->options.requireEMS, 1); + + /* Re-enabling the normal master secret clears the requirement but leaves + * EMS support intact. */ + ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_EnableNormalMasterSecret(ctx)); + ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_EnableNormalMasterSecret(ssl)); + ExpectIntEQ(ctx->requireEMS, 0); + ExpectIntEQ(ssl->options.requireEMS, 0); + ExpectIntEQ(ctx->haveEMS, 1); + ExpectIntEQ(ssl->options.haveEMS, 1); + + /* Disabling EMS afterwards clears the requirement (mutually exclusive). */ + ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_DisableNormalMasterSecret(ssl)); + ExpectIntEQ(ssl->options.requireEMS, 1); + ExpectIntEQ(WOLFSSL_SUCCESS, wolfSSL_DisableExtendedMasterSecret(ssl)); + ExpectIntEQ(ssl->options.requireEMS, 0); + ExpectIntEQ(ssl->options.disableEMS, 1); + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); +#endif + return EXPECT_RESULT(); +} + + #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ !defined(WOLFSSL_NO_CA_NAMES) && !defined(NO_BIO) && \ !defined(NO_CERTS) && !defined(NO_TLS) && (defined(OPENSSL_EXTRA) || \ diff --git a/tests/api/test_tls_ext.h b/tests/api/test_tls_ext.h index 90ccdf17c96..7b432e5a245 100644 --- a/tests/api/test_tls_ext.h +++ b/tests/api/test_tls_ext.h @@ -25,6 +25,8 @@ int test_tls_ems_downgrade(void); int test_tls_ems_resumption_downgrade(void); int test_tls_ems_resumption_server_downgrade(void); +int test_tls_ems_server_disable(void); +int test_tls_require_ems(void); int test_tls12_chacha20_poly1305_bad_tag(void); int test_tls13_null_cipher_bad_hmac(void); int test_scr_verify_data_mismatch(void); @@ -33,6 +35,7 @@ int test_helloRequest_no_renegotiation_option(void); int test_tls13_hrr_cipher_suite_mismatch(void); int test_tls13_ticket_age_out_of_window(void); int test_wolfSSL_DisableExtendedMasterSecret(void); +int test_wolfSSL_DisableNormalMasterSecret(void); int test_certificate_authorities_certificate_request(void); int test_certificate_authorities_client_hello(void); int test_TLSX_TCA_Find(void); diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index 4c6893fbeb3..8c28405705d 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -159,7 +159,7 @@ enum wolfSSL_ErrorCodes { DTLS_EXPORT_VER_E = -411, /* export version error */ INPUT_SIZE_E = -412, /* input size too big error */ CTX_INIT_MUTEX_E = -413, /* initialize ctx mutex error */ - EXT_MASTER_SECRET_NEEDED_E = -414, /* need EMS enabled to resume */ + EXT_MASTER_SECRET_NEEDED_E = -414, /* EMS required but not negotiated */ DTLS_POOL_SZ_E = -415, /* exceeded DTLS pool size */ DECODE_E = -416, /* decode handshake message error */ HTTP_TIMEOUT = -417, /* HTTP timeout for OCSP or CRL req */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 38e5015d0d8..b665688bb3e 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -4061,6 +4061,13 @@ struct WOLFSSL_CTX { byte groupMessages:1; /* group handshake messages before sending */ byte minDowngrade; /* minimum downgrade version */ byte haveEMS:1; /* have extended master secret extension */ +#ifdef HAVE_EXTENDED_MASTER + byte disableEMS:1; /* user disabled extended master secret, + * ignore peer's EMS request (server) and + * don't advertise it (client) */ + byte requireEMS:1; /* user requires extended master secret, + * abort if EMS is not negotiated */ +#endif byte useClientOrder:1; /* Use client's cipher preference order */ #if defined(HAVE_SESSION_TICKET) byte noTicketTls12:1; /* TLS 1.2 server won't send ticket */ @@ -5231,6 +5238,12 @@ struct Options { word16 weOwnRng:1; /* will be true unless CTX owns */ word16 dontFreeDigest:1; /* when true, we used SetDigest */ word16 haveEMS:1; /* using extended master secret */ +#ifdef HAVE_EXTENDED_MASTER + word16 disableEMS:1; /* user disabled extended master + * secret */ + word16 requireEMS:1; /* user requires extended master + * secret */ +#endif #ifdef HAVE_POLY1305 word16 oldPoly:1; /* set when to use old rfc way of poly*/ #endif diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index b71810d3181..0b18f62b4ae 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -5076,6 +5076,10 @@ WOLFSSL_API int wolfSSL_CTX_set_num_tickets(WOLFSSL_CTX* ctx, size_t mxTickets); /* TLS Extended Master Secret Extension */ WOLFSSL_API int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_DisableNormalMasterSecret(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_DisableNormalMasterSecret(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_EnableNormalMasterSecret(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_EnableNormalMasterSecret(WOLFSSL_CTX* ctx); #define WOLFSSL_CRL_MONITOR 0x01 /* monitor this dir flag */ From cde2a65ce760fae4e1176f60420e73d9f96ca66f Mon Sep 17 00:00:00 2001 From: Kareem Date: Wed, 22 Jul 2026 16:28:50 -0700 Subject: [PATCH 2/2] Code review feedback --- src/tls.c | 12 +++++++----- tests/api/test_tls_ext.c | 25 ++++++++++++++----------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/tls.c b/src/tls.c index 82106df8027..186e7a96d39 100644 --- a/src/tls.c +++ b/src/tls.c @@ -18298,13 +18298,15 @@ WOLFSSL_TEST_VIS int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, if (size != 0) return BUFFER_ERROR; + /* Honor a user request to disable EMS by ignoring the peer's + * extension rather than enabling it. */ + if (!ssl->options.disableEMS) { #ifndef NO_WOLFSSL_SERVER - /* Honor a user request to disable EMS on the server by - * ignoring the peer's extension rather than enabling it. */ - if (isRequest && !ssl->options.disableEMS) - ssl->options.haveEMS = 1; + if (isRequest) + ssl->options.haveEMS = 1; #endif - pendingEMS = 1; + pendingEMS = 1; + } break; #endif diff --git a/tests/api/test_tls_ext.c b/tests/api/test_tls_ext.c index 6a4886b8f0c..70c77bde76d 100644 --- a/tests/api/test_tls_ext.c +++ b/tests/api/test_tls_ext.c @@ -369,6 +369,7 @@ static int test_tls_require_ems_ex(int serverSide, int peerDisables) WOLFSSL_CTX *ctx_s = NULL; WOLFSSL *ssl_c = NULL; WOLFSSL *ssl_s = NULL; + int ret; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); @@ -389,12 +390,13 @@ static int test_tls_require_ems_ex(int serverSide, int peerDisables) WOLFSSL_SUCCESS); /* EMS cannot be negotiated so the requiring side must abort. */ - ExpectIntNE(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + ret = test_memio_do_handshake(ssl_c, ssl_s, 10, NULL); + ExpectIntNE(ret, 0); if (serverSide) - ExpectIntEQ(wolfSSL_get_error(ssl_s, 0), + ExpectIntEQ(wolfSSL_get_error(ssl_s, ret), WC_NO_ERR_TRACE(EXT_MASTER_SECRET_NEEDED_E)); else - ExpectIntEQ(wolfSSL_get_error(ssl_c, 0), + ExpectIntEQ(wolfSSL_get_error(ssl_c, ret), WC_NO_ERR_TRACE(EXT_MASTER_SECRET_NEEDED_E)); } else { @@ -905,11 +907,11 @@ int test_wolfSSL_DisableExtendedMasterSecret(void) EXPECT_DECLS; #if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT) && \ !defined(NO_TLS) - WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); - WOLFSSL *ssl = wolfSSL_new(ctx); + WOLFSSL_CTX *ctx = NULL; + WOLFSSL *ssl = NULL; - ExpectNotNull(ctx); - ExpectNotNull(ssl); + ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + ExpectNotNull(ssl = wolfSSL_new(ctx)); /* error cases */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_DisableExtendedMasterSecret(NULL)); @@ -931,11 +933,12 @@ int test_wolfSSL_DisableNormalMasterSecret(void) EXPECT_DECLS; #if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT) && \ !defined(NO_TLS) - WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); - WOLFSSL *ssl = wolfSSL_new(ctx); + WOLFSSL_CTX *ctx = NULL; + WOLFSSL *ssl = NULL; - ExpectNotNull(ctx); - ExpectNotNull(ssl); + + ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + ExpectNotNull(ssl = wolfSSL_new(ctx)); /* error cases */ ExpectIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_DisableNormalMasterSecret(NULL));