Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 92 additions & 117 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -42847,32 +42853,13 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
ssl->options.peerAuthGood = 0;
return ret;
}
#if defined(HAVE_SESSION_TICKET) && \
(defined(HAVE_SNI) || defined(HAVE_ALPN))
/* Do not resume session if sniHash/alpnHash do not match. */
if (!ssl->options.useTicket) {
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 defined(HAVE_SNI) || defined(HAVE_ALPN)
if (VerifyTicketBinding(ssl) != 0) {
WOLFSSL_MSG("Resumed session binding mismatch, full handshake");
ssl->options.resuming = 0;
return ret;
}
Comment thread
philljj marked this conversation as resolved.
Resolved
#endif /* HAVE_SESSION_TICKET && (HAVE_SNI || HAVE_ALPN) */
#endif

#if !defined(WOLFSSL_NO_TICKET_EXPIRE) && !defined(NO_ASN_TIME)
/* check if the ticket is valid */
Expand Down Expand Up @@ -44330,70 +44317,6 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)

#endif /* !WOLFSSL_NO_TLS12 */

#ifdef HAVE_SESSION_TICKET

#ifdef WOLFSSL_TICKET_HAVE_ID
static void GetRealSessionID(WOLFSSL* ssl, const byte** id, byte* idSz)
{
if (ssl->session->haveAltSessionID) {
*id = ssl->session->altSessionID;
*idSz = ID_LEN;
}
else if (IsAtLeastTLSv1_3(ssl->version)) {
/* In TLS 1.3 ssl->session->sessionID only holds the client's
* legacy_session_id that we echo in the ServerHello. It is chosen
* by the peer and must not be used to identify the session in
* the ticket or the session cache. Report no ID so that
* SetupTicket generates a random one. */
*id = NULL;
*idSz = 0;
}
else if (ssl->arrays != NULL) {
*id = ssl->arrays->sessionID;
*idSz = ssl->arrays->sessionIDSz;
}
else {
*id = ssl->session->sessionID;
*idSz = ssl->session->sessionIDSz;
}
}
#endif

int SetupTicket(WOLFSSL* ssl)
{
int ret = 0;

(void)ssl;

#ifdef WOLFSSL_TLS13
{
/* Client adds to ticket age to obfuscate. */
byte ageAdd[AGEADD_LEN]; /* Obfuscation of age */
ret = wc_RNG_GenerateBlock(ssl->rng, ageAdd, AGEADD_LEN);
if (ret != 0)
return ret;
ato32(ageAdd, &ssl->session->ticketAdd);
}
#endif

#ifdef WOLFSSL_TICKET_HAVE_ID
{
const byte* id = NULL;
byte idSz = 0;

GetRealSessionID(ssl, &id, &idSz);
if (idSz == 0) {
ret = wc_RNG_GenerateBlock(ssl->rng, ssl->session->altSessionID,
ID_LEN);
if (ret != 0)
return ret;
ssl->session->haveAltSessionID = 1;
}
}
#endif
return ret;
}

#ifdef HAVE_SNI
/* Hash server-selected SNI; zeros dst when none. */
int TicketSniHash(WOLFSSL* ssl, byte* dst)
Expand Down Expand Up @@ -44440,27 +44363,10 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
#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
* 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. */
/* 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)
Expand All @@ -44470,22 +44376,91 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
if (TicketSniHash(ssl, curHash) != 0 ||
XMEMCMP(curHash, ssl->session->sniHash,
TICKET_BINDING_HASH_SZ) != 0) {
WOLFSSL_MSG("Ticket SNI mismatch");
return WOLFSSL_FATAL_ERROR;
WOLFSSL_MSG("Resumed session SNI mismatch");
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) {
WOLFSSL_MSG("Ticket ALPN mismatch");
return WOLFSSL_FATAL_ERROR;
TICKET_BINDING_HASH_SZ) != 0)) {
WOLFSSL_MSG("Resumed session ALPN mismatch");
ret = WOLFSSL_FATAL_ERROR;
}
#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 /* HAVE_SNI || HAVE_ALPN */

#ifdef HAVE_SESSION_TICKET

#ifdef WOLFSSL_TICKET_HAVE_ID
static void GetRealSessionID(WOLFSSL* ssl, const byte** id, byte* idSz)
{
if (ssl->session->haveAltSessionID) {
*id = ssl->session->altSessionID;
*idSz = ID_LEN;
}
else if (IsAtLeastTLSv1_3(ssl->version)) {
/* In TLS 1.3 ssl->session->sessionID only holds the client's
* legacy_session_id that we echo in the ServerHello. It is chosen
* by the peer and must not be used to identify the session in
* the ticket or the session cache. Report no ID so that
* SetupTicket generates a random one. */
*id = NULL;
*idSz = 0;
}
else if (ssl->arrays != NULL) {
*id = ssl->arrays->sessionID;
*idSz = ssl->arrays->sessionIDSz;
}
else {
*id = ssl->session->sessionID;
*idSz = ssl->session->sessionIDSz;
}
#endif
return 0;
}
#endif

int SetupTicket(WOLFSSL* ssl)
{
int ret = 0;

(void)ssl;

#ifdef WOLFSSL_TLS13
{
/* Client adds to ticket age to obfuscate. */
byte ageAdd[AGEADD_LEN]; /* Obfuscation of age */
ret = wc_RNG_GenerateBlock(ssl->rng, ageAdd, AGEADD_LEN);
if (ret != 0)
return ret;
ato32(ageAdd, &ssl->session->ticketAdd);
}
#endif

#ifdef WOLFSSL_TICKET_HAVE_ID
{
const byte* id = NULL;
byte idSz = 0;

GetRealSessionID(ssl, &id, &idSz);
if (idSz == 0) {
ret = wc_RNG_GenerateBlock(ssl->rng, ssl->session->altSessionID,
ID_LEN);
if (ret != 0)
return ret;
ssl->session->haveAltSessionID = 1;
}
}
#endif
return ret;
}

/* 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)
Expand Down
Loading
Loading