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
174 changes: 102 additions & 72 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -40684,8 +40684,12 @@ int SetTicket(WOLFSSL* ssl, const byte* ticket, word32 length)
if (length > sizeof(ssl->session->staticTicket)) {
byte* sessionTicket =
(byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
if (sessionTicket == NULL)
if (sessionTicket == NULL) {
/* The old ticket is gone; its length is not valid for the static
* buffer */
ssl->session->ticketLen = 0;
return MEMORY_E;
}
ssl->session->ticket = sessionTicket;
ssl->session->ticketLenAlloc = (word16)length;
}
Expand Down Expand Up @@ -45204,37 +45208,114 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
InternalTicket* it;
ExternalTicket* et;
int encLen;
int encMax;
int ret;
int error;
word32 itHash = 0;
byte zeros[WOLFSSL_TICKET_MAC_SZ]; /* biggest cmp size */
int internalTicketSz;
word32 ticketSz;
byte* mac;
#if defined(OPENSSL_ALL) && defined(KEEP_PEER_CERT) && \
!defined(NO_CERT_IN_TICKET)
const byte* peerCertDer = NULL;
word16 peerCertSz = 0;
#endif

WOLFSSL_ASSERT_GE(sizeof(ssl->session->staticTicket), WOLFSSL_TICKET_ENC_SZ);
WOLFSSL_ASSERT_SIZEOF_GE(ssl->session->staticTicket, *et);

if (ssl->session->ticket != ssl->session->staticTicket) {
/* Always use the static ticket buffer */
XFREE(ssl->session->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK);
ssl->session->ticket = ssl->session->staticTicket;
ssl->session->ticketLenAlloc = 0;
#if defined(OPENSSL_ALL) && defined(KEEP_PEER_CERT) && \
!defined(NO_CERT_IN_TICKET)
/* Store peer certificate in ticket for session resumption.
* Try ssl->peerCert first, then ssl->session->chain as fallback.
* Skip for DTLS to keep ticket size small for MTU constraints. */
if (!ssl->options.dtls) {
const byte* certDer = NULL;
word32 certDerSz = 0;

if (ssl->peerCert.derCert != NULL &&
ssl->peerCert.derCert->length > 0) {
/* Use current peer certificate */
certDer = ssl->peerCert.derCert->buffer;
certDerSz = ssl->peerCert.derCert->length;
}
#ifdef SESSION_CERTS
else if (ssl->session->chain.count > 0) {
/* Use peer certificate from session chain */
certDer = ssl->session->chain.certs[0].buffer;
certDerSz = ssl->session->chain.certs[0].length;
}
#endif

if (certDer != NULL && certDerSz > 0 &&
certDerSz <= MAX_TICKET_PEER_CERT_SZ
#ifdef HAVE_MAX_FRAGMENT
/* We don't support fragmentation in
* SendTls13NewSessionTicket yet. */
&& (!IsAtLeastTLSv1_3(ssl->version) ||
ssl->max_fragment == MAX_RECORD_SIZE)
#endif
) {
peerCertDer = certDer;
peerCertSz = (word16)certDerSz;
}
else if (certDerSz > MAX_TICKET_PEER_CERT_SZ) {
WOLFSSL_MSG("Peer cert too large for ticket, skipping");
}
}
#endif

et = (ExternalTicket*)ssl->session->ticket;
it = (InternalTicket*)et->enc_ticket;
internalTicketSz = (int)WOLFSSL_INTERNAL_TICKET_BASE_SZ;
/* Space for the encrypt callback: WOLFSSL_TICKET_ENC_SZ less the
* certificate space this ticket does not use. */
encMax = (int)WOLFSSL_TICKET_ENC_BASE_SZ;
#if defined(OPENSSL_ALL) && defined(KEEP_PEER_CERT) && \
!defined(NO_CERT_IN_TICKET)
internalTicketSz += peerCertSz;
encMax += peerCertSz;
#endif
#ifdef WOLFSSL_TICKET_ENC_CBC_HMAC
internalTicketSz = (internalTicketSz + 15) & (~0xf);
#endif
ticketSz = WOLFSSL_TICKET_FIXED_SZ + (word32)encMax;

/* The static buffer holds a ticket without a peer certificate. On an
* async re-entry the size is the same and the buffer is kept. */
if (ticketSz <= sizeof(ssl->session->staticTicket)) {
if (ssl->session->ticket != ssl->session->staticTicket) {
XFREE(ssl->session->ticket, ssl->session->heap,
DYNAMIC_TYPE_SESSION_TICK);
ssl->session->ticket = ssl->session->staticTicket;
ssl->session->ticketLenAlloc = 0;
}
}
else if (ssl->session->ticketLenAlloc < ticketSz) {
byte* ticket = (byte*)XMALLOC(ticketSz, ssl->session->heap,
DYNAMIC_TYPE_SESSION_TICK);
if (ticket == NULL) {
WOLFSSL_ERROR_VERBOSE(MEMORY_E);
return MEMORY_E;
}
if (ssl->session->ticketLenAlloc > 0) {
XFREE(ssl->session->ticket, ssl->session->heap,
DYNAMIC_TYPE_SESSION_TICK);
}
ssl->session->ticket = ticket;
ssl->session->ticketLenAlloc = (word16)ticketSz;
}
/* Set once the new ticket is made */
ssl->session->ticketLen = 0;

#ifdef WOLFSSL_ASYNC_CRYPT
if (ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E))
#endif
{
XMEMSET(ssl->session->ticket, 0, SESSION_TICKET_LEN);
XMEMSET(ssl->session->ticket, 0, ticketSz);
}

et = (ExternalTicket*)ssl->session->ticket;
it = (InternalTicket*)et->enc_ticket;

/* build internal */
it->pv.major = ssl->version.major;
it->pv.minor = ssl->version.minor;
Expand Down Expand Up @@ -45313,51 +45394,9 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)

#if defined(OPENSSL_ALL) && defined(KEEP_PEER_CERT) && \
!defined(NO_CERT_IN_TICKET)
/* Store peer certificate in ticket for session resumption.
* Try ssl->peerCert first, then ssl->session->chain as fallback.
* Skip for DTLS to keep ticket size small for MTU constraints. */
if (ssl->options.dtls) {
c16toa(0, it->peerCertLen);
peerCertSz = 0;
}
else {
const byte* certDer = NULL;
word32 certDerSz = 0;

if (ssl->peerCert.derCert != NULL &&
ssl->peerCert.derCert->length > 0) {
/* Use current peer certificate */
certDer = ssl->peerCert.derCert->buffer;
certDerSz = ssl->peerCert.derCert->length;
}
#ifdef SESSION_CERTS
else if (ssl->session->chain.count > 0) {
/* Use peer certificate from session chain */
certDer = ssl->session->chain.certs[0].buffer;
certDerSz = ssl->session->chain.certs[0].length;
}
#endif

if (certDer != NULL && certDerSz > 0 &&
certDerSz <= MAX_TICKET_PEER_CERT_SZ
#ifdef HAVE_MAX_FRAGMENT
/* We don't support fragmentation in
* SendTls13NewSessionTicket yet. */
&& (!IsAtLeastTLSv1_3(ssl->version) ||
ssl->max_fragment == MAX_RECORD_SIZE)
#endif
) {
c16toa((word16)certDerSz, it->peerCertLen);
XMEMCPY(it->peerCert, certDer, certDerSz);
peerCertSz = (word16)certDerSz;
}
else {
if (certDerSz > MAX_TICKET_PEER_CERT_SZ)
WOLFSSL_MSG("Peer cert too large for ticket, skipping");
c16toa(0, it->peerCertLen);
peerCertSz = 0;
}
}
c16toa(peerCertSz, it->peerCertLen);
if (peerCertSz > 0)
XMEMCPY(it->peerCert, peerCertDer, peerCertSz);
#endif

#ifdef WOLFSSL_TICKET_HAVE_ID
Expand All @@ -45372,19 +45411,11 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
}
#endif

internalTicketSz = (int)WOLFSSL_INTERNAL_TICKET_BASE_SZ;
#if defined(OPENSSL_ALL) && defined(KEEP_PEER_CERT) && \
!defined(NO_CERT_IN_TICKET)
internalTicketSz += peerCertSz;
#endif
#ifdef WOLFSSL_TICKET_ENC_CBC_HMAC
internalTicketSz = (internalTicketSz + 15) & (~0xf);
#endif
/* MAC is placed after the encrypted data */
mac = et->enc_ticket + WOLFSSL_TICKET_ENC_SZ;
mac = et->enc_ticket + encMax;

/* encrypt */
encLen = WOLFSSL_TICKET_ENC_SZ; /* max size user can use */
encLen = encMax; /* max size user can use */
if (ssl->ctx->ticketEncCb == NULL
#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL)
||
Expand Down Expand Up @@ -45417,10 +45448,10 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
#endif
goto error;
}
if (encLen < internalTicketSz ||
encLen > (int)WOLFSSL_TICKET_ENC_SZ) {
if (encLen < internalTicketSz || encLen > encMax) {
WOLFSSL_MSG("Bad user ticket encrypt size");
ret = BAD_TICKET_KEY_CB_SZ;
goto error;
}

/* sanity checks on encrypt callback */
Expand Down Expand Up @@ -45459,7 +45490,7 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)

/* set size */
c16toa((word16)encLen, et->enc_len);
if (encLen < (int)WOLFSSL_TICKET_ENC_SZ) {
if (encLen < encMax) {
/* move mac up since whole enc buffer not used */
XMEMMOVE(et->enc_ticket + encLen, mac,
WOLFSSL_TICKET_MAC_SZ);
Expand All @@ -45471,12 +45502,11 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl)
error:
#ifdef WOLFSSL_CHECK_MEM_ZERO
/* Ticket has sensitive data in it now. */
wc_MemZero_Add("Create Ticket internal", it,
WOLFSSL_INTERNAL_TICKET_MAX_SZ);
wc_MemZero_Add("Create Ticket internal", it, (word32)encMax);
#endif
ForceZero(it, WOLFSSL_INTERNAL_TICKET_MAX_SZ);
ForceZero(it, (word32)encMax);
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Check(it, WOLFSSL_INTERNAL_TICKET_MAX_SZ);
wc_MemZero_Check(it, (word32)encMax);
#endif
WOLFSSL_ERROR_VERBOSE(ret);
return ret;
Expand Down
5 changes: 3 additions & 2 deletions src/ssl_api_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -1625,7 +1625,7 @@ int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf,

if ((ret == WOLFSSL_SUCCESS) && (bufSz > 0)) {
/* Ticket will fit into static ticket */
if (bufSz <= SESSION_TICKET_LEN) {
if (bufSz <= sizeof(ssl->session->staticTicket)) {
if (ssl->session->ticketLenAlloc > 0) {
XFREE(ssl->session->ticket, ssl->session->heap,
DYNAMIC_TYPE_SESSION_TICK);
Expand All @@ -1635,7 +1635,7 @@ int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf,
}
else { /* Ticket requires dynamic ticket storage */
/* is dyn buffer big enough */
if (ssl->session->ticketLen < bufSz) {
if (ssl->session->ticketLenAlloc < bufSz) {
if (ssl->session->ticketLenAlloc > 0) {
XFREE(ssl->session->ticket, ssl->session->heap,
DYNAMIC_TYPE_SESSION_TICK);
Expand All @@ -1645,6 +1645,7 @@ int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf,
if (ssl->session->ticket == NULL) {
ssl->session->ticket = ssl->session->staticTicket;
ssl->session->ticketLenAlloc = 0;
ssl->session->ticketLen = 0;
ret = MEMORY_ERROR;
}
else {
Expand Down
18 changes: 11 additions & 7 deletions src/ssl_sess.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,12 +413,13 @@ static int SessionSanityPointerSet(int row)
s->type = WOLFSSL_SESSION_TYPE_CACHE;
s->cacheRow = row;

/* clamp ticketLen */
/* drop a ticket that was not in the static buffer: the row copy
* only has the static buffer's (stale) bytes for it */
#ifdef HAVE_SESSION_TICKET
s->ticket = s->staticTicket;
s->ticketLenAlloc = 0;
if (s->ticketLen > SESSION_TICKET_LEN) {
s->ticketLen = SESSION_TICKET_LEN;
if (s->ticketLen > sizeof(s->staticTicket)) {
s->ticketLen = 0;
}
#endif /* HAVE_SESSION_TICKET */
#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || \
Expand Down Expand Up @@ -1495,7 +1496,7 @@ static int GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output,
#ifdef HAVE_SESSION_TICKET
if (tmpBufSet) {
if (error == WOLFSSL_SUCCESS) {
if (output->ticketLen > SESSION_TICKET_LEN) {
if (output->ticketLen > sizeof(output->staticTicket)) {
output->ticket = (byte*)XMALLOC(output->ticketLen, output->heap,
DYNAMIC_TYPE_SESSION_TICK);
if (output->ticket == NULL) {
Expand All @@ -1504,6 +1505,9 @@ static int GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output,
output->ticketLenAlloc = 0;
output->ticketLen = 0;
}
else {
output->ticketLenAlloc = output->ticketLen;
}
}
else {
output->ticket = output->staticTicket;
Expand Down Expand Up @@ -2012,7 +2016,7 @@ int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession,
#ifdef HAVE_SESSION_TICKET
ticLen = addSession->ticketLen;
/* Alloc Memory here to avoid syscalls during lock */
if (ticLen > SESSION_TICKET_LEN) {
if (ticLen > (int)sizeof(addSession->staticTicket)) {
ticBuff = (byte*)XMALLOC((size_t)ticLen, NULL,
DYNAMIC_TYPE_SESSION_TICK);
if (ticBuff == NULL) {
Expand Down Expand Up @@ -3363,7 +3367,7 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess,
if (s->ticketLenAlloc > 0) {
XFREE(s->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK);
}
if (s->ticketLen <= SESSION_TICKET_LEN)
if (s->ticketLen <= sizeof(s->staticTicket))
s->ticket = s->staticTicket;
else {
s->ticket = (byte*)XMALLOC(s->ticketLen, NULL,
Expand Down Expand Up @@ -4300,7 +4304,7 @@ static int wolfSSL_DupSessionEx(const WOLFSSL_SESSION* input,
output->cacheRow = INVALID_SESSION_ROW;
#endif
#ifdef HAVE_SESSION_TICKET
if (input->ticketLen > SESSION_TICKET_LEN) {
if (input->ticketLen > sizeof(output->staticTicket)) {
/* Need dynamic buffer */
if (ticBuff == NULL || ticLenAlloc < input->ticketLen) {
/* allocate new one */
Expand Down
2 changes: 1 addition & 1 deletion src/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -12850,7 +12850,7 @@ int TLSX_PreSharedKey_Parse_ClientHello(TLSX** extensions, const byte* input,
ato16(input + idx, &identityLen);
idx += OPAQUE16_LEN;
if (len < OPAQUE16_LEN + identityLen + OPAQUE32_LEN ||
identityLen > MAX_PSK_ID_LEN)
identityLen > MAX_PSK_ID_WIRE_LEN)
return BUFFER_E;
/* Cache identity pointer. */
identity = input + idx;
Expand Down
21 changes: 15 additions & 6 deletions src/tls13.c
Original file line number Diff line number Diff line change
Expand Up @@ -6848,6 +6848,13 @@ int FindPskSuite(const WOLFSSL* ssl, PreSharedKey* psk, byte* psk_key,
*found = 0;
(void)suite;

/* A longer identity can only be a session ticket */
if (psk->identityLen > MAX_PSK_ID_LEN) {
WOLFSSL_MSG("PSK identity longer than MAX_PSK_ID_LEN, not offered to "
"the PSK callback");
return 0;
}

if (ssl->options.server_psk_tls13_cb != NULL) {
*psk_keySz = ssl->options.server_psk_tls13_cb((WOLFSSL*)ssl,
(char*)psk->identity, psk_key, MAX_PSK_KEY_LEN, &cipherName);
Expand Down Expand Up @@ -7021,13 +7028,15 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz,
for (current = (PreSharedKey*)ext->data; current != NULL;
current = current->next) {
#ifndef NO_PSK
if (current->identityLen > MAX_PSK_ID_LEN) {
ret = BUFFER_ERROR;
goto cleanup;
/* A session ticket can be longer than an external PSK identity. */
if (current->identityLen <= MAX_PSK_ID_LEN) {
XMEMCPY(ssl->arrays->client_identity, current->identity,
current->identityLen);
ssl->arrays->client_identity[current->identityLen] = '\0';
}
else {
ssl->arrays->client_identity[0] = '\0';
}
XMEMCPY(ssl->arrays->client_identity, current->identity,
current->identityLen);
ssl->arrays->client_identity[current->identityLen] = '\0';
#endif

#ifdef HAVE_SESSION_TICKET
Expand Down
Loading
Loading