From b2c80eae15248a038d30d4dd94293852c2b0a734 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 3 Jun 2026 00:25:46 +0200 Subject: [PATCH] F-5807: enforce EMS consistency on client session resumption CompleteServerHello's resumption branch derived keys from the cached master secret without checking the resumed session's extended_master_secret state against the abbreviated ServerHello, letting a MITM strip EMS on resumption. Per RFC 7627 Section 5.3, abort with a fatal handshake_failure when the cached session's EMS flag does not match the ServerHello EMS state. --- src/internal.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/internal.c b/src/internal.c index 4fc9ca00f7..04185f1ffd 100644 --- a/src/internal.c +++ b/src/internal.c @@ -32263,6 +32263,22 @@ static void MakePSKPreMasterSecret(Arrays* arrays, byte use_psk_key) } else { if (DSH_CheckSessionId(ssl)) { + /* RFC 7627 5.3: resumed session EMS state must match the + * ServerHello; abort on mismatch. Stateless (session-ticket) + * resumption - e.g. EAP-FAST, whose PAC is a TLS ticket - binds + * the EMS state in the ticket and need not re-advertise the + * extension, so this applies only to session-ID resumption. */ + if ( + #ifdef HAVE_SESSION_TICKET + ssl->session->ticketLen == 0 && + #endif + ssl->session->haveEMS != ssl->options.haveEMS) { + WOLFSSL_MSG("Resumed session EMS state does not match " + "ServerHello EMS state"); + SendAlert(ssl, alert_fatal, handshake_failure); + WOLFSSL_ERROR_VERBOSE(EXT_MASTER_SECRET_NEEDED_E); + return EXT_MASTER_SECRET_NEEDED_E; + } if (SetCipherSpecs(ssl) == 0) { if (!HaveUniqueSessionObj(ssl)) { WOLFSSL_MSG("Unable to have unique session object");