From 9948823142fe1947127386e08a32fe262e748821 Mon Sep 17 00:00:00 2001 From: Paul Adelsbach Date: Tue, 13 Oct 2026 17:34:45 -0700 Subject: [PATCH 1/3] Check SNI/ALPN on session ID resumption without session tickets --- src/internal.c | 100 ++++++++++++++++++++++--------------------- src/ssl_sess.c | 11 +++-- tests/api/test_tls.c | 19 +++++--- wolfssl/internal.h | 23 +++++----- 4 files changed, 81 insertions(+), 72 deletions(-) diff --git a/src/internal.c b/src/internal.c index 1f62c435246..b85bf461701 100644 --- a/src/internal.c +++ b/src/internal.c @@ -42847,10 +42847,12 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl) ssl->options.peerAuthGood = 0; return ret; } -#if defined(HAVE_SESSION_TICKET) && \ - (defined(HAVE_SNI) || defined(HAVE_ALPN)) +#if defined(HAVE_SNI) || defined(HAVE_ALPN) /* Do not resume session if sniHash/alpnHash do not match. */ - if (!ssl->options.useTicket) { + #ifdef HAVE_SESSION_TICKET + if (!ssl->options.useTicket) + #endif + { byte curHash[TICKET_BINDING_HASH_SZ]; #ifdef HAVE_SNI if (TicketSniHash(ssl, curHash) != 0 || @@ -42872,7 +42874,7 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl) } #endif } -#endif /* HAVE_SESSION_TICKET && (HAVE_SNI || HAVE_ALPN) */ +#endif /* HAVE_SNI || HAVE_ALPN */ #if !defined(WOLFSSL_NO_TICKET_EXPIRE) && !defined(NO_ASN_TIME) /* check if the ticket is valid */ @@ -44330,6 +44332,51 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl) #endif /* !WOLFSSL_NO_TLS12 */ +#ifdef HAVE_SNI + /* Hash server-selected SNI; zeros dst when none. */ + int TicketSniHash(WOLFSSL* ssl, byte* dst) + { + char* name = NULL; + word16 nameLen; + + nameLen = TLSX_SNI_GetRequest(ssl->extensions, + WOLFSSL_SNI_HOST_NAME, + (void**)&name, 0); + if (name != NULL && nameLen > 0) { + return wc_Hash(TICKET_BINDING_HASH_TYPE, (const byte*)name, + nameLen, dst, TICKET_BINDING_HASH_SZ); + } + + XMEMSET(dst, 0, TICKET_BINDING_HASH_SZ); + return 0; + } +#endif + +#ifdef HAVE_ALPN + /* Hash negotiated ALPN; zeros dst when none. */ + int TicketAlpnHash(WOLFSSL* ssl, byte* dst) + { + TLSX* extension; + ALPN* alpn; + + extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL); + if (extension != NULL) { + alpn = (ALPN*)extension->data; + if (alpn != NULL && alpn->negotiated == 1) { + word32 protoLen = (word32)alpn->protocol_nameSz; + if (protoLen > 0) { + return wc_Hash(TICKET_BINDING_HASH_TYPE, + (const byte*)alpn->protocol_name, + protoLen, dst, TICKET_BINDING_HASH_SZ); + } + } + } + + XMEMSET(dst, 0, TICKET_BINDING_HASH_SZ); + return 0; + } +#endif + #ifdef HAVE_SESSION_TICKET #ifdef WOLFSSL_TICKET_HAVE_ID @@ -44394,51 +44441,6 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl) return ret; } -#ifdef HAVE_SNI - /* Hash server-selected SNI; zeros dst when none. */ - int TicketSniHash(WOLFSSL* ssl, byte* dst) - { - char* name = NULL; - word16 nameLen; - - nameLen = TLSX_SNI_GetRequest(ssl->extensions, - WOLFSSL_SNI_HOST_NAME, - (void**)&name, 0); - if (name != NULL && nameLen > 0) { - return wc_Hash(TICKET_BINDING_HASH_TYPE, (const byte*)name, - nameLen, dst, TICKET_BINDING_HASH_SZ); - } - - XMEMSET(dst, 0, TICKET_BINDING_HASH_SZ); - return 0; - } -#endif - -#ifdef HAVE_ALPN - /* Hash negotiated ALPN; zeros dst when none. */ - int TicketAlpnHash(WOLFSSL* ssl, byte* dst) - { - TLSX* extension; - ALPN* alpn; - - extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL); - if (extension != NULL) { - alpn = (ALPN*)extension->data; - if (alpn != NULL && alpn->negotiated == 1) { - word32 protoLen = (word32)alpn->protocol_nameSz; - if (protoLen > 0) { - return wc_Hash(TICKET_BINDING_HASH_TYPE, - (const byte*)alpn->protocol_name, - protoLen, dst, TICKET_BINDING_HASH_SZ); - } - } - } - - XMEMSET(dst, 0, TICKET_BINDING_HASH_SZ); - return 0; - } -#endif - #if defined(HAVE_SNI) || defined(HAVE_ALPN) /* Server-side TLS 1.2 ticket-resumption binding check. Confirms the * SNI/ALPN bound to the resumed session matches what was negotiated diff --git a/src/ssl_sess.c b/src/ssl_sess.c index 341ccd77afc..e0b25a7facf 100644 --- a/src/ssl_sess.c +++ b/src/ssl_sess.c @@ -2942,6 +2942,7 @@ int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) #ifdef HAVE_SESSION_TICKET /* ticket len | ticket */ size += OPAQUE16_LEN + sess->ticketLen; +#endif #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) #ifdef HAVE_SNI /* sniHash */ @@ -2952,7 +2953,6 @@ int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) size += TICKET_BINDING_HASH_SZ; #endif #endif /* !NO_WOLFSSL_SERVER && !NO_TLS */ -#endif #ifndef NO_WOLFSSL_SERVER /* peerAuthOk and isPSK */ size += OPAQUE8_LEN; @@ -3041,6 +3041,7 @@ int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) c16toa(sess->ticketLen, data + idx); idx += OPAQUE16_LEN; XMEMCPY(data + idx, sess->ticket, sess->ticketLen); idx += sess->ticketLen; +#endif #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) #ifdef HAVE_SNI XMEMCPY(data + idx, sess->sniHash, TICKET_BINDING_HASH_SZ); @@ -3051,7 +3052,6 @@ int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) idx += TICKET_BINDING_HASH_SZ; #endif #endif /* !NO_WOLFSSL_SERVER && !NO_TLS */ -#endif #ifndef NO_WOLFSSL_SERVER data[idx++] = (byte)(sess->peerAuthOk | (sess->isPSK << 1)); #endif @@ -3345,6 +3345,7 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, goto end; } XMEMCPY(s->ticket, data + idx, s->ticketLen); idx += s->ticketLen; +#endif #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) #ifdef HAVE_SNI /* sniHash - SNI binding for stateful resumption (RFC 6066 section 3) */ @@ -3365,7 +3366,6 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, idx += TICKET_BINDING_HASH_SZ; #endif #endif /* !NO_WOLFSSL_SERVER && !NO_TLS */ -#endif #ifndef NO_WOLFSSL_SERVER if (i - idx < OPAQUE8_LEN) { ret = BUFFER_ERROR; @@ -3974,8 +3974,7 @@ void SetupSession(WOLFSSL* ssl) session->sessionCtxSz = ssl->sessionCtxSz; } #endif -#if defined(HAVE_SESSION_TICKET) && \ - !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) +#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) /* Bind the current SNI/ALPN to the session to verify on later resumption */ #ifdef HAVE_SNI (void)TicketSniHash(ssl, session->sniHash); @@ -3983,7 +3982,7 @@ void SetupSession(WOLFSSL* ssl) #ifdef HAVE_ALPN (void)TicketAlpnHash(ssl, session->alpnHash); #endif -#endif /* HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER && !NO_TLS */ +#endif /* !NO_WOLFSSL_SERVER && !NO_TLS */ session->timeout = ssl->timeout; #ifndef NO_ASN_TIME session->bornOn = LowResTimer(); diff --git a/tests/api/test_tls.c b/tests/api/test_tls.c index 590cde798b4..d103d6f0be6 100644 --- a/tests/api/test_tls.c +++ b/tests/api/test_tls.c @@ -5644,10 +5644,9 @@ int test_tls_set_session_min_downgrade(void) return EXPECT_RESULT(); } -#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ - (!defined(WOLFSSL_NO_TLS12) || defined(WOLFSSL_TLS13)) && \ - defined(HAVE_SNI) && defined(HAVE_SESSION_TICKET) && \ - !defined(NO_SESSION_CACHE) +#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(HAVE_SNI) && \ + !defined(NO_SESSION_CACHE) && (!defined(WOLFSSL_NO_TLS12) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET))) /* Accept-all SNI callback. */ static int accept_any_sni_cb(WOLFSSL* ssl, int* ret, void* arg) { @@ -5663,7 +5662,7 @@ int test_tls12_session_id_resumption_sni_mismatch(void) EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(WOLFSSL_NO_TLS12) && defined(HAVE_SNI) && \ - defined(HAVE_SESSION_TICKET) && !defined(NO_SESSION_CACHE) + !defined(NO_SESSION_CACHE) WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; WOLFSSL *ssl_c = NULL, *ssl_s = NULL; WOLFSSL_SESSION *sess = NULL; @@ -5680,8 +5679,10 @@ int test_tls12_session_id_resumption_sni_mismatch(void) ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); wolfSSL_CTX_set_servername_callback(ctx_s, accept_any_sni_cb); +#ifdef HAVE_SESSION_TICKET ExpectIntEQ(wolfSSL_NoTicketTLSv12(ssl_c), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_NoTicketTLSv12(ssl_s), WOLFSSL_SUCCESS); +#endif ExpectIntEQ(wolfSSL_UseSNI(ssl_c, WOLFSSL_SNI_HOST_NAME, sniA, (word16)XSTRLEN(sniA)), WOLFSSL_SUCCESS); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); @@ -5704,8 +5705,10 @@ int test_tls12_session_id_resumption_sni_mismatch(void) ExpectNotNull(ssl_s = wolfSSL_new(ctx_s)); wolfSSL_SetIOReadCtx(ssl_s, &test_ctx); wolfSSL_SetIOWriteCtx(ssl_s, &test_ctx); +#ifdef HAVE_SESSION_TICKET ExpectIntEQ(wolfSSL_NoTicketTLSv12(ssl_c), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_NoTicketTLSv12(ssl_s), WOLFSSL_SUCCESS); +#endif ExpectIntEQ(wolfSSL_UseSNI(ssl_c, WOLFSSL_SNI_HOST_NAME, sniB, (word16)XSTRLEN(sniB)), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_set_session(ssl_c, sess), WOLFSSL_SUCCESS); @@ -5962,7 +5965,7 @@ int test_tls12_session_id_resumption_alpn_mismatch(void) EXPECT_DECLS; #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ !defined(WOLFSSL_NO_TLS12) && defined(HAVE_ALPN) && \ - defined(HAVE_SESSION_TICKET) && !defined(NO_SESSION_CACHE) + !defined(NO_SESSION_CACHE) WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; WOLFSSL *ssl_c = NULL, *ssl_s = NULL; WOLFSSL_SESSION *sess = NULL; @@ -5978,8 +5981,10 @@ int test_tls12_session_id_resumption_alpn_mismatch(void) 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); +#ifdef HAVE_SESSION_TICKET ExpectIntEQ(wolfSSL_NoTicketTLSv12(ssl_c), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_NoTicketTLSv12(ssl_s), WOLFSSL_SUCCESS); +#endif ExpectIntEQ(wolfSSL_UseALPN(ssl_c, (char*)alpnA, (word32)XSTRLEN(alpnA), WOLFSSL_ALPN_FAILED_ON_MISMATCH), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_UseALPN(ssl_s, (char*)alpnA, (word32)XSTRLEN(alpnA), @@ -6006,8 +6011,10 @@ int test_tls12_session_id_resumption_alpn_mismatch(void) ExpectNotNull(ssl_s = wolfSSL_new(ctx_s)); wolfSSL_SetIOReadCtx(ssl_s, &test_ctx); wolfSSL_SetIOWriteCtx(ssl_s, &test_ctx); +#ifdef HAVE_SESSION_TICKET ExpectIntEQ(wolfSSL_NoTicketTLSv12(ssl_c), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_NoTicketTLSv12(ssl_s), WOLFSSL_SUCCESS); +#endif ExpectIntEQ(wolfSSL_UseALPN(ssl_c, (char*)alpnB, (word32)XSTRLEN(alpnB), WOLFSSL_ALPN_FAILED_ON_MISMATCH), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_UseALPN(ssl_s, (char*)alpnB, (word32)XSTRLEN(alpnB), diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 6a2cd709e14..e66f67224a2 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3989,13 +3989,8 @@ WOLFSSL_LOCAL int SetupClientSecureRenegotiation(WOLFSSL* ssl); #endif /* HAVE_SECURE_RENEGOTIATION */ -#ifdef HAVE_SESSION_TICKET -/* Max peer cert size for ticket: 2KB is reasonable for most RSA/ECC certs */ -#ifndef MAX_TICKET_PEER_CERT_SZ -#define MAX_TICKET_PEER_CERT_SZ 2048 -#endif #if defined(HAVE_SNI) || defined(HAVE_ALPN) -/* Hash algorithm used for SNI/ALPN binding in session tickets. +/* Hash algorithm used for SNI/ALPN binding in sessions and tickets. * Pick the best available at compile time. */ #ifndef TICKET_BINDING_HASH_TYPE #if !defined(NO_SHA256) @@ -4013,6 +4008,12 @@ WOLFSSL_LOCAL int SetupClientSecureRenegotiation(WOLFSSL* ssl); #endif #endif +#ifdef HAVE_SESSION_TICKET +/* Max peer cert size for ticket: 2KB is reasonable for most RSA/ECC certs */ +#ifndef MAX_TICKET_PEER_CERT_SZ +#define MAX_TICKET_PEER_CERT_SZ 2048 +#endif + /* Our ticket format. All members need to be a byte or array of byte to * avoid alignment issues */ typedef struct InternalTicket { @@ -5404,13 +5405,13 @@ struct WOLFSSL_SESSION { byte* ticket; word16 ticketLen; word16 ticketLenAlloc; /* is dynamic */ +#endif /* HAVE_SESSION_TICKET */ #ifdef HAVE_SNI byte sniHash[TICKET_BINDING_HASH_SZ]; /* SNI at issue */ #endif /* HAVE_SNI */ - #ifdef HAVE_ALPN +#ifdef HAVE_ALPN byte alpnHash[TICKET_BINDING_HASH_SZ]; /* ALPN at issue */ - #endif /* HAVE_ALPN */ -#endif /* HAVE_SESSION_TICKET */ +#endif /* HAVE_ALPN */ #ifdef SESSION_CERTS WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */ @@ -7748,6 +7749,7 @@ WOLFSSL_LOCAL int DoClientTicket_ex(const WOLFSSL* ssl, PreSharedKey* psk, #endif WOLFSSL_LOCAL int DoClientTicket(WOLFSSL* ssl, const byte* input, word32 len); +#endif /* HAVE_SESSION_TICKET */ /* TicketSniHash, TicketAlpnHash, and VerifyTicketBinding are defined in * internal.c only when !NO_WOLFSSL_SERVER && !NO_TLS - gate the * declarations to match so client-only or no-TLS builds don't compile in @@ -7759,11 +7761,10 @@ WOLFSSL_LOCAL int TicketSniHash(WOLFSSL* ssl, byte* dst); #ifdef HAVE_ALPN WOLFSSL_LOCAL int TicketAlpnHash(WOLFSSL* ssl, byte* dst); #endif -#if defined(HAVE_SNI) || defined(HAVE_ALPN) +#if defined(HAVE_SESSION_TICKET) && (defined(HAVE_SNI) || defined(HAVE_ALPN)) WOLFSSL_LOCAL int VerifyTicketBinding(WOLFSSL* ssl); #endif #endif /* !NO_WOLFSSL_SERVER && !NO_TLS */ -#endif /* HAVE_SESSION_TICKET */ WOLFSSL_LOCAL int SendData(WOLFSSL* ssl, const void* data, size_t sz); #ifdef WOLFSSL_THREADED_CRYPT WOLFSSL_LOCAL int SendAsyncData(WOLFSSL* ssl); From ab3b3d6a120b05b35a109b869b5c5db54338f791 Mon Sep 17 00:00:00 2001 From: Paul Adelsbach Date: Wed, 14 Oct 2026 09:43:02 -0700 Subject: [PATCH 2/3] PR feedback: check binding in OLD_HELLO_ALLOWED --- src/internal.c | 113 +++++++++++++++---------------------------- tests/api/test_tls.c | 100 ++++++++++++++++++++++++++++++++++++++ tests/api/test_tls.h | 2 + wolfssl/internal.h | 2 +- 4 files changed, 143 insertions(+), 74 deletions(-) diff --git a/src/internal.c b/src/internal.c index b85bf461701..88e02e9b1e2 100644 --- a/src/internal.c +++ b/src/internal.c @@ -42698,6 +42698,12 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl) ssl->options.resuming = 0; ssl->options.peerAuthGood = 0; } + #if defined(HAVE_SNI) || defined(HAVE_ALPN) + else if (VerifyTicketBinding(ssl) != 0) { + WOLFSSL_MSG("Resumed session binding mismatch, full handshake"); + ssl->options.resuming = 0; + } + #endif else { if (MatchSuite(ssl, &clSuites) < 0) { WOLFSSL_MSG("Unsupported cipher suite, OldClientHello"); @@ -42848,33 +42854,12 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl) return ret; } #if defined(HAVE_SNI) || defined(HAVE_ALPN) - /* Do not resume session if sniHash/alpnHash do not match. */ - #ifdef HAVE_SESSION_TICKET - if (!ssl->options.useTicket) - #endif - { - byte curHash[TICKET_BINDING_HASH_SZ]; -#ifdef HAVE_SNI - if (TicketSniHash(ssl, curHash) != 0 || - XMEMCMP(curHash, session->sniHash, - TICKET_BINDING_HASH_SZ) != 0) { - WOLFSSL_MSG("Resumed session SNI mismatch, full handshake"); - ssl->options.resuming = 0; - return ret; - } -#endif -#ifdef HAVE_ALPN - if (ssl->options.resuming && - (TicketAlpnHash(ssl, curHash) != 0 || - XMEMCMP(curHash, session->alpnHash, - TICKET_BINDING_HASH_SZ) != 0)) { - WOLFSSL_MSG("Resumed session ALPN mismatch, full handshake"); - ssl->options.resuming = 0; - return ret; - } -#endif + if (VerifyTicketBinding(ssl) != 0) { + WOLFSSL_MSG("Resumed session binding mismatch, full handshake"); + ssl->options.resuming = 0; + return ret; } -#endif /* HAVE_SNI || HAVE_ALPN */ +#endif #if !defined(WOLFSSL_NO_TICKET_EXPIRE) && !defined(NO_ASN_TIME) /* check if the ticket is valid */ @@ -44377,6 +44362,35 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl) } #endif +#if defined(HAVE_SNI) || defined(HAVE_ALPN) + /* Returns 0 when SNI/ALPN match ssl->session. Call after ALPN_Select. */ + int VerifyTicketBinding(WOLFSSL* ssl) + { + byte curHash[TICKET_BINDING_HASH_SZ]; + + if (!ssl->options.resuming) + return 0; + +#ifdef HAVE_SNI + if (TicketSniHash(ssl, curHash) != 0 || + XMEMCMP(curHash, ssl->session->sniHash, + TICKET_BINDING_HASH_SZ) != 0) { + WOLFSSL_MSG("Resumed session SNI mismatch"); + return WOLFSSL_FATAL_ERROR; + } +#endif +#ifdef HAVE_ALPN + if (TicketAlpnHash(ssl, curHash) != 0 || + XMEMCMP(curHash, ssl->session->alpnHash, + TICKET_BINDING_HASH_SZ) != 0) { + WOLFSSL_MSG("Resumed session ALPN mismatch"); + return WOLFSSL_FATAL_ERROR; + } +#endif + return 0; + } +#endif + #ifdef HAVE_SESSION_TICKET #ifdef WOLFSSL_TICKET_HAVE_ID @@ -44441,53 +44455,6 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl) return ret; } -#if defined(HAVE_SNI) || defined(HAVE_ALPN) - /* Server-side TLS 1.2 ticket-resumption binding check. Confirms the - * SNI/ALPN bound to the resumed session matches what was negotiated - * for the current connection. Must be called after extension - * parsing and ALPN_Select so the negotiated values are available, - * and only once DoClientTicketFinalize has populated - * ssl->session->sniHash/alpnHash from the decrypted ticket. - * - * Other resumption paths handle the same check themselves and do - * not use this function: - * - TLS 1.2 session-ID (stateful): HandleTlsResumption compares - * against the cached session at lookup time. - * - TLS 1.3 PSK: DoPreSharedKeys compares against each candidate - * ticket's bound hashes before committing, allowing the server - * to skip mismatching PSKs and pick the next one. - * - * Returns 0 on match, WOLFSSL_FATAL_ERROR on mismatch. The caller - * is responsible for the policy on mismatch -- RFC 6066 Section 3 - * mandates declining the resumption and proceeding with a full - * handshake rather than aborting. */ - int VerifyTicketBinding(WOLFSSL* ssl) - { - byte curHash[TICKET_BINDING_HASH_SZ]; - - if (!ssl->options.resuming) - return 0; - -#ifdef HAVE_SNI - if (TicketSniHash(ssl, curHash) != 0 || - XMEMCMP(curHash, ssl->session->sniHash, - TICKET_BINDING_HASH_SZ) != 0) { - WOLFSSL_MSG("Ticket SNI mismatch"); - return WOLFSSL_FATAL_ERROR; - } -#endif -#ifdef HAVE_ALPN - if (TicketAlpnHash(ssl, curHash) != 0 || - XMEMCMP(curHash, ssl->session->alpnHash, - TICKET_BINDING_HASH_SZ) != 0) { - WOLFSSL_MSG("Ticket ALPN mismatch"); - return WOLFSSL_FATAL_ERROR; - } -#endif - return 0; - } -#endif - /* Returns 1 when the default ticket encryption callback is in use with a * hint of at least half the key lifetime. */ int DefTicketHintTooLarge(WOLFSSL* ssl) diff --git a/tests/api/test_tls.c b/tests/api/test_tls.c index d103d6f0be6..2137319bd80 100644 --- a/tests/api/test_tls.c +++ b/tests/api/test_tls.c @@ -6037,6 +6037,106 @@ int test_tls12_session_id_resumption_alpn_mismatch(void) return EXPECT_RESULT(); } +#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ + defined(OLD_HELLO_ALLOWED) && !defined(WOLFSSL_NO_TLS12) && \ + defined(HAVE_SNI) && defined(HAVE_ALPN) && !defined(NO_SESSION_CACHE) +/* Resume a TLS 1.2 session ID with an SSLv2 ClientHello (no extensions). */ +static int test_tls12_old_hello_resume(int useSni, int useAlpn) +{ + EXPECT_DECLS; + WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; + WOLFSSL *ssl_c = NULL, *ssl_s = NULL; + struct test_memio_ctx test_ctx; + const char* sni = "public.example"; + const char alpn[] = "h2"; + byte hello[2 + 9 + 3 + ID_LEN + RAN_LEN]; + /* SSLv2 header, ClientHello, TLS 1.2, suite/ID/random lengths */ + const byte hdr[] = { + 0x80, (byte)(sizeof(hello) - 2), OLD_HELLO_ID, + SSLv3_MAJOR, TLSv1_2_MINOR, 0, 3, 0, ID_LEN, 0, RAN_LEN + }; + int idx = 0; + + 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); + wolfSSL_CTX_set_servername_callback(ctx_s, accept_any_sni_cb); +#ifdef HAVE_SESSION_TICKET + ExpectIntEQ(wolfSSL_NoTicketTLSv12(ssl_c), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_NoTicketTLSv12(ssl_s), WOLFSSL_SUCCESS); +#endif +#ifdef HAVE_EXTENDED_MASTER + /* An SSLv2 ClientHello cannot request EMS. */ + ExpectIntEQ(wolfSSL_DisableExtendedMasterSecret(ssl_c), WOLFSSL_SUCCESS); +#endif + if (useSni) { + ExpectIntEQ(wolfSSL_UseSNI(ssl_c, WOLFSSL_SNI_HOST_NAME, sni, + (word16)XSTRLEN(sni)), WOLFSSL_SUCCESS); + } + if (useAlpn) { + ExpectIntEQ(wolfSSL_UseALPN(ssl_c, (char*)alpn, (word32)XSTRLEN(alpn), + WOLFSSL_ALPN_FAILED_ON_MISMATCH), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_UseALPN(ssl_s, (char*)alpn, (word32)XSTRLEN(alpn), + WOLFSSL_ALPN_FAILED_ON_MISMATCH), WOLFSSL_SUCCESS); + } + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + ExpectIntEQ(ssl_c->session->sessionIDSz, ID_LEN); + + if (EXPECT_SUCCESS()) { + XMEMCPY(hello, hdr, sizeof(hdr)); + idx = (int)sizeof(hdr); + hello[idx++] = 0; /* TLS suite in SSLv2 three byte form */ + hello[idx++] = ssl_c->options.cipherSuite0; + hello[idx++] = ssl_c->options.cipherSuite; + XMEMCPY(hello + idx, ssl_c->session->sessionID, ID_LEN); + idx += ID_LEN; + XMEMSET(hello + idx, 0x5a, RAN_LEN); + } + + wolfSSL_free(ssl_c); ssl_c = NULL; + wolfSSL_free(ssl_s); ssl_s = NULL; + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + ExpectNotNull(ssl_s = wolfSSL_new(ctx_s)); + wolfSSL_SetIOReadCtx(ssl_s, &test_ctx); + wolfSSL_SetIOWriteCtx(ssl_s, &test_ctx); + if (useAlpn) { + ExpectIntEQ(wolfSSL_UseALPN(ssl_s, (char*)alpn, (word32)XSTRLEN(alpn), + WOLFSSL_ALPN_FAILED_ON_MISMATCH), WOLFSSL_SUCCESS); + } + ExpectIntEQ(test_memio_inject_message(&test_ctx, 0, (const char*)hello, + (int)sizeof(hello)), 0); + ExpectIntEQ(wolfSSL_accept(ssl_s), WOLFSSL_FATAL_ERROR); + ExpectIntEQ(wolfSSL_get_error(ssl_s, WOLFSSL_FATAL_ERROR), + WOLFSSL_ERROR_WANT_READ); + ExpectIntEQ(wolfSSL_session_reused(ssl_s), !useSni && !useAlpn); + + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_c); + wolfSSL_CTX_free(ctx_s); + return EXPECT_RESULT(); +} +#endif + +/* SSLv2 ClientHello resumption must not bypass the SNI/ALPN binding. */ +int test_tls12_old_hello_resumption_binding(void) +{ + EXPECT_DECLS; +#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ + defined(OLD_HELLO_ALLOWED) && !defined(WOLFSSL_NO_TLS12) && \ + defined(HAVE_SNI) && defined(HAVE_ALPN) && !defined(NO_SESSION_CACHE) + /* { useSni, useAlpn } */ + static const byte cases[][2] = { { 0, 0 }, { 1, 0 }, { 0, 1 } }; + size_t i; + + for (i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) { + ExpectIntEQ(test_tls12_old_hello_resume(cases[i][0], cases[i][1]), + TEST_SUCCESS); + } +#endif + return EXPECT_RESULT(); +} + /* TLS 1.3 PSK resumption must fall back to a full handshake if the ALPN * protocol negotiated for the resumed connection does not match the ALPN * bound to the original session. Mirrors diff --git a/tests/api/test_tls.h b/tests/api/test_tls.h index 4c9133427b6..16e3504e4cb 100644 --- a/tests/api/test_tls.h +++ b/tests/api/test_tls.h @@ -97,6 +97,7 @@ int test_tls12_declined_ticket_auth_not_reminted(void); int test_tls13_session_resumption_sni_mismatch(void); int test_tls13_resumption_with_alpn(void); int test_tls12_session_id_resumption_alpn_mismatch(void); +int test_tls12_old_hello_resumption_binding(void); int test_tls13_session_resumption_alpn_mismatch(void); int test_tls_set_curves_list_ecc_fallback(void); int test_tls12_corrupted_finished(void); @@ -206,6 +207,7 @@ int test_tls_param_flags_crl_check(void); TEST_DECL_GROUP("tls", test_tls13_session_resumption_sni_mismatch), \ TEST_DECL_GROUP("tls", test_tls13_resumption_with_alpn), \ TEST_DECL_GROUP("tls", test_tls12_session_id_resumption_alpn_mismatch),\ + TEST_DECL_GROUP("tls", test_tls12_old_hello_resumption_binding), \ TEST_DECL_GROUP("tls", test_tls13_session_resumption_alpn_mismatch), \ TEST_DECL_GROUP("tls", test_tls_set_curves_list_ecc_fallback), \ TEST_DECL_GROUP("tls", test_tls12_corrupted_finished), \ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index e66f67224a2..3ea829c0b4e 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -7761,7 +7761,7 @@ WOLFSSL_LOCAL int TicketSniHash(WOLFSSL* ssl, byte* dst); #ifdef HAVE_ALPN WOLFSSL_LOCAL int TicketAlpnHash(WOLFSSL* ssl, byte* dst); #endif -#if defined(HAVE_SESSION_TICKET) && (defined(HAVE_SNI) || defined(HAVE_ALPN)) +#if defined(HAVE_SNI) || defined(HAVE_ALPN) WOLFSSL_LOCAL int VerifyTicketBinding(WOLFSSL* ssl); #endif #endif /* !NO_WOLFSSL_SERVER && !NO_TLS */ From 581908788a22c5c242d736645aafe4d1cf289b56 Mon Sep 17 00:00:00 2001 From: Paul Adelsbach Date: Wed, 28 Oct 2026 13:20:59 -0700 Subject: [PATCH 3/3] Add cleanup after failed SNI/ALPN check, add comments to #endif's --- src/internal.c | 22 ++++++++----- src/ssl_sess.c | 48 ++++++++++++++-------------- tests/api/test_tls.c | 75 ++++++++++++++++++++++++++++++++++++++++++++ tests/api/test_tls.h | 2 ++ 4 files changed, 115 insertions(+), 32 deletions(-) diff --git a/src/internal.c b/src/internal.c index 88e02e9b1e2..cd897621c54 100644 --- a/src/internal.c +++ b/src/internal.c @@ -44366,6 +44366,7 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl) /* Returns 0 when SNI/ALPN match ssl->session. Call after ALPN_Select. */ int VerifyTicketBinding(WOLFSSL* ssl) { + int ret = 0; byte curHash[TICKET_BINDING_HASH_SZ]; if (!ssl->options.resuming) @@ -44376,20 +44377,25 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl) XMEMCMP(curHash, ssl->session->sniHash, TICKET_BINDING_HASH_SZ) != 0) { WOLFSSL_MSG("Resumed session SNI mismatch"); - return WOLFSSL_FATAL_ERROR; + ret = WOLFSSL_FATAL_ERROR; } -#endif +#endif /* HAVE_SNI */ #ifdef HAVE_ALPN - if (TicketAlpnHash(ssl, curHash) != 0 || + if (ret == 0 && (TicketAlpnHash(ssl, curHash) != 0 || XMEMCMP(curHash, ssl->session->alpnHash, - TICKET_BINDING_HASH_SZ) != 0) { + TICKET_BINDING_HASH_SZ) != 0)) { WOLFSSL_MSG("Resumed session ALPN mismatch"); - return WOLFSSL_FATAL_ERROR; + ret = WOLFSSL_FATAL_ERROR; } -#endif - return 0; +#endif /* HAVE_ALPN */ +#ifdef SESSION_CERTS + /* Drop the declined session's peer before the full handshake. */ + if (ret != 0) + ResetSessionCertChain(ssl); +#endif /* SESSION_CERTS */ + return ret; } -#endif +#endif /* HAVE_SNI || HAVE_ALPN */ #ifdef HAVE_SESSION_TICKET diff --git a/src/ssl_sess.c b/src/ssl_sess.c index e0b25a7facf..55c7dbed0a3 100644 --- a/src/ssl_sess.c +++ b/src/ssl_sess.c @@ -2931,27 +2931,27 @@ int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) #else /* ticketSeen Hi 32 bits | ticketSeen Lo 32 bits | ticketAdd */ size += OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE32_LEN; -#endif +#endif /* WOLFSSL_32BIT_MILLI_TIME */ /* ticketNonce */ size += OPAQUE8_LEN + sess->ticketNonce.len; -#endif +#endif /* WOLFSSL_TLS13 */ #ifdef WOLFSSL_EARLY_DATA size += OPAQUE32_LEN; -#endif -#endif +#endif /* WOLFSSL_EARLY_DATA */ +#endif /* HAVE_SESSION_TICKET || !NO_PSK */ #ifdef HAVE_SESSION_TICKET /* ticket len | ticket */ size += OPAQUE16_LEN + sess->ticketLen; -#endif +#endif /* HAVE_SESSION_TICKET */ #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) #ifdef HAVE_SNI /* sniHash */ size += TICKET_BINDING_HASH_SZ; -#endif +#endif /* HAVE_SNI */ #ifdef HAVE_ALPN /* alpnHash */ size += TICKET_BINDING_HASH_SZ; -#endif +#endif /* HAVE_ALPN */ #endif /* !NO_WOLFSSL_SERVER && !NO_TLS */ #ifndef NO_WOLFSSL_SERVER /* peerAuthOk and isPSK */ @@ -3025,38 +3025,38 @@ int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) idx += OPAQUE32_LEN; c32toa((word32)sess->ticketSeen, data + idx); idx += OPAQUE32_LEN; -#endif +#endif /* WOLFSSL_32BIT_MILLI_TIME */ c32toa(sess->ticketAdd, data + idx); idx += OPAQUE32_LEN; data[idx++] = sess->ticketNonce.len; XMEMCPY(data + idx, sess->ticketNonce.data, sess->ticketNonce.len); idx += sess->ticketNonce.len; -#endif +#endif /* WOLFSSL_TLS13 */ #ifdef WOLFSSL_EARLY_DATA c32toa(sess->maxEarlyDataSz, data + idx); idx += OPAQUE32_LEN; -#endif -#endif +#endif /* WOLFSSL_EARLY_DATA */ +#endif /* HAVE_SESSION_TICKET || !NO_PSK */ #ifdef HAVE_SESSION_TICKET c16toa(sess->ticketLen, data + idx); idx += OPAQUE16_LEN; XMEMCPY(data + idx, sess->ticket, sess->ticketLen); idx += sess->ticketLen; -#endif +#endif /* HAVE_SESSION_TICKET */ #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) #ifdef HAVE_SNI XMEMCPY(data + idx, sess->sniHash, TICKET_BINDING_HASH_SZ); idx += TICKET_BINDING_HASH_SZ; -#endif +#endif /* HAVE_SNI */ #ifdef HAVE_ALPN XMEMCPY(data + idx, sess->alpnHash, TICKET_BINDING_HASH_SZ); idx += TICKET_BINDING_HASH_SZ; -#endif +#endif /* HAVE_ALPN */ #endif /* !NO_WOLFSSL_SERVER && !NO_TLS */ #ifndef NO_WOLFSSL_SERVER data[idx++] = (byte)(sess->peerAuthOk | (sess->isPSK << 1)); #endif } -#endif +#endif /* HAVE_EXT_CACHE */ (void)sess; (void)p; @@ -3273,7 +3273,7 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, idx += OPAQUE32_LEN; s->ticketSeen = ((sword64)seenHi << 32) + seenLo; } -#endif +#endif /* WOLFSSL_32BIT_MILLI_TIME */ if (i - idx < OPAQUE32_LEN) { ret = BUFFER_ERROR; @@ -3305,7 +3305,7 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, #endif /* defined(WOLFSSL_TICKET_NONCE_MALLOC) && FIPS_VERSION_GE(5,3) */ idx += s->ticketNonce.len; -#endif +#endif /* WOLFSSL_TLS13 */ #ifdef WOLFSSL_EARLY_DATA if (i - idx < OPAQUE32_LEN) { ret = BUFFER_ERROR; @@ -3313,8 +3313,8 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, } ato32(data + idx, &s->maxEarlyDataSz); idx += OPAQUE32_LEN; -#endif -#endif +#endif /* WOLFSSL_EARLY_DATA */ +#endif /* HAVE_SESSION_TICKET || !NO_PSK */ #ifdef HAVE_SESSION_TICKET /* ticket len */ if (i - idx < OPAQUE16_LEN) { @@ -3345,7 +3345,7 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, goto end; } XMEMCPY(s->ticket, data + idx, s->ticketLen); idx += s->ticketLen; -#endif +#endif /* HAVE_SESSION_TICKET */ #if !defined(NO_WOLFSSL_SERVER) && !defined(NO_TLS) #ifdef HAVE_SNI /* sniHash - SNI binding for stateful resumption (RFC 6066 section 3) */ @@ -3355,7 +3355,7 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, } XMEMCPY(s->sniHash, data + idx, TICKET_BINDING_HASH_SZ); idx += TICKET_BINDING_HASH_SZ; -#endif +#endif /* HAVE_SNI */ #ifdef HAVE_ALPN /* alpnHash - ALPN binding for stateful resumption */ if (i - idx < TICKET_BINDING_HASH_SZ) { @@ -3364,7 +3364,7 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, } XMEMCPY(s->alpnHash, data + idx, TICKET_BINDING_HASH_SZ); idx += TICKET_BINDING_HASH_SZ; -#endif +#endif /* HAVE_ALPN */ #endif /* !NO_WOLFSSL_SERVER && !NO_TLS */ #ifndef NO_WOLFSSL_SERVER if (i - idx < OPAQUE8_LEN) { @@ -3978,10 +3978,10 @@ void SetupSession(WOLFSSL* ssl) /* Bind the current SNI/ALPN to the session to verify on later resumption */ #ifdef HAVE_SNI (void)TicketSniHash(ssl, session->sniHash); -#endif +#endif /* HAVE_SNI */ #ifdef HAVE_ALPN (void)TicketAlpnHash(ssl, session->alpnHash); -#endif +#endif /* HAVE_ALPN */ #endif /* !NO_WOLFSSL_SERVER && !NO_TLS */ session->timeout = ssl->timeout; #ifndef NO_ASN_TIME diff --git a/tests/api/test_tls.c b/tests/api/test_tls.c index 2137319bd80..f092088bd10 100644 --- a/tests/api/test_tls.c +++ b/tests/api/test_tls.c @@ -5730,6 +5730,81 @@ int test_tls12_session_id_resumption_sni_mismatch(void) return EXPECT_RESULT(); } +/* Declined session ID resumption must not keep the cached peer cert. */ +int test_tls12_session_id_sni_mismatch_peer_cert(void) +{ + EXPECT_DECLS; +#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ + !defined(WOLFSSL_NO_TLS12) && defined(HAVE_SNI) && \ + !defined(NO_SESSION_CACHE) && defined(SESSION_CERTS) && \ + defined(KEEP_PEER_CERT) && !defined(WOLFSSL_NO_CLIENT_AUTH) && \ + !defined(NO_RSA) + WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; + WOLFSSL *ssl_c = NULL, *ssl_s = NULL; + WOLFSSL_SESSION *sess = NULL; + WOLFSSL_X509* peer = NULL; + struct test_memio_ctx test_ctx; + const char* sniA = "private.example"; + const char* sniB = "public.example"; + + /* Full handshake with client auth under SNI A. */ + 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); + wolfSSL_CTX_set_servername_callback(ctx_s, accept_any_sni_cb); + ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx_s, cliCertFile, NULL), + WOLFSSL_SUCCESS); + wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_PEER | + WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); + ExpectIntEQ(wolfSSL_use_certificate_file(ssl_c, cliCertFile, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_use_PrivateKey_file(ssl_c, cliKeyFile, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); +#ifdef HAVE_SESSION_TICKET + ExpectIntEQ(wolfSSL_NoTicketTLSv12(ssl_c), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_NoTicketTLSv12(ssl_s), WOLFSSL_SUCCESS); +#endif + ExpectIntEQ(wolfSSL_UseSNI(ssl_c, WOLFSSL_SNI_HOST_NAME, + sniA, (word16)XSTRLEN(sniA)), WOLFSSL_SUCCESS); + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + ExpectNotNull(peer = wolfSSL_get_peer_certificate(ssl_s)); + wolfSSL_X509_free(peer); + peer = NULL; + ExpectNotNull(sess = wolfSSL_get1_session(ssl_c)); + + wolfSSL_free(ssl_c); ssl_c = NULL; + wolfSSL_free(ssl_s); ssl_s = NULL; + + /* Offer the session under SNI B to a server not asking for a cert. */ + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + ExpectNotNull(ssl_c = wolfSSL_new(ctx_c)); + wolfSSL_SetIOReadCtx(ssl_c, &test_ctx); + wolfSSL_SetIOWriteCtx(ssl_c, &test_ctx); + ExpectNotNull(ssl_s = wolfSSL_new(ctx_s)); + wolfSSL_SetIOReadCtx(ssl_s, &test_ctx); + wolfSSL_SetIOWriteCtx(ssl_s, &test_ctx); + wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_NONE, NULL); +#ifdef HAVE_SESSION_TICKET + ExpectIntEQ(wolfSSL_NoTicketTLSv12(ssl_c), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_NoTicketTLSv12(ssl_s), WOLFSSL_SUCCESS); +#endif + ExpectIntEQ(wolfSSL_UseSNI(ssl_c, WOLFSSL_SNI_HOST_NAME, + sniB, (word16)XSTRLEN(sniB)), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_set_session(ssl_c, sess), WOLFSSL_SUCCESS); + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + ExpectIntEQ(wolfSSL_session_reused(ssl_s), 0); + ExpectNull(peer = wolfSSL_get_peer_certificate(ssl_s)); + wolfSSL_X509_free(peer); + + wolfSSL_SESSION_free(sess); + wolfSSL_free(ssl_c); + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_c); + wolfSSL_CTX_free(ctx_s); +#endif + return EXPECT_RESULT(); +} + /* A TLS 1.2 ticket that decrypts is copied to the session before it can be * declined, and the server writes its next ticket before SetupSession() * resets that. The new ticket must record only what the full handshake diff --git a/tests/api/test_tls.h b/tests/api/test_tls.h index 16e3504e4cb..69dcdde4835 100644 --- a/tests/api/test_tls.h +++ b/tests/api/test_tls.h @@ -93,6 +93,7 @@ int test_tls12_server_hello_tls13_suite(void); int test_tls12_client_hello_no_tls13_suites(void); int test_tls_set_session_min_downgrade(void); int test_tls12_session_id_resumption_sni_mismatch(void); +int test_tls12_session_id_sni_mismatch_peer_cert(void); int test_tls12_declined_ticket_auth_not_reminted(void); int test_tls13_session_resumption_sni_mismatch(void); int test_tls13_resumption_with_alpn(void); @@ -203,6 +204,7 @@ int test_tls_param_flags_crl_check(void); TEST_DECL_GROUP("tls", test_tls12_client_hello_no_tls13_suites), \ TEST_DECL_GROUP("tls", test_tls_set_session_min_downgrade), \ TEST_DECL_GROUP("tls", test_tls12_session_id_resumption_sni_mismatch), \ + TEST_DECL_GROUP("tls", test_tls12_session_id_sni_mismatch_peer_cert), \ TEST_DECL_GROUP("tls", test_tls12_declined_ticket_auth_not_reminted), \ TEST_DECL_GROUP("tls", test_tls13_session_resumption_sni_mismatch), \ TEST_DECL_GROUP("tls", test_tls13_resumption_with_alpn), \