mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-30 02:37:28 +02:00
TLS 1.3: hold decrypted ticket to check which ciphersuite matches
DTLS 1.3: Move stateless ticket decoding to FindPskSuiteFromExt
This commit is contained in:
225
src/dtls.c
225
src/dtls.c
@ -291,24 +291,17 @@ static int TlsxFindByType(WolfSSL_ConstVector* ret, word16 extType,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_DTLS13) || defined(WOLFSSL_DTLS_NO_HVR_ON_RESUME)
|
||||
#if defined(WOLFSSL_DTLS_NO_HVR_ON_RESUME)
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
static int TlsTicketIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector exts,
|
||||
PskInfo* pskInfo, byte isTls13)
|
||||
int* resume)
|
||||
{
|
||||
WolfSSL_ConstVector tlsxSessionTicket;
|
||||
byte tempTicket[SESSION_TICKET_LEN];
|
||||
InternalTicket* it;
|
||||
int ret;
|
||||
InternalTicket* it = NULL;
|
||||
int ret = 0;
|
||||
|
||||
(void)isTls13;
|
||||
|
||||
#if defined(WOLFSSL_TLS13) && !defined(NO_PSK)
|
||||
if (isTls13)
|
||||
ret = TlsxFindByType(&tlsxSessionTicket, TLSX_PRE_SHARED_KEY, exts);
|
||||
else
|
||||
#endif
|
||||
ret = TlsxFindByType(&tlsxSessionTicket, TLSX_SESSION_TICKET, exts);
|
||||
ret = TlsxFindByType(&tlsxSessionTicket, TLSX_SESSION_TICKET, exts);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
if (tlsxSessionTicket.size == 0)
|
||||
@ -316,26 +309,20 @@ static int TlsTicketIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector exts,
|
||||
if (tlsxSessionTicket.size > SESSION_TICKET_LEN)
|
||||
return 0;
|
||||
XMEMCPY(tempTicket, tlsxSessionTicket.elements, tlsxSessionTicket.size);
|
||||
ret = DoDecryptTicket((WOLFSSL*)ssl, tempTicket,
|
||||
(word32)tlsxSessionTicket.size, &it);
|
||||
if (ret != WOLFSSL_TICKET_RET_OK && ret != WOLFSSL_TICKET_RET_CREATE)
|
||||
return 0;
|
||||
/* Store info for later */
|
||||
#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
|
||||
pskInfo->pv = it->pv;
|
||||
#endif
|
||||
pskInfo->cipherSuite0 = it->suite[0];
|
||||
pskInfo->cipherSuite = it->suite[1];
|
||||
ato16(it->namedGroup, &pskInfo->namedGroup);
|
||||
|
||||
ForceZero(it, sizeof(InternalTicket));
|
||||
pskInfo->isValid = 1;
|
||||
ret = DoDecryptTicket(ssl, tempTicket, (word32)tlsxSessionTicket.size, &it);
|
||||
if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) {
|
||||
/* This logic is only for TLS <= 1.2 tickets. Don't accept TLS 1.3. */
|
||||
if (!IsAtLeastTLSv1_3(it->pv))
|
||||
*resume = TRUE;
|
||||
}
|
||||
if (it != NULL)
|
||||
ForceZero(it, sizeof(InternalTicket));
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_SESSION_TICKET */
|
||||
|
||||
static int TlsSessionIdIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector sessionID,
|
||||
PskInfo* pskInfo)
|
||||
int* resume)
|
||||
{
|
||||
WOLFSSL_SESSION* sess;
|
||||
word32 sessRow;
|
||||
@ -353,17 +340,19 @@ static int TlsSessionIdIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector sessionID
|
||||
ssl->ctx->get_sess_cb((WOLFSSL*)ssl, sessionID.elements, ID_LEN,
|
||||
&unused);
|
||||
if (sess != NULL) {
|
||||
/* Store info for later */
|
||||
#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
|
||||
pskInfo->pv = sess->version;
|
||||
#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
|
||||
defined(HAVE_SESSION_TICKET))
|
||||
/* This logic is only for TLS <= 1.2 tickets. Don't accept
|
||||
* TLS 1.3. */
|
||||
if (IsAtLeastTLSv1_3(sess->version))
|
||||
wolfSSL_FreeSession(ssl->ctx, sess);
|
||||
else
|
||||
#endif
|
||||
pskInfo->cipherSuite0 = sess->cipherSuite0;
|
||||
pskInfo->cipherSuite = sess->cipherSuite;
|
||||
pskInfo->namedGroup = sess->namedGroup;
|
||||
|
||||
pskInfo->isValid = 1;
|
||||
wolfSSL_FreeSession(ssl->ctx, sess);
|
||||
return 0;
|
||||
{
|
||||
*resume = 1;
|
||||
wolfSSL_FreeSession(ssl->ctx, sess);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ssl->ctx->internalCacheLookupOff)
|
||||
@ -372,15 +361,15 @@ static int TlsSessionIdIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector sessionID
|
||||
#endif
|
||||
ret = TlsSessionCacheGetAndLock(sessionID.elements, &sess, &sessRow, 1);
|
||||
if (ret == 0 && sess != NULL) {
|
||||
/* Store info for later */
|
||||
#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
|
||||
pskInfo->pv = sess->version;
|
||||
#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \
|
||||
defined(HAVE_SESSION_TICKET))
|
||||
/* This logic is only for TLS <= 1.2 tickets. Don't accept
|
||||
* TLS 1.3. */
|
||||
if (!IsAtLeastTLSv1_3(sess->version))
|
||||
#endif
|
||||
pskInfo->cipherSuite0 = sess->cipherSuite0;
|
||||
pskInfo->cipherSuite = sess->cipherSuite;
|
||||
pskInfo->namedGroup = sess->namedGroup;
|
||||
|
||||
pskInfo->isValid = 1;
|
||||
{
|
||||
*resume = 1;
|
||||
}
|
||||
TlsSessionCacheUnlockRow(sessRow);
|
||||
}
|
||||
|
||||
@ -388,19 +377,18 @@ static int TlsSessionIdIsValid(const WOLFSSL* ssl, WolfSSL_ConstVector sessionID
|
||||
}
|
||||
|
||||
static int TlsResumptionIsValid(const WOLFSSL* ssl, WolfSSL_CH* ch,
|
||||
PskInfo* pskInfo, byte isTls13)
|
||||
int* resume)
|
||||
{
|
||||
int ret;
|
||||
|
||||
(void)isTls13;
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
ret = TlsTicketIsValid(ssl, ch->extension, pskInfo, isTls13);
|
||||
ret = TlsTicketIsValid(ssl, ch->extension, resume);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
if (pskInfo->isValid)
|
||||
if (*resume)
|
||||
return 0;
|
||||
#endif /* HAVE_SESSION_TICKET */
|
||||
ret = TlsSessionIdIsValid(ssl, ch->sessionId, pskInfo);
|
||||
ret = TlsSessionIdIsValid(ssl, ch->sessionId, resume);
|
||||
return ret;
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS13 || WOLFSSL_DTLS_NO_HVR_ON_RESUME */
|
||||
@ -454,18 +442,16 @@ static int CopySupportedGroup(TLSX* src, TLSX** dst, void* heap)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_DTLS13) && !defined(NO_PSK)
|
||||
#if defined(WOLFSSL_DTLS13) && \
|
||||
(!defined(NO_PSK) || defined(HAVE_SESSION_TICKET))
|
||||
/* Very simplified version of CheckPreSharedKeys to find the current suite */
|
||||
static void FindPskSuiteFromExt(const WOLFSSL* ssl, TLSX* extensions,
|
||||
PskInfo* pskInfo, Suites* suites)
|
||||
{
|
||||
TLSX* pskExt = TLSX_Find(extensions, TLSX_PRE_SHARED_KEY);
|
||||
int found = 0;
|
||||
PreSharedKey* current;
|
||||
byte psk_key[MAX_PSK_KEY_LEN];
|
||||
word32 psk_keySz;
|
||||
int i;
|
||||
byte foundSuite[SUITE_LEN];
|
||||
int ret;
|
||||
|
||||
if (pskExt == NULL)
|
||||
return;
|
||||
@ -473,17 +459,61 @@ static void FindPskSuiteFromExt(const WOLFSSL* ssl, TLSX* extensions,
|
||||
for (i = 0; i < suites->suiteSz; i += 2) {
|
||||
for (current = (PreSharedKey*)pskExt->data; current != NULL;
|
||||
current = current->next) {
|
||||
if (FindPskSuite(ssl, current, psk_key, &psk_keySz,
|
||||
suites->suites + i, &found, foundSuite) == 0) {
|
||||
if (found) {
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
{
|
||||
/* Decode the identity. */
|
||||
switch (current->decryptRet) {
|
||||
case PSK_DECRYPT_NONE:
|
||||
ret = DoClientTicket_ex(ssl, current);
|
||||
break;
|
||||
case PSK_DECRYPT_OK:
|
||||
ret = WOLFSSL_TICKET_RET_OK;
|
||||
break;
|
||||
case PSK_DECRYPT_CREATE:
|
||||
ret = WOLFSSL_TICKET_RET_CREATE;
|
||||
break;
|
||||
case PSK_DECRYPT_FAIL:
|
||||
ret = WOLFSSL_TICKET_RET_REJECT;
|
||||
break;
|
||||
}
|
||||
if (ret == WOLFSSL_TICKET_RET_OK) {
|
||||
if (DoClientTicketCheck(current, ssl->timeout,
|
||||
suites->suites + i) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pskInfo->cipherSuite0 = current->it->suite[0];
|
||||
pskInfo->cipherSuite = current->it->suite[1];
|
||||
pskInfo->isValid = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifndef NO_PSK
|
||||
{
|
||||
int found = 0;
|
||||
byte psk_key[MAX_PSK_KEY_LEN];
|
||||
word32 psk_keySz;
|
||||
byte foundSuite[SUITE_LEN];
|
||||
ret = FindPskSuite(ssl, current, psk_key, &psk_keySz,
|
||||
suites->suites + i, &found, foundSuite);
|
||||
/* Clear the key just in case */
|
||||
ForceZero(psk_key, sizeof(psk_key));
|
||||
if (ret == 0 && found) {
|
||||
pskInfo->cipherSuite0 = foundSuite[0];
|
||||
pskInfo->cipherSuite = foundSuite[1];
|
||||
pskInfo->isValid = 1;
|
||||
return;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
CleanupClientTickets((PreSharedKey*)pskExt->data);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -493,8 +523,12 @@ static void FindPskSuiteFromExt(const WOLFSSL* ssl, TLSX* extensions,
|
||||
#error "WOLFSSL_SEND_HRR_COOKIE has to be defined to use DTLS 1.3 server"
|
||||
#endif
|
||||
|
||||
static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch,
|
||||
PskInfo* pskInfo)
|
||||
#ifdef WOLFSSL_PSK_ONE_ID
|
||||
#error WOLFSSL_PSK_ONE_ID is not compatible with stateless DTLS 1.3 server. \
|
||||
wolfSSL needs to be able to make multiple calls for the same PSK.
|
||||
#endif
|
||||
|
||||
static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch)
|
||||
{
|
||||
int ret = -1;
|
||||
TLSX* parsedExts = NULL;
|
||||
@ -511,8 +545,10 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch,
|
||||
CipherSpecs specs;
|
||||
byte cookieHash[WC_MAX_DIGEST_SIZE];
|
||||
int cookieHashSz;
|
||||
|
||||
(void)pskInfo;
|
||||
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
|
||||
PskInfo pskInfo;
|
||||
XMEMSET(&pskInfo, 0, sizeof(pskInfo));
|
||||
#endif
|
||||
|
||||
XMEMSET(&cs, 0, sizeof(cs));
|
||||
|
||||
@ -601,18 +637,13 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch,
|
||||
* and if they don't match we will error out there anyway. */
|
||||
byte modes;
|
||||
|
||||
#ifndef NO_PSK
|
||||
/* When we didn't find a valid ticket ask the user for the
|
||||
* ciphersuite matching this identity */
|
||||
if (!pskInfo->isValid) {
|
||||
if (TLSX_PreSharedKey_Parse_ClientHello(&parsedExts,
|
||||
tlsx.elements, tlsx.size, ssl->heap) == 0)
|
||||
FindPskSuiteFromExt(ssl, parsedExts, pskInfo, &suites);
|
||||
/* Revert to full handshake if PSK parsing failed */
|
||||
}
|
||||
#endif
|
||||
/* Ask the user for the ciphersuite matching this identity */
|
||||
if (TLSX_PreSharedKey_Parse_ClientHello(&parsedExts,
|
||||
tlsx.elements, tlsx.size, ssl->heap) == 0)
|
||||
FindPskSuiteFromExt(ssl, parsedExts, &pskInfo, &suites);
|
||||
/* Revert to full handshake if PSK parsing failed */
|
||||
|
||||
if (pskInfo->isValid) {
|
||||
if (pskInfo.isValid) {
|
||||
ret = TlsxFindByType(&tlsx, TLSX_PSK_KEY_EXCHANGE_MODES,
|
||||
ch->extension);
|
||||
if (ret != 0)
|
||||
@ -638,9 +669,9 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch,
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
|
||||
if (usePSK && pskInfo->isValid) {
|
||||
cs.cipherSuite0 = pskInfo->cipherSuite0;
|
||||
cs.cipherSuite = pskInfo->cipherSuite;
|
||||
if (usePSK && pskInfo.isValid) {
|
||||
cs.cipherSuite0 = pskInfo.cipherSuite0;
|
||||
cs.cipherSuite = pskInfo.cipherSuite;
|
||||
|
||||
if (haveSG && !haveKS) {
|
||||
WOLFSSL_MSG("Client didn't send KeyShare or Supported Groups.");
|
||||
@ -737,15 +768,13 @@ dtls13_cleanup:
|
||||
}
|
||||
#endif
|
||||
|
||||
static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13,
|
||||
PskInfo* pskInfo)
|
||||
static int SendStatelessReply(const WOLFSSL* ssl, WolfSSL_CH* ch, byte isTls13)
|
||||
{
|
||||
int ret;
|
||||
(void)isTls13;
|
||||
(void)pskInfo;
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
if (isTls13) {
|
||||
ret = SendStatelessReplyDtls13(ssl, ch, pskInfo);
|
||||
ret = SendStatelessReplyDtls13(ssl, ch);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -789,9 +818,7 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input,
|
||||
int ret;
|
||||
WolfSSL_CH ch;
|
||||
byte isTls13 = 0;
|
||||
PskInfo pskInfo;
|
||||
|
||||
XMEMSET(&pskInfo, 0, sizeof(pskInfo));
|
||||
XMEMSET(&ch, 0, sizeof(ch));
|
||||
|
||||
ssl->options.dtlsStateful = 0;
|
||||
@ -816,33 +843,21 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input,
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
#if defined(WOLFSSL_DTLS13) || defined(WOLFSSL_DTLS_NO_HVR_ON_RESUME)
|
||||
ret = TlsResumptionIsValid(ssl, &ch, &pskInfo, isTls13);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
#endif
|
||||
#ifdef WOLFSSL_DTLS_NO_HVR_ON_RESUME
|
||||
if (pskInfo.isValid) {
|
||||
ssl->options.dtlsStateful = 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_DTLS13) && defined(HAVE_SESSION_TICKET)
|
||||
if (pskInfo.isValid) {
|
||||
if (IsAtLeastTLSv1_3(pskInfo.pv)) {
|
||||
if (!isTls13)
|
||||
return VERSION_ERROR;
|
||||
}
|
||||
else {
|
||||
if (isTls13)
|
||||
return VERSION_ERROR;
|
||||
if (!isTls13) {
|
||||
int resume = FALSE;
|
||||
ret = TlsResumptionIsValid(ssl, &ch, &resume);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
if (resume) {
|
||||
ssl->options.dtlsStateful = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ch.cookie.size == 0 && ch.cookieExt.size == 0) {
|
||||
ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13, &pskInfo);
|
||||
ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13);
|
||||
}
|
||||
else {
|
||||
byte cookieGood;
|
||||
@ -857,7 +872,7 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input,
|
||||
ret = INVALID_PARAMETER;
|
||||
else
|
||||
#endif
|
||||
ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13, &pskInfo);
|
||||
ret = SendStatelessReply((WOLFSSL*)ssl, &ch, isTls13);
|
||||
}
|
||||
else
|
||||
ssl->options.dtlsStateful = 1;
|
||||
|
361
src/internal.c
361
src/internal.c
@ -34547,7 +34547,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
|
||||
}
|
||||
|
||||
int DoDecryptTicket(WOLFSSL* ssl, const byte* input, word32 len,
|
||||
int DoDecryptTicket(const WOLFSSL* ssl, const byte* input, word32 len,
|
||||
InternalTicket **it)
|
||||
{
|
||||
ExternalTicket* et;
|
||||
@ -34589,7 +34589,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
ret = WOLFSSL_TICKET_RET_REJECT;
|
||||
}
|
||||
else {
|
||||
ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv,
|
||||
/* Callback uses ssl without const but for DTLS, it really shouldn't
|
||||
* modify its state. */
|
||||
ret = ssl->ctx->ticketEncCb((WOLFSSL*)ssl, et->key_name, et->iv,
|
||||
et->enc_ticket + inLen, 0,
|
||||
et->enc_ticket, inLen, &outLen,
|
||||
ssl->ctx->ticketEncCtx);
|
||||
@ -34614,142 +34616,265 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Parse ticket sent by client, returns callback return value */
|
||||
int DoClientTicket(WOLFSSL* ssl, const byte* input, word32 len)
|
||||
static int DoClientTicketCheckVersion(const WOLFSSL* ssl,
|
||||
InternalTicket* it)
|
||||
{
|
||||
InternalTicket* it;
|
||||
int ret;
|
||||
if (ssl->version.minor < it->pv.minor) {
|
||||
WOLFSSL_MSG("Ticket has greater version");
|
||||
return VERSION_ERROR;
|
||||
}
|
||||
else if (ssl->version.minor > it->pv.minor) {
|
||||
if (IsAtLeastTLSv1_3(it->pv) != IsAtLeastTLSv1_3(ssl->version)) {
|
||||
WOLFSSL_MSG("Tickets cannot be shared between "
|
||||
"TLS 1.3 and TLS 1.2 and lower");
|
||||
return VERSION_ERROR;
|
||||
}
|
||||
|
||||
if (!ssl->options.downgrade) {
|
||||
WOLFSSL_MSG("Ticket has lesser version");
|
||||
return VERSION_ERROR;
|
||||
}
|
||||
|
||||
WOLFSSL_MSG("Downgrading protocol due to ticket");
|
||||
|
||||
if (it->pv.minor < ssl->options.minDowngrade) {
|
||||
WOLFSSL_MSG("Ticket has lesser version than allowed");
|
||||
return VERSION_ERROR;
|
||||
}
|
||||
}
|
||||
/* Check resumption master secret. */
|
||||
if (IsAtLeastTLSv1_3(it->pv) &&
|
||||
it->ticketNonceLen > MAX_TICKET_NONCE_STATIC_SZ) {
|
||||
WOLFSSL_MSG("Unsupported ticketNonce len in ticket");
|
||||
return BAD_TICKET_ENCRYPT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return 0 when check successful. <0 on failure. */
|
||||
int DoClientTicketCheck(const PreSharedKey* psk, sword64 timeout,
|
||||
const byte* suite)
|
||||
{
|
||||
word32 ticketAdd;
|
||||
#ifdef WOLFSSL_32BIT_MILLI_TIME
|
||||
word32 now;
|
||||
sword64 diff;
|
||||
word32 ticketSeen; /* Time ticket seen (ms) */
|
||||
|
||||
ato32(psk->it->timestamp, &ticketSeen);
|
||||
|
||||
now = TimeNowInMilliseconds();
|
||||
if (now == 0)
|
||||
return GETTIME_ERROR;
|
||||
/* Difference between now and time ticket constructed
|
||||
* (from decrypted ticket). */
|
||||
diff = now;
|
||||
diff -= ticketSeen;
|
||||
if (diff > timeout * 1000 ||
|
||||
diff > (sword64)TLS13_MAX_TICKET_AGE * 1000)
|
||||
return -1;
|
||||
#else
|
||||
sword64 diff;
|
||||
sword64 ticketSeen; /* Time ticket seen (ms) */
|
||||
word32 seenHi, seenLo;
|
||||
|
||||
ato32(psk->it->timestamp , &seenHi);
|
||||
ato32(psk->it->timestamp + OPAQUE32_LEN, &seenLo);
|
||||
ticketSeen = ((sword64)seenHi << 32) + seenLo;
|
||||
|
||||
diff = TimeNowInMilliseconds();
|
||||
if (diff == 0)
|
||||
return GETTIME_ERROR;
|
||||
/* Difference between now and time ticket constructed
|
||||
* (from decrypted ticket). */
|
||||
diff -= ticketSeen;
|
||||
if (diff > timeout * 1000 ||
|
||||
diff > (sword64)TLS13_MAX_TICKET_AGE * 1000)
|
||||
return -1;
|
||||
#endif
|
||||
ato32(psk->it->ageAdd, &ticketAdd);
|
||||
/* Subtract client's ticket age and unobfuscate. */
|
||||
diff -= psk->ticketAge;
|
||||
diff += ticketAdd;
|
||||
/* Check session and ticket age timeout.
|
||||
* Allow +/- 1000 milliseconds on ticket age.
|
||||
*/
|
||||
if (diff < -1000 || diff - MAX_TICKET_AGE_DIFF * 1000 > 1000)
|
||||
return -1;
|
||||
|
||||
#ifndef WOLFSSL_PSK_ONE_ID
|
||||
/* Check whether resumption is possible based on suites in SSL and
|
||||
* ciphersuite in ticket.
|
||||
*/
|
||||
if (XMEMCMP(suite, psk->it->suite, SUITE_LEN) != 0)
|
||||
return -1;
|
||||
#else
|
||||
if (!FindSuiteSSL(ssl, psk->it->suite))
|
||||
return -1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DoClientTicketFinalize(WOLFSSL* ssl, InternalTicket* it)
|
||||
{
|
||||
#ifdef WOLFSSL_TICKET_HAVE_ID
|
||||
ssl->session->haveAltSessionID = 1;
|
||||
XMEMCPY(ssl->session->altSessionID, it->id, ID_LEN);
|
||||
if (wolfSSL_GetSession(ssl, NULL, 1) != NULL) {
|
||||
WOLFSSL_MSG("Found session matching the session id"
|
||||
" found in the ticket");
|
||||
}
|
||||
else {
|
||||
WOLFSSL_MSG("Can't find session matching the session id"
|
||||
" found in the ticket");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!IsAtLeastTLSv1_3(ssl->version)) {
|
||||
XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN);
|
||||
/* Copy the haveExtendedMasterSecret property from the ticket to
|
||||
* the saved session, so the property may be checked later. */
|
||||
ssl->session->haveEMS = it->haveEMS;
|
||||
ato32((const byte*)&it->timestamp, &ssl->session->bornOn);
|
||||
#ifndef NO_RESUME_SUITE_CHECK
|
||||
ssl->session->cipherSuite0 = it->suite[0];
|
||||
ssl->session->cipherSuite = it->suite[1];
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#ifdef WOLFSSL_TLS13
|
||||
/* This should have been already checked in
|
||||
* DoClientTicketCheckVersion */
|
||||
if (it->ticketNonceLen > MAX_TICKET_NONCE_STATIC_SZ) {
|
||||
WOLFSSL_MSG("Unsupported ticketNonce len in ticket");
|
||||
return;
|
||||
}
|
||||
/* Restore information to renegotiate. */
|
||||
#ifdef WOLFSSL_32BIT_MILLI_TIME
|
||||
ato32(it->timestamp, &ssl->session->ticketSeen);
|
||||
#else
|
||||
word32 seenHi, seenLo;
|
||||
|
||||
ato32(it->timestamp , &seenHi);
|
||||
ato32(it->timestamp + OPAQUE32_LEN, &seenLo);
|
||||
ssl->session->ticketSeen = ((sword64)seenHi << 32) + seenLo;
|
||||
#endif
|
||||
ato32(it->ageAdd, &ssl->session->ticketAdd);
|
||||
ssl->session->cipherSuite0 = it->suite[0];
|
||||
ssl->session->cipherSuite = it->suite[1];
|
||||
#ifdef WOLFSSL_EARLY_DATA
|
||||
ato32(it->maxEarlyDataSz, &ssl->session->maxEarlyDataSz);
|
||||
#endif
|
||||
/* Resumption master secret. */
|
||||
XMEMCPY(ssl->session->masterSecret, it->msecret, SECRET_LEN);
|
||||
#if defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
|
||||
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
|
||||
if (ssl->session->ticketNonce.data
|
||||
!= ssl->session->ticketNonce.dataStatic) {
|
||||
XFREE(ssl->session->ticketNonce.data, ssl->heap,
|
||||
DYNAMIC_TYPE_SESSION_TICK);
|
||||
ssl->session->ticketNonce.data =
|
||||
ssl->session->ticketNonce.dataStatic;
|
||||
}
|
||||
#endif /* defined(WOLFSSL_TICKET_NONCE_MALLOC) && FIPS_VERSION_GE(5,3) */
|
||||
XMEMCPY(ssl->session->ticketNonce.data, it->ticketNonce,
|
||||
it->ticketNonceLen);
|
||||
ssl->session->ticketNonce.len = it->ticketNonceLen;
|
||||
ato16(it->namedGroup, &ssl->session->namedGroup);
|
||||
#endif
|
||||
}
|
||||
ssl->version.minor = it->pv.minor;
|
||||
}
|
||||
|
||||
/* Parse ticket sent by client, returns callback return value. Doesn't
|
||||
* modify ssl and stores the InternalTicket inside psk */
|
||||
int DoClientTicket_ex(const WOLFSSL* ssl, PreSharedKey* psk)
|
||||
{
|
||||
int decryptRet;
|
||||
int ret;
|
||||
|
||||
WOLFSSL_START(WC_FUNC_TICKET_DO);
|
||||
WOLFSSL_ENTER("DoClientTicket");
|
||||
WOLFSSL_ENTER("DoClientTicket_ex");
|
||||
|
||||
ret = DoDecryptTicket(ssl, input, len, &it);
|
||||
if (ret != WOLFSSL_TICKET_RET_OK && ret != WOLFSSL_TICKET_RET_CREATE) {
|
||||
WOLFSSL_LEAVE("DoClientTicket", ret);
|
||||
return ret;
|
||||
decryptRet = DoDecryptTicket(ssl, psk->identity, psk->identityLen,
|
||||
&psk->it);
|
||||
switch (decryptRet) {
|
||||
case WOLFSSL_TICKET_RET_OK:
|
||||
psk->decryptRet = PSK_DECRYPT_OK;
|
||||
break;
|
||||
case WOLFSSL_TICKET_RET_CREATE:
|
||||
psk->decryptRet = PSK_DECRYPT_CREATE;
|
||||
break;
|
||||
default:
|
||||
psk->decryptRet = PSK_DECRYPT_FAIL;
|
||||
return decryptRet;
|
||||
}
|
||||
#ifdef WOLFSSL_CHECK_MEM_ZERO
|
||||
/* Internal ticket successfully decrypted. */
|
||||
wc_MemZero_Add("Do Client Ticket internal", it, sizeof(InternalTicket));
|
||||
#endif
|
||||
|
||||
/* get master secret */
|
||||
if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) {
|
||||
if (ssl->version.minor < it->pv.minor) {
|
||||
WOLFSSL_MSG("Ticket has greater version");
|
||||
ret = VERSION_ERROR;
|
||||
goto error;
|
||||
}
|
||||
else if (ssl->version.minor > it->pv.minor) {
|
||||
if (IsAtLeastTLSv1_3(it->pv) != IsAtLeastTLSv1_3(ssl->version)) {
|
||||
WOLFSSL_MSG("Tickets cannot be shared between "
|
||||
"TLS 1.3 and TLS 1.2 and lower");
|
||||
ret = VERSION_ERROR;
|
||||
goto error;
|
||||
}
|
||||
ret = DoClientTicketCheckVersion(ssl, psk->it);
|
||||
if (ret != 0) {
|
||||
psk->decryptRet = PSK_DECRYPT_FAIL;
|
||||
return ret;
|
||||
}
|
||||
return decryptRet;
|
||||
}
|
||||
|
||||
if (!ssl->options.downgrade) {
|
||||
WOLFSSL_MSG("Ticket has lesser version");
|
||||
ret = VERSION_ERROR;
|
||||
goto error;
|
||||
}
|
||||
/* Parse ticket sent by client, returns callback return value */
|
||||
int DoClientTicket(WOLFSSL* ssl, const byte* input, word32 len)
|
||||
{
|
||||
int decryptRet;
|
||||
int ret;
|
||||
InternalTicket* it
|
||||
|
||||
WOLFSSL_MSG("Downgrading protocol due to ticket");
|
||||
WOLFSSL_START(WC_FUNC_TICKET_DO);
|
||||
WOLFSSL_ENTER("DoClientTicket");
|
||||
|
||||
if (it->pv.minor < ssl->options.minDowngrade) {
|
||||
WOLFSSL_MSG("Ticket has lesser version than allowed");
|
||||
ret = VERSION_ERROR;
|
||||
goto error;
|
||||
}
|
||||
ssl->version.minor = it->pv.minor;
|
||||
}
|
||||
decryptRet = DoDecryptTicket(ssl, input, len, &it);
|
||||
if (decryptRet != WOLFSSL_TICKET_RET_OK &&
|
||||
decryptRet != WOLFSSL_TICKET_RET_CREATE)
|
||||
return decryptRet;
|
||||
#ifdef WOLFSSL_CHECK_MEM_ZERO
|
||||
/* Internal ticket successfully decrypted. */
|
||||
wc_MemZero_Add("Do Client Ticket internal", it, sizeof(InternalTicket));
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_TICKET_HAVE_ID
|
||||
{
|
||||
ssl->session->haveAltSessionID = 1;
|
||||
XMEMCPY(ssl->session->altSessionID, it->id, ID_LEN);
|
||||
if (wolfSSL_GetSession(ssl, NULL, 1) != NULL) {
|
||||
WOLFSSL_MSG("Found session matching the session id"
|
||||
" found in the ticket");
|
||||
}
|
||||
else {
|
||||
WOLFSSL_MSG("Can't find session matching the session id"
|
||||
" found in the ticket");
|
||||
}
|
||||
}
|
||||
ret = DoClientTicketCheckVersion(ssl, it);
|
||||
if (ret != 0) {
|
||||
ForceZero(it, sizeof(*it));
|
||||
#ifdef WOLFSSL_CHECK_MEM_ZERO
|
||||
wc_MemZero_Check(it, sizeof(InternalTicket));
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
DoClientTicketFinalize(ssl, it);
|
||||
|
||||
ForceZero(it, sizeof(*it));
|
||||
#ifdef WOLFSSL_CHECK_MEM_ZERO
|
||||
wc_MemZero_Check(it, sizeof(InternalTicket));
|
||||
#endif
|
||||
|
||||
if (!IsAtLeastTLSv1_3(ssl->version)) {
|
||||
XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN);
|
||||
/* Copy the haveExtendedMasterSecret property from the ticket to
|
||||
* the saved session, so the property may be checked later. */
|
||||
ssl->session->haveEMS = it->haveEMS;
|
||||
ato32((const byte*)&it->timestamp, &ssl->session->bornOn);
|
||||
#ifndef NO_RESUME_SUITE_CHECK
|
||||
ssl->session->cipherSuite0 = it->suite[0];
|
||||
ssl->session->cipherSuite = it->suite[1];
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#ifdef WOLFSSL_TLS13
|
||||
/* Restore information to renegotiate. */
|
||||
#ifdef WOLFSSL_32BIT_MILLI_TIME
|
||||
ato32(it->timestamp, &ssl->session->ticketSeen);
|
||||
#else
|
||||
word32 seenHi, seenLo;
|
||||
return decryptRet;
|
||||
}
|
||||
|
||||
ato32(it->timestamp , &seenHi);
|
||||
ato32(it->timestamp + OPAQUE32_LEN, &seenLo);
|
||||
ssl->session->ticketSeen = ((sword64)seenHi << 32) + seenLo;
|
||||
#endif
|
||||
ato32(it->ageAdd, &ssl->session->ticketAdd);
|
||||
ssl->session->cipherSuite0 = it->suite[0];
|
||||
ssl->session->cipherSuite = it->suite[1];
|
||||
#ifdef WOLFSSL_EARLY_DATA
|
||||
ato32(it->maxEarlyDataSz, &ssl->session->maxEarlyDataSz);
|
||||
#endif
|
||||
/* Resumption master secret. */
|
||||
XMEMCPY(ssl->session->masterSecret, it->msecret, SECRET_LEN);
|
||||
if (it->ticketNonceLen > MAX_TICKET_NONCE_STATIC_SZ) {
|
||||
WOLFSSL_MSG("Unsupported ticketNonce len in ticket");
|
||||
WOLFSSL_LEAVE("DoClientTicket", BAD_TICKET_ENCRYPT);
|
||||
return BAD_TICKET_ENCRYPT;
|
||||
}
|
||||
#if defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
|
||||
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
|
||||
if (ssl->session->ticketNonce.data
|
||||
!= ssl->session->ticketNonce.dataStatic) {
|
||||
XFREE(ssl->session->ticketNonce.data, ssl->heap,
|
||||
DYNAMIC_TYPE_SESSION_TICK);
|
||||
ssl->session->ticketNonce.data =
|
||||
ssl->session->ticketNonce.dataStatic;
|
||||
}
|
||||
#endif /* defined(WOLFSSL_TICKET_NONCE_MALLOC) && FIPS_VERSION_GE(5,3) */
|
||||
XMEMCPY(ssl->session->ticketNonce.data, it->ticketNonce,
|
||||
it->ticketNonceLen);
|
||||
ssl->session->ticketNonce.len = it->ticketNonceLen;
|
||||
ato16(it->namedGroup, &ssl->session->namedGroup);
|
||||
void CleanupClientTickets(PreSharedKey* psk)
|
||||
{
|
||||
for (; psk != NULL; psk = psk->next) {
|
||||
if (psk->decryptRet == PSK_DECRYPT_OK ||
|
||||
psk->decryptRet == PSK_DECRYPT_CREATE) {
|
||||
psk->decryptRet = PSK_DECRYPT_NONE;
|
||||
ForceZero(psk->identity, psk->identityLen);
|
||||
#ifdef WOLFSSL_CHECK_MEM_ZERO
|
||||
/* We want to check the InternalTicket area since that is what
|
||||
* we registered in DoClientTicket_ex */
|
||||
wc_MemZero_Check((((ExternalTicket*)psk->identity)->enc_ticket),
|
||||
sizeof(InternalTicket));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
ForceZero(it, sizeof(*it));
|
||||
#ifdef WOLFSSL_CHECK_MEM_ZERO
|
||||
wc_MemZero_Check(it, sizeof(InternalTicket));
|
||||
#endif
|
||||
|
||||
WOLFSSL_LEAVE("DoClientTicket", ret);
|
||||
WOLFSSL_END(WC_FUNC_TICKET_DO);
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
ForceZero(it, sizeof(*it));
|
||||
#ifdef WOLFSSL_CHECK_MEM_ZERO
|
||||
wc_MemZero_Check(it, sizeof(InternalTicket));
|
||||
#endif
|
||||
WOLFSSL_ERROR_VERBOSE(ret);
|
||||
return WOLFSSL_TICKET_RET_REJECT;
|
||||
}
|
||||
|
||||
|
||||
|
81
src/tls13.c
81
src/tls13.c
@ -5658,68 +5658,33 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz,
|
||||
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
/* Decode the identity. */
|
||||
ret = DoClientTicket(ssl, current->identity, current->identityLen);
|
||||
switch (current->decryptRet) {
|
||||
case PSK_DECRYPT_NONE:
|
||||
ret = DoClientTicket_ex(ssl, current);
|
||||
break;
|
||||
case PSK_DECRYPT_OK:
|
||||
ret = WOLFSSL_TICKET_RET_OK;
|
||||
break;
|
||||
case PSK_DECRYPT_CREATE:
|
||||
ret = WOLFSSL_TICKET_RET_CREATE;
|
||||
break;
|
||||
case PSK_DECRYPT_FAIL:
|
||||
ret = WOLFSSL_TICKET_RET_REJECT;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
if (ret == WC_PENDING_E)
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
if (ret == WOLFSSL_TICKET_RET_OK) {
|
||||
#ifdef WOLFSSL_32BIT_MILLI_TIME
|
||||
word32 now;
|
||||
sword64 diff;
|
||||
|
||||
now = TimeNowInMilliseconds();
|
||||
if (now == 0)
|
||||
return GETTIME_ERROR;
|
||||
/* Difference between now and time ticket constructed
|
||||
* (from decrypted ticket). */
|
||||
diff = now;
|
||||
diff -= ssl->session->ticketSeen;
|
||||
if (diff > (sword64)ssl->timeout * 1000 ||
|
||||
diff > (sword64)TLS13_MAX_TICKET_AGE * 1000) {
|
||||
if (DoClientTicketCheck(current, ssl->timeout, suite) != 0) {
|
||||
current = current->next;
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
sword64 diff;
|
||||
|
||||
diff = TimeNowInMilliseconds();
|
||||
if (diff == 0)
|
||||
return GETTIME_ERROR;
|
||||
/* Difference between now and time ticket constructed
|
||||
* (from decrypted ticket). */
|
||||
diff -= ssl->session->ticketSeen;
|
||||
if (diff > (sword64)ssl->timeout * 1000 ||
|
||||
diff > (sword64)TLS13_MAX_TICKET_AGE * 1000) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* Subtract client's ticket age and unobfuscate. */
|
||||
diff -= current->ticketAge;
|
||||
diff += ssl->session->ticketAdd;
|
||||
/* Check session and ticket age timeout.
|
||||
* Allow +/- 1000 milliseconds on ticket age.
|
||||
*/
|
||||
if (diff < -1000 || diff - MAX_TICKET_AGE_DIFF * 1000 > 1000)
|
||||
continue;
|
||||
|
||||
#if !defined(WOLFSSL_PSK_ONE_ID) && !defined(WOLFSSL_PRIORITIZE_PSK)
|
||||
/* Check whether resumption is possible based on suites in SSL and
|
||||
* ciphersuite in ticket.
|
||||
*/
|
||||
if ((suite[0] != ssl->session->cipherSuite0) ||
|
||||
(suite[1] != ssl->session->cipherSuite))
|
||||
continue;
|
||||
#else
|
||||
{
|
||||
byte s[2] = {
|
||||
ssl->session->cipherSuite0,
|
||||
ssl->session->cipherSuite,
|
||||
};
|
||||
if (!FindSuiteSSL(ssl, s))
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
DoClientTicketFinalize(ssl, current->it);
|
||||
|
||||
/* SERVER: using secret in session ticket for peer auth. */
|
||||
ssl->options.peerAuthGood = 1;
|
||||
@ -5893,13 +5858,23 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz,
|
||||
ret = DoPreSharedKeys(ssl, input, helloSz - bindersLen,
|
||||
suites->suites + i, usingPSK, &first);
|
||||
if (ret != 0) {
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
if (ret != WC_PENDING_E)
|
||||
#endif
|
||||
CleanupClientTickets((PreSharedKey*)ext->data);
|
||||
#endif
|
||||
WOLFSSL_MSG_EX("DoPreSharedKeys: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
CleanupClientTickets((PreSharedKey*)ext->data);
|
||||
#endif
|
||||
#else
|
||||
ret = DoPreSharedKeys(ssl, input, helloSz - bindersLen, suite, usingPSK,
|
||||
&first);
|
||||
CleanupClientTickets((PreSharedKey*)ext->data);
|
||||
if (ret != 0) {
|
||||
WOLFSSL_MSG_EX("DoPreSharedKeys: %d", ret);
|
||||
return ret;
|
||||
|
124
tests/api.c
124
tests/api.c
@ -62844,6 +62844,129 @@ static int test_wolfSSL_CRL_CERT_REVOKED_alert(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) \
|
||||
&& defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(HAVE_AESGCM) && \
|
||||
!defined(NO_SHA256) && defined(WOLFSSL_AES_128) && \
|
||||
defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256)
|
||||
|
||||
static WOLFSSL_CTX* test_TLS_13_ticket_different_ciphers_ctx = NULL;
|
||||
static WOLFSSL_SESSION* test_TLS_13_ticket_different_ciphers_session = NULL;
|
||||
static int test_TLS_13_ticket_different_ciphers_run = 0;
|
||||
|
||||
static void test_TLS_13_ticket_different_ciphers_ssl_ready(WOLFSSL* ssl)
|
||||
{
|
||||
switch (test_TLS_13_ticket_different_ciphers_run) {
|
||||
case 0:
|
||||
/* First run */
|
||||
AssertIntEQ(wolfSSL_set_cipher_list(ssl, "TLS13-AES128-GCM-SHA256"),
|
||||
WOLFSSL_SUCCESS);
|
||||
if (wolfSSL_is_server(ssl)) {
|
||||
AssertNotNull(test_TLS_13_ticket_different_ciphers_ctx =
|
||||
wolfSSL_get_SSL_CTX(ssl));
|
||||
AssertIntEQ(WOLFSSL_SUCCESS,
|
||||
wolfSSL_CTX_up_ref(test_TLS_13_ticket_different_ciphers_ctx));
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
/* Second run */
|
||||
AssertIntEQ(wolfSSL_set_cipher_list(ssl, "TLS13-AES256-GCM-SHA384:"
|
||||
"TLS13-AES128-GCM-SHA256"),
|
||||
WOLFSSL_SUCCESS);
|
||||
if (!wolfSSL_is_server(ssl)) {
|
||||
AssertIntEQ(wolfSSL_set_session(ssl,
|
||||
test_TLS_13_ticket_different_ciphers_session),
|
||||
WOLFSSL_SUCCESS);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Bad state? */
|
||||
Fail(("Should not enter here"), ("Should not enter here"));
|
||||
}
|
||||
}
|
||||
|
||||
static void test_TLS_13_ticket_different_ciphers_on_result(WOLFSSL* ssl)
|
||||
{
|
||||
switch (test_TLS_13_ticket_different_ciphers_run) {
|
||||
case 0:
|
||||
/* First run */
|
||||
AssertNotNull(test_TLS_13_ticket_different_ciphers_session =
|
||||
wolfSSL_get1_session(ssl));
|
||||
break;
|
||||
case 1:
|
||||
/* Second run */
|
||||
AssertTrue(wolfSSL_session_reused(ssl));
|
||||
break;
|
||||
default:
|
||||
/* Bad state? */
|
||||
Fail(("Should not enter here"), ("Should not enter here"));
|
||||
}
|
||||
}
|
||||
|
||||
static int test_TLS_13_ticket_different_ciphers(void)
|
||||
{
|
||||
/* Check that we handle the connection when the ticket doesn't match
|
||||
* the first ciphersuite. */
|
||||
callback_functions client_cbs, server_cbs;
|
||||
struct test_params {
|
||||
method_provider client_meth;
|
||||
method_provider server_meth;
|
||||
int doUdp;
|
||||
} params[] = {
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
/* Test that the stateless code handles sessions correctly */
|
||||
{wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, 1},
|
||||
#endif
|
||||
{wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, 0},
|
||||
};
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(params)/sizeof(*params); i++) {
|
||||
XMEMSET(&client_cbs, 0, sizeof(client_cbs));
|
||||
XMEMSET(&server_cbs, 0, sizeof(server_cbs));
|
||||
|
||||
test_TLS_13_ticket_different_ciphers_run = 0;
|
||||
|
||||
client_cbs.doUdp = server_cbs.doUdp = params[i].doUdp;
|
||||
|
||||
client_cbs.method = params[i].client_meth;
|
||||
server_cbs.method = params[i].server_meth;
|
||||
|
||||
client_cbs.ssl_ready = test_TLS_13_ticket_different_ciphers_ssl_ready;
|
||||
server_cbs.ssl_ready = test_TLS_13_ticket_different_ciphers_ssl_ready;
|
||||
|
||||
client_cbs.on_result = test_TLS_13_ticket_different_ciphers_on_result;
|
||||
|
||||
server_cbs.ticNoInit = 1;
|
||||
|
||||
test_wolfSSL_client_server_nofail(&client_cbs, &server_cbs);
|
||||
|
||||
AssertTrue(client_cbs.return_code);
|
||||
AssertTrue(server_cbs.return_code);
|
||||
|
||||
test_TLS_13_ticket_different_ciphers_run++;
|
||||
|
||||
server_cbs.ctx = test_TLS_13_ticket_different_ciphers_ctx;
|
||||
|
||||
test_wolfSSL_client_server_nofail(&client_cbs, &server_cbs);
|
||||
|
||||
AssertTrue(client_cbs.return_code);
|
||||
AssertTrue(server_cbs.return_code);
|
||||
|
||||
wolfSSL_SESSION_free(test_TLS_13_ticket_different_ciphers_session);
|
||||
test_TLS_13_ticket_different_ciphers_session = NULL;
|
||||
wolfSSL_CTX_free(test_TLS_13_ticket_different_ciphers_ctx);
|
||||
test_TLS_13_ticket_different_ciphers_ctx = NULL;
|
||||
}
|
||||
|
||||
return TEST_RES_CHECK(1);
|
||||
}
|
||||
#else
|
||||
static int test_TLS_13_ticket_different_ciphers(void)
|
||||
{
|
||||
return TEST_SKIPPED;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------*
|
||||
| Main
|
||||
*----------------------------------------------------------------------------*/
|
||||
@ -63844,6 +63967,7 @@ TEST_CASE testCases[] = {
|
||||
* !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) */
|
||||
TEST_DECL(test_wolfSSL_CTX_set_ciphersuites),
|
||||
TEST_DECL(test_wolfSSL_CRL_CERT_REVOKED_alert),
|
||||
TEST_DECL(test_TLS_13_ticket_different_ciphers),
|
||||
TEST_DECL(test_WOLFSSL_dtls_version_alert),
|
||||
TEST_DECL(test_ForceZero),
|
||||
|
||||
|
@ -3097,6 +3097,13 @@ WOLFSSL_LOCAL int TLSX_KeyShare_Parse_ClientHello(const WOLFSSL* ssl,
|
||||
|
||||
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
|
||||
|
||||
enum PskDecryptReturn {
|
||||
PSK_DECRYPT_NONE = 0,
|
||||
PSK_DECRYPT_OK,
|
||||
PSK_DECRYPT_CREATE,
|
||||
PSK_DECRYPT_FAIL,
|
||||
};
|
||||
|
||||
/* The PreSharedKey extension information - entry in a linked list. */
|
||||
typedef struct PreSharedKey {
|
||||
word16 identityLen; /* Length of identity */
|
||||
@ -3107,8 +3114,12 @@ typedef struct PreSharedKey {
|
||||
word32 binderLen; /* Length of HMAC */
|
||||
byte binder[WC_MAX_DIGEST_SIZE]; /* HMAC of handshake */
|
||||
byte hmac; /* HMAC algorithm */
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
InternalTicket* it; /* ptr to ticket */
|
||||
#endif
|
||||
byte resumption:1; /* Resumption PSK */
|
||||
byte chosen:1; /* Server's choice */
|
||||
byte decryptRet:3; /* Ticket decrypt return */
|
||||
struct PreSharedKey* next; /* List pointer */
|
||||
} PreSharedKey;
|
||||
|
||||
@ -3933,13 +3944,8 @@ typedef struct TicketNonce {
|
||||
|
||||
#ifdef WOLFSSL_DTLS
|
||||
typedef struct PskInfo {
|
||||
#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)
|
||||
/* Macro guard matches one for session->version */
|
||||
ProtocolVersion pv;
|
||||
#endif
|
||||
byte cipherSuite0;
|
||||
byte cipherSuite;
|
||||
word16 namedGroup;
|
||||
byte isValid:1;
|
||||
} PskInfo;
|
||||
#endif
|
||||
@ -5650,10 +5656,16 @@ extern const WOLF_EC_NIST_NAME kNistCurves[];
|
||||
WOLFSSL_LOCAL int SendChangeCipher(WOLFSSL* ssl);
|
||||
WOLFSSL_LOCAL int SendTicket(WOLFSSL* ssl);
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
WOLFSSL_LOCAL int DoDecryptTicket(WOLFSSL* ssl, const byte* input, word32 len,
|
||||
InternalTicket **it);
|
||||
#endif /* HAVE_SESSION_TICKET */
|
||||
WOLFSSL_LOCAL int DoDecryptTicket(const WOLFSSL* ssl, const byte* input,
|
||||
word32 len, InternalTicket **it);
|
||||
/* Return 0 when check successful. <0 on failure. */
|
||||
WOLFSSL_LOCAL int DoClientTicketCheck(const PreSharedKey* psk, sword64 timeout,
|
||||
const byte* suite);
|
||||
WOLFSSL_LOCAL void DoClientTicketFinalize(WOLFSSL* ssl, InternalTicket* it);
|
||||
WOLFSSL_LOCAL void CleanupClientTickets(PreSharedKey* psk);
|
||||
WOLFSSL_LOCAL int DoClientTicket(WOLFSSL* ssl, const byte* input, word32 len);
|
||||
WOLFSSL_LOCAL int DoClientTicket_ex(const WOLFSSL* ssl, PreSharedKey* psk);
|
||||
#endif /* HAVE_SESSION_TICKET */
|
||||
WOLFSSL_LOCAL int SendData(WOLFSSL* ssl, const void* data, int sz);
|
||||
#ifdef WOLFSSL_TLS13
|
||||
WOLFSSL_LOCAL int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType);
|
||||
|
Reference in New Issue
Block a user