diff --git a/examples/client/client.c b/examples/client/client.c index 08e2e1aa7..b42ba231e 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1753,17 +1753,20 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID; wolfSSL_method_func method = NULL; - WOLFSSL_CTX* ctx = 0; - WOLFSSL* ssl = 0; + WOLFSSL_CTX* ctx = NULL; + WOLFSSL* ssl = NULL; #ifdef WOLFSSL_WOLFSENTRY_HOOKS wolfsentry_errcode_t wolfsentry_ret; #endif - WOLFSSL* sslResume = 0; - WOLFSSL_SESSION* session = 0; + WOLFSSL* sslResume = NULL; + WOLFSSL_SESSION* session = NULL; +#if !defined(NO_SESSION_CACHE) && (defined(OPENSSL_EXTRA) || \ + defined(HAVE_EXT_CACHE)) byte* flatSession = NULL; int flatSessionSz = 0; +#endif char msg[CLI_MSG_SZ]; int msgSz = 0; @@ -1957,8 +1960,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif (void)session; - (void)flatSession; - (void)flatSessionSz; (void)sslResume; (void)atomicUser; (void)scr; @@ -3898,7 +3899,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifndef NO_SESSION_CACHE if (resumeSession) { - session = wolfSSL_get_session(ssl); + session = wolfSSL_get1_session(ssl); } #endif @@ -3914,6 +3915,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) XFREE(flatSession, NULL, DYNAMIC_TYPE_TMP_BUFFER); err_sys("flat session size check failure"); } + /* using heap based flat session, free original session */ + wolfSSL_SESSION_free(session); + session = NULL; } } #endif @@ -4006,9 +4010,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #if defined(OPENSSL_EXTRA) && defined(HAVE_EXT_CACHE) if (flatSession) { XFREE(flatSession, NULL, DYNAMIC_TYPE_TMP_BUFFER); - wolfSSL_SESSION_free(session); } #endif + wolfSSL_SESSION_free(session); + session = NULL; + #ifdef HAVE_SESSION_TICKET wolfSSL_set_SessionTicket_cb(sslResume, sessionTicketCB, (void*)"resumed session"); diff --git a/src/internal.c b/src/internal.c index dfca942ee..019bbd1a1 100644 --- a/src/internal.c +++ b/src/internal.c @@ -6637,9 +6637,16 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) } #endif /*OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */ + ssl->session.masterSecret = ssl->session._masterSecret; +#ifndef NO_CLIENT_CACHE + ssl->session.serverID = ssl->session._serverID; +#endif +#ifdef OPENSSL_EXTRA + ssl->session.sessionCtx = ssl->session._sessionCtx; +#endif #ifdef HAVE_SESSION_TICKET ssl->options.noTicketTls12 = ctx->noTicketTls12; - ssl->session.ticket = ssl->session.staticTicket; + ssl->session.ticket = ssl->session._staticTicket; #endif #ifdef WOLFSSL_MULTICAST @@ -7215,10 +7222,10 @@ void SSL_ResourceFree(WOLFSSL* ssl) #endif #ifdef HAVE_SESSION_TICKET - if (ssl->session.isDynamic) { + if (ssl->session.ticketLenAlloc > 0) { XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ssl->session.ticket = ssl->session.staticTicket; - ssl->session.isDynamic = 0; + ssl->session.ticket = ssl->session._staticTicket; + ssl->session.ticketLenAlloc = 0; ssl->session.ticketLen = 0; } #endif @@ -7492,10 +7499,10 @@ void FreeHandshakeResources(WOLFSSL* ssl) #endif /* HAVE_PK_CALLBACKS */ #ifdef HAVE_SESSION_TICKET - if (ssl->session.isDynamic) { + if (ssl->session.ticketLenAlloc > 0) { XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ssl->session.ticket = ssl->session.staticTicket; - ssl->session.isDynamic = 0; + ssl->session.ticket = ssl->session._staticTicket; + ssl->session.ticketLenAlloc = 0; ssl->session.ticketLen = 0; } #endif @@ -26787,19 +26794,19 @@ exit_scv: int SetTicket(WOLFSSL* ssl, const byte* ticket, word32 length) { /* Free old dynamic ticket if we already had one */ - if (ssl->session.isDynamic) { + if (ssl->session.ticketLenAlloc > 0) { XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ssl->session.ticket = ssl->session.staticTicket; - ssl->session.isDynamic = 0; + ssl->session.ticket = ssl->session._staticTicket; + ssl->session.ticketLenAlloc = 0; } - if (length > sizeof(ssl->session.staticTicket)) { + if (length > sizeof(ssl->session._staticTicket)) { byte* sessionTicket = (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); if (sessionTicket == NULL) return MEMORY_E; ssl->session.ticket = sessionTicket; - ssl->session.isDynamic = 1; + ssl->session.ticketLenAlloc = (word16)length; } ssl->session.ticketLen = (word16)length; diff --git a/src/ssl.c b/src/ssl.c index 077ac200f..c1398ad54 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -3176,25 +3176,28 @@ WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf, if (bufSz > 0) { /* Ticket will fit into static ticket */ - if(bufSz <= SESSION_TICKET_LEN) { - if (ssl->session.isDynamic) { - XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ssl->session.isDynamic = 0; - ssl->session.ticket = ssl->session.staticTicket; + if (bufSz <= SESSION_TICKET_LEN) { + if (ssl->session.ticketLenAlloc > 0) { + XFREE(ssl->session.ticket, ssl->heap, + DYNAMIC_TYPE_SESSION_TICK); + ssl->session.ticketLenAlloc = 0; + ssl->session.ticket = ssl->session._staticTicket; } - } else { /* Ticket requires dynamic ticket storage */ + } + else { /* Ticket requires dynamic ticket storage */ if (ssl->session.ticketLen < bufSz) { /* is dyn buffer big enough */ - if(ssl->session.isDynamic) + if (ssl->session.ticketLenAlloc > 0) { XFREE(ssl->session.ticket, ssl->heap, - DYNAMIC_TYPE_SESSION_TICK); + DYNAMIC_TYPE_SESSION_TICK); + } ssl->session.ticket = (byte*)XMALLOC(bufSz, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - if(!ssl->session.ticket) { - ssl->session.ticket = ssl->session.staticTicket; - ssl->session.isDynamic = 0; + if(ssl->session.ticket == NULL) { + ssl->session.ticket = ssl->session._staticTicket; + ssl->session.ticketLenAlloc = 0; return MEMORY_ERROR; } - ssl->session.isDynamic = 1; + ssl->session.ticketLenAlloc = (word16)bufSz; } } XMEMCPY(ssl->session.ticket, buf, bufSz); @@ -12224,11 +12227,32 @@ WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl) { WOLFSSL_ENTER("SSL_get_session"); if (ssl) - return GetSession(ssl, 0, 1); + return GetSession(ssl, NULL, 1); return NULL; } +/* The get1 version requires caller to call SSL_SESSION_free */ +WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl) +{ + WOLFSSL_SESSION* sess = NULL; + if (ssl != NULL) { + sess = GetSessionRef(ssl); + if (sess != NULL) { + /* wolfSSL_get_session returns either static cache or ref. If ref then + * increase reference counter */ + /* increase reference count if allocated session */ + #ifdef ENABLE_CLIENT_SESSION_REF + if (sess->type == WOLFSSL_SESSION_TYPE_REF) { + sess->refCount++; + } + #endif + } + } + return sess; +} + + /* * Sets the session object to use when establishing a TLS/SSL session using * the ssl object. Therefore, this function must be called before @@ -12276,9 +12300,9 @@ int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession) session = GetSessionClient(ssl, id, len); if (session) { if (SetSession(ssl, session) != WOLFSSL_SUCCESS) { - #ifdef HAVE_EXT_CACHE - FreeSession(session, 0); - #endif + #ifdef HAVE_EXT_CACHE + FreeSession(session); + #endif WOLFSSL_MSG("SetSession failed"); session = NULL; } @@ -12291,10 +12315,11 @@ int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession) ssl->session.idLen = (word16)min(SERVER_ID_LEN, (word32)len); XMEMCPY(ssl->session.serverID, id, ssl->session.idLen); } - #ifdef HAVE_EXT_CACHE - else - FreeSession(session, 0); - #endif +#ifdef HAVE_EXT_CACHE + else { + FreeSession(session); + } +#endif return WOLFSSL_SUCCESS; } @@ -14898,8 +14923,17 @@ int wolfSSL_Cleanup(void) } -#ifndef NO_SESSION_CACHE +static WC_INLINE WOLFSSL_SESSION* GetSessionPtr(const WOLFSSL_SESSION* s) +{ +#ifdef ENABLE_CLIENT_SESSION_REF + if (s && s->type == WOLFSSL_SESSION_TYPE_REF) { + s = (const WOLFSSL_SESSION*)s->refPtr; + } +#endif + return (WOLFSSL_SESSION*)s; +} +#ifndef NO_SESSION_CACHE /* some session IDs aren't random after all, let's make them random */ static WC_INLINE word32 HashSession(const byte* sessionID, word32 len, int* error) @@ -15154,7 +15188,7 @@ static int SslSessionCacheOff(const WOLFSSL* ssl, const WOLFSSL_SESSION* session WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, byte restoreSessionCerts) { - WOLFSSL_SESSION* ret = 0; + WOLFSSL_SESSION* ret = NULL; const byte* id = NULL; word32 row; int idx; @@ -15162,7 +15196,7 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, int error = 0; SessionRow* sessRow; - (void) restoreSessionCerts; + (void)restoreSessionCerts; if (SslSessionCacheOff(ssl, &ssl->session)) return NULL; @@ -15243,140 +15277,178 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, return ret; } - -static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom) +int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) { - int ret = WOLFSSL_SUCCESS; - WOLFSSL_SESSION* copyInto = &ssl->session; - int lockedRow; + int ret = WOLFSSL_SUCCESS, row = -1; #ifdef HAVE_SESSION_TICKET - int ticLen = 0; - void* ticBuff = NULL; - int isDynamic = 0; + int ticLenAlloc; + byte *ticBuff = NULL; +#endif +#ifdef ENABLE_CLIENT_SESSION_REF + WOLFSSL_SESSION* ref = NULL; #endif - if (ssl == NULL || copyFrom == NULL) { + if (ssl == NULL || session == NULL || SslSessionCacheOff(ssl, session)) { + return WOLFSSL_FAILURE; + } + + row = session->cacheRow; +#ifdef ENABLE_CLIENT_SESSION_REF + if (session->type == WOLFSSL_SESSION_TYPE_REF) { + if (session->refPtr == NULL) { + WOLFSSL_MSG("Invalid session reference"); + ret = WOLFSSL_FAILURE; + } + if (ret == WOLFSSL_SUCCESS) { + int error = 0; + ref = session; /* keep copy of ref for later */ + session = (WOLFSSL_SESSION*)session->refPtr; + row = HashSession(ref->sessionID, ID_LEN, &error) % SESSION_ROWS; + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); + ret = WOLFSSL_FAILURE; + } + } + } +#endif + + if (row < 0 || row >= SESSION_ROWS) { return BAD_FUNC_ARG; } - lockedRow = copyFrom->cacheRow; - if (lockedRow >= SESSION_ROWS) { - return BAD_FUNC_ARG; - } - - if (lockedRow >= 0 && SESSION_ROW_LOCK(&SessionCache[lockedRow]) != 0) { + /* lock session cache row */ + if (SESSION_ROW_LOCK(&SessionCache[row]) != 0) { return BAD_MUTEX_E; } -#ifdef HAVE_SESSION_TICKET - /* Free old dynamic ticket if we had one to avoid leak */ - if (copyInto->isDynamic) { - XFREE(copyInto->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - copyInto->ticket = copyInto->staticTicket; - copyInto->isDynamic = 0; +#ifdef ENABLE_CLIENT_SESSION_REF + /* verify if ID matches session cache entry */ + if (ref != NULL && + XMEMCMP(ref->sessionID, session->sessionID, ID_LEN) != 0) { + WOLFSSL_MSG("Session cache reference not longer valid"); + ret = WOLFSSL_FAILURE; } #endif #ifdef HAVE_SESSION_TICKET - /* Size of ticket to alloc if needed; Use later for alloc outside lock */ - isDynamic = copyFrom->isDynamic; - ticLen = copyFrom->ticketLen; + /* cache the old dynamic buffer and try to reuse or free later */ + ticLenAlloc = ssl->session.ticketLenAlloc; + if (ticLenAlloc > 0) { + ticBuff = ssl->session.ticket; + } #endif - /* copy ticket structure */ - XMEMCPY(copyInto, copyFrom, sizeof(WOLFSSL_SESSION)); - - if (lockedRow >= 0) { - SESSION_ROW_UNLOCK(&SessionCache[lockedRow]); - } + /* copy session structure */ + XMEMCPY(&ssl->session, session, sizeof(WOLFSSL_SESSION)); + ssl->session.type = WOLFSSL_SESSION_TYPE_SSL; + ssl->session.masterSecret = ssl->session._masterSecret; +#ifndef NO_CLIENT_CACHE + ssl->session.serverID = ssl->session._serverID; +#endif +#ifdef OPENSSL_EXTRA + ssl->session.sessionCtx = ssl->session._sessionCtx; +#endif #ifdef HAVE_SESSION_TICKET - /* Default ticket to non dynamic. This will avoid crash if we fail below */ - copyInto->ticket = copyInto->staticTicket; - copyInto->isDynamic = 0; + /* try and use existing buffer */ + if (ssl->session.ticketLenAlloc > 0 && ticBuff != NULL && + ticLenAlloc >= ssl->session.ticketLen) { + XMEMCPY(ticBuff, session->ticket, ssl->session.ticketLen); + ssl->session.ticket = ticBuff; + ssl->session.ticketLenAlloc = ticLenAlloc; + ticBuff = NULL; /* don't free later after unlock */ + } + else { + /* Default ticket to non dynamic */ + ssl->session.ticket = ssl->session._staticTicket; + ssl->session.ticketLenAlloc = 0; + } +#endif - /* If doing dynamic copy, need to alloc outside lock, then inside a lock - * confirm the size still matches and memcpy */ - if (isDynamic) { - ticBuff = (byte*)XMALLOC(ticLen, ssl->heap, - DYNAMIC_TYPE_SESSION_TICK); - if (ticBuff == NULL) { + SESSION_ROW_UNLOCK(&SessionCache[row]); + +#ifdef HAVE_SESSION_TICKET + if (ret == WOLFSSL_SUCCESS) { + if (ticBuff != NULL) { + /* free old ticket buffer */ + XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + } + /* allocate new one */ + ticBuff = (byte*)XMALLOC(ssl->session.ticketLen, ssl->heap, + DYNAMIC_TYPE_SESSION_TICK); + if (ticBuff != NULL) { + XMEMSET(ticBuff, 0, ssl->session.ticketLen); + ssl->session.ticketLenAlloc = (word16)ssl->session.ticketLen; + ssl->session.ticket = ticBuff; + } + else { ret = MEMORY_ERROR; } - if (ret == WOLFSSL_SUCCESS && lockedRow >= 0 && - SESSION_ROW_LOCK(&SessionCache[lockedRow]) != 0) { + if (ret == WOLFSSL_SUCCESS && SESSION_ROW_LOCK(&SessionCache[row]) != 0) { ret = BAD_MUTEX_E; } - if (ret == WOLFSSL_SUCCESS && (word16)ticLen != copyFrom->ticketLen) { - /* Another thread modified the ssl-> session ticket during alloc. + if (ret == WOLFSSL_SUCCESS && session->ticketLen != ssl->session.ticketLen) { + /* Another thread modified the ssl->session ticket during alloc. * Treat as error, since ticket different than when copy requested */ ret = VAR_STATE_CHANGE_E; } if (ret == WOLFSSL_SUCCESS) { - copyInto->ticket = (byte*)ticBuff; - copyInto->isDynamic = 1; - XMEMCPY(copyInto->ticket, copyFrom->ticket, ticLen); + XMEMCPY(ssl->session.ticket, session->ticket, ssl->session.ticketLen); } - if (ret != BAD_MUTEX_E && lockedRow >= 0) { - SESSION_ROW_UNLOCK(&SessionCache[lockedRow]); + if (ret != BAD_MUTEX_E) { + SESSION_ROW_UNLOCK(&SessionCache[row]); } } +#endif if (ret != WOLFSSL_SUCCESS) { + #ifdef HAVE_SESSION_TICKET /* cleanup */ - if (ticBuff) { - XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + if (ssl->session.ticket != ssl->session._staticTicket) { + XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); } - copyInto->ticket = copyInto->staticTicket; - copyInto->isDynamic = 0; + ssl->session.ticket = ssl->session._staticTicket; + ssl->session.ticketLenAlloc = 0; + #endif + return ret; } -#endif /* HAVE_SESSION_TICKET */ - - return ret; -} - -int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) -{ - if (ssl == NULL || SslSessionCacheOff(ssl, session)) - return WOLFSSL_FAILURE; + session = NULL; /* invalidate the provided session, only use ssl->session */ #ifdef OPENSSL_EXTRA /* check for application context id */ if (ssl->sessionCtxSz > 0) { - if (XMEMCMP(ssl->sessionCtx, session->sessionCtx, ssl->sessionCtxSz)) { + if (XMEMCMP(ssl->sessionCtx, ssl->session.sessionCtx, ssl->sessionCtxSz)) { /* context id did not match! */ WOLFSSL_MSG("Session context did not match"); - return SSL_FAILURE; + return WOLFSSL_FAILURE; } } #endif /* OPENSSL_EXTRA */ - if (LowResTimer() < (session->bornOn + session->timeout)) { - int ret = GetDeepCopySession(ssl, session); - if (ret == WOLFSSL_SUCCESS) { - ssl->options.resuming = 1; + if (LowResTimer() < (ssl->session.bornOn + ssl->session.timeout)) { + ssl->options.resuming = 1; #if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ defined(HAVE_SESSION_TICKET)) - ssl->version = session->version; + ssl->version = ssl->session.version; #endif #if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) - ssl->options.cipherSuite0 = session->cipherSuite0; - ssl->options.cipherSuite = session->cipherSuite; + ssl->options.cipherSuite0 = ssl->session.cipherSuite0; + ssl->options.cipherSuite = ssl->session.cipherSuite; #endif - } - - return ret; + ret = WOLFSSL_SUCCESS; } else { #if defined(OPENSSL_EXTRA) && defined(WOLFSSL_ERROR_CODE_OPENSSL) WOLFSSL_MSG("Session is expired but return success for \ OpenSSL compatibility"); - return WOLFSSL_SUCCESS; + ret = WOLFSSL_SUCCESS; +#else + ret = WOLFSSL_FAILURE; /* session timed out */ #endif /* OPENSSL_EXTRA && WOLFSSL_ERROR_CODE_OPENSSL */ - return WOLFSSL_FAILURE; /* session timed out */ } + return ret; } @@ -15486,8 +15558,17 @@ int AddSession(WOLFSSL* ssl) session = &sessRow->Sessions[idx]; } + session->type = WOLFSSL_SESSION_TYPE_CACHE; session->cacheRow = row; session->side = (byte)ssl->options.side; + session->heap = ssl->heap; + session->masterSecret = session->_masterSecret; +#ifndef NO_CLIENT_CACHE + session->serverID = session->_serverID; +#endif +#ifdef OPENSSL_EXTRA + session->sessionCtx = session->_sessionCtx; +#endif #ifdef WOLFSSL_TLS13 if (ssl->options.tls1_3) { @@ -15520,10 +15601,9 @@ int AddSession(WOLFSSL* ssl) if ((word16)ticLen != ssl->session.ticketLen) { error = VAR_STATE_CHANGE_E; } - if (error == 0) { /* Cleanup cache row's old Dynamic buff if exists */ - if (session->isDynamic) { + if (session->ticketLenAlloc > 0) { XFREE(session->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); session->ticket = NULL; } @@ -15531,17 +15611,19 @@ int AddSession(WOLFSSL* ssl) /* If too large to store in static buffer, use dyn buffer */ if (ticLen > SESSION_TICKET_LEN) { session->ticket = ticBuff; - session->isDynamic = 1; - } else { - session->ticket = session->staticTicket; - session->isDynamic = 0; + session->ticketLenAlloc = (word16)ticLen; + } + else { + session->ticket = session->_staticTicket; + session->ticketLenAlloc = 0; } session->ticketLen = (word16)ticLen; XMEMCPY(session->ticket, ssl->session.ticket, ticLen); - } else { /* cleanup, reset state */ - session->ticket = session->staticTicket; - session->isDynamic = 0; + } + else { /* cleanup, reset state */ + session->ticket = session->_staticTicket; + session->ticketLenAlloc = 0; session->ticketLen = 0; if (ticBuff) { XFREE(ticBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); @@ -15665,7 +15747,7 @@ int AddSession(WOLFSSL* ssl) cbRet = ssl->ctx->new_sess_cb(ssl, session); } if (ssl->options.internalCacheOff && cbRet == 0) { - FreeSession(session, 1); + FreeSession(session); } #endif @@ -15721,6 +15803,8 @@ WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session) WOLFSSL_X509_CHAIN* chain = NULL; WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain"); + + session = GetSessionPtr(session); if (session) chain = &session->chain; @@ -15735,6 +15819,8 @@ WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session) WOLFSSL_X509* wolfSSL_SESSION_get0_peer(WOLFSSL_SESSION* session) { WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain"); + + session = GetSessionPtr(session); if (session) { int count; @@ -23195,32 +23281,88 @@ int wolfSSL_session_reused(WOLFSSL* ssl) return resuming; } +WOLFSSL_SESSION* GetSessionRef(WOLFSSL* ssl) +{ + WOLFSSL_SESSION* session; +#ifdef ENABLE_CLIENT_SESSION_REF + WOLFSSL_SESSION* ref = NULL; + const word32 refSize = (word32)OFFSETOF(WOLFSSL_SESSION, refPtr) + + (word32)sizeof(wc_ptr_t); + int refCount = 0; +#endif + + session = GetSession(ssl, NULL, 1); + if (session == NULL) { + return session; + } + +#ifdef ENABLE_CLIENT_SESSION_REF + /* if GetSessionRef has already been called then use existing pointer */ + ref = (WOLFSSL_SESSION*)ssl->session.refPtr; + if (ref == NULL) { + ref = (WOLFSSL_SESSION*)XMALLOC(refSize, ssl->heap, + DYNAMIC_TYPE_SESSION); + } + else { + /* use existing ref count */ + refCount = ref->refCount; + } + if (ref == NULL) { + WOLFSSL_MSG("Error allocating client session reference"); + return NULL; + } + + + XMEMCPY(ref, session, refSize); + ref->type = WOLFSSL_SESSION_TYPE_REF; + ref->refCount = refCount; + ref->refPtr = (void*)session; + ref->heap = ssl->heap; + ssl->session.refPtr = ref; + session = ref; +#endif /* ENABLE_CLIENT_SESSION_REF */ + + return session; +} + #if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE) /* return a new malloc'd session with default settings on success */ -static WOLFSSL_SESSION* NewSession(void) +WOLFSSL_SESSION* NewSession(void* heap) { WOLFSSL_SESSION* ret = NULL; - ret = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL, - DYNAMIC_TYPE_OPENSSL); + ret = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), heap, + DYNAMIC_TYPE_SESSION); if (ret != NULL) { XMEMSET(ret, 0, sizeof(WOLFSSL_SESSION)); - ret->isAlloced = 1; + ret->type = WOLFSSL_SESSION_TYPE_HEAP; + ret->heap = heap; + ret->masterSecret = ret->_masterSecret; + #ifndef NO_CLIENT_CACHE + ret->serverID = ret->_serverID; + #endif + #ifdef OPENSSL_EXTRA + ret->sessionCtx = ret->_sessionCtx; + #endif + #ifdef HAVE_SESSION_TICKET + ret->ticket = ret->_staticTicket; + #endif } + (void)heap; return ret; } -WOLFSSL_SESSION* wolfSSL_SESSION_new(void) +WOLFSSL_SESSION* wolfSSL_SESSION_new_ex(void* heap) { - WOLFSSL_SESSION* ret = NewSession(); + WOLFSSL_SESSION* ret = NewSession(heap); #ifdef OPENSSL_EXTRA if (ret != NULL) { #ifndef SINGLE_THREADED if (wc_InitMutex(&ret->refMutex) != 0) { WOLFSSL_MSG("Error setting up session reference mutex"); - XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL); + XFREE(ret, ret->heap, DYNAMIC_TYPE_SESSION); return NULL; } #endif @@ -23230,11 +23372,16 @@ WOLFSSL_SESSION* wolfSSL_SESSION_new(void) return ret; } +WOLFSSL_SESSION* wolfSSL_SESSION_new(void) +{ + return wolfSSL_SESSION_new_ex(NULL); +} /* add one to session reference count * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error */ int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session) { + session = GetSessionPtr(session); if (session == NULL) return WOLFSSL_FAILURE; @@ -23260,37 +23407,46 @@ WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session) WOLFSSL_ENTER("wolfSSL_SESSION_dup"); + session = GetSessionPtr(session); if (session == NULL) return NULL; + #ifdef HAVE_SESSION_TICKET - if (session->isDynamic && !session->ticket) { + if (session->ticketLenAlloc > 0 && !session->ticket) { WOLFSSL_MSG("Session dynamic flag is set but ticket pointer is null"); return NULL; } #endif - copy = NewSession(); + copy = NewSession(session->heap); if (copy != NULL) { XMEMCPY(copy, session, sizeof(WOLFSSL_SESSION)); - copy->isAlloced = 1; + copy->type = WOLFSSL_SESSION_TYPE_HEAP; copy->cacheRow = -1; /* not in cache */ + copy->masterSecret = copy->_masterSecret; + #ifndef NO_CLIENT_CACHE + copy->serverID = copy->_serverID; + #endif + #ifdef OPENSSL_EXTRA + copy->sessionCtx = copy->_sessionCtx; + #endif #ifdef OPENSSL_EXTRA #ifndef SINGLE_THREADED if (wc_InitMutex(©->refMutex) != 0) { WOLFSSL_MSG("Error setting up session reference mutex"); - XFREE(copy, NULL, DYNAMIC_TYPE_OPENSSL); + XFREE(copy, copy->heap, DYNAMIC_TYPE_SESSION); return NULL; } #endif copy->refCount = 1; #endif #ifdef HAVE_SESSION_TICKET - if (session->isDynamic) { - copy->ticket = (byte*)XMALLOC(session->ticketLen, NULL, + if (session->ticketLenAlloc > 0) { + copy->ticket = (byte*)XMALLOC(session->ticketLen, copy->heap, DYNAMIC_TYPE_SESSION_TICK); XMEMCPY(copy->ticket, session->ticket, session->ticketLen); } else { - copy->ticket = copy->staticTicket; + copy->ticket = copy->_staticTicket; } #endif #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) @@ -23299,18 +23455,32 @@ WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session) } return copy; #else - WOLFSSL_MSG("wolfSSL_SESSION_dup was called " - "but HAVE_EXT_CACHE is not defined"); + WOLFSSL_MSG("wolfSSL_SESSION_dup feature not compiled in"); (void)session; return NULL; #endif /* HAVE_EXT_CACHE */ } -void FreeSession(WOLFSSL_SESSION* session, int isAlloced) +#endif /* OPENSSL_EXTRA || HAVE_EXT_CACHE */ + +void FreeSession(WOLFSSL_SESSION* session) { if (session == NULL) return; +#ifdef ENABLE_CLIENT_SESSION_REF + if (session->type == WOLFSSL_SESSION_TYPE_REF) { + WOLFSSL_SESSION* ref; + session->refCount--; + if (session->refCount > 0) { + return; /* don't free yet */ + } + ref = session; + session = (WOLFSSL_SESSION*)session->refPtr; + XFREE(ref, ref->heap, DYNAMIC_TYPE_SESSION); + } +#endif + #ifdef HAVE_EX_DATA_CLEANUP_HOOKS wolfSSL_CRYPTO_cleanup_ex_data(&session->ex_data); #endif @@ -23343,32 +23513,25 @@ void FreeSession(WOLFSSL_SESSION* session, int isAlloced) #endif } #endif -#if defined(HAVE_EXT_CACHE) || defined(OPENSSL_EXTRA) - if (isAlloced) { - #ifdef HAVE_SESSION_TICKET - if (session->isDynamic) - XFREE(session->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK); - #endif - XFREE(session, NULL, DYNAMIC_TYPE_OPENSSL); + +#ifdef HAVE_SESSION_TICKET + if (session->ticketLenAlloc > 0) { + XFREE(session->ticket, heap, DYNAMIC_TYPE_SESSION_TICK); } -#else - /* No need to free since cache is static */ - (void)session; - (void)isAlloced; #endif + + if (session->type == WOLFSSL_SESSION_TYPE_HEAP) { + XFREE(session, session->heap, DYNAMIC_TYPE_SESSION); + } } void wolfSSL_SESSION_free(WOLFSSL_SESSION* session) { - if (session == NULL) - return; - -#if defined(HAVE_EXT_CACHE) || defined(OPENSSL_EXTRA) - FreeSession(session, session->isAlloced); -#else - FreeSession(session, 0); -#endif + FreeSession(session); } + +#if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE) + /** * set cipher to WOLFSSL_SESSION from WOLFSSL_CIPHER * @param session a pointer to WOLFSSL_SESSION structure @@ -23381,6 +23544,7 @@ int wolfSSL_SESSION_set_cipher(WOLFSSL_SESSION* session, WOLFSSL_ENTER("wolfSSL_SESSION_set_cipher"); /* sanity check */ + session = GetSessionPtr(session); if (session == NULL || cipher == NULL) { WOLFSSL_MSG("bad argument"); return WOLFSSL_FAILURE; @@ -23529,6 +23693,7 @@ const char* wolfSSL_CIPHER_get_version(const WOLFSSL_CIPHER* cipher) const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session) { + session = GetSessionPtr(session); if (session == NULL) { return NULL; } @@ -26023,31 +26188,6 @@ char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER* cipher, char* in, return ret; } - -#ifndef NO_SESSION_CACHE - -WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl) -{ - if (ssl == NULL) { - return NULL; - } - - /* sessions are stored statically, no need for reference count */ - return wolfSSL_get_session(ssl); -} - -#endif /* NO_SESSION_CACHE */ - - - -/* was do nothing */ -/* -void OPENSSL_free(void* buf) -{ - (void)buf; -} -*/ - #ifndef NO_WOLFSSL_STUB int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path, int* ssl) @@ -31266,7 +31406,6 @@ void wolfSSL_sk_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, WOLFSSL_ENTER("wolfSSL_sk_pop_free"); if (sk == NULL) { - WOLFSSL_MSG("Error, BAD_FUNC_ARG"); return; } #if defined(WOLFSSL_QT) @@ -31523,6 +31662,7 @@ int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) #endif unsigned char *data; + sess = GetSessionPtr(sess); if (sess == NULL) { return BAD_FUNC_ARG; } @@ -31683,14 +31823,15 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, int j; word16 length; #endif -#endif +#endif /* HAVE_EXT_CACHE */ (void)p; (void)i; (void)ret; - if (sess != NULL) - s = *sess; + if (sess != NULL) { + s = GetSessionPtr(*sess); + } #ifdef HAVE_EXT_CACHE if (p == NULL || *p == NULL) @@ -31701,7 +31842,7 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, if (s == NULL) return NULL; #ifdef HAVE_SESSION_TICKET - s->isDynamic = 0; + s->ticketLenAlloc = 0; #endif } @@ -31857,10 +31998,11 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, ato16(data + idx, &s->ticketLen); idx += OPAQUE16_LEN; /* Dispose of ol dynamic ticket and ensure space for new ticket. */ - if (s->isDynamic) + if (s->ticketLenAlloc > 0) { XFREE(s->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK); + } if (s->ticketLen <= SESSION_TICKET_LEN) - s->ticket = s->staticTicket; + s->ticket = s->_staticTicket; else { s->ticket = (byte*)XMALLOC(s->ticketLen, NULL, DYNAMIC_TYPE_SESSION_TICK); @@ -31868,7 +32010,7 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, ret = MEMORY_ERROR; goto end; } - s->isDynamic = 1; + s->ticketLenAlloc = (word16)s->ticketLen; } /* ticket */ @@ -31890,7 +32032,7 @@ end: wolfSSL_SESSION_free(s); s = NULL; } -#endif +#endif /* HAVE_EXT_CACHE */ return s; } @@ -31902,14 +32044,13 @@ end: int wolfSSL_SESSION_has_ticket(const WOLFSSL_SESSION* sess) { WOLFSSL_ENTER("wolfSSL_SESSION_has_ticket"); + sess = GetSessionPtr(sess); #ifdef HAVE_SESSION_TICKET if (sess) { if ((sess->ticketLen > 0) && (sess->ticket != NULL)) { return WOLFSSL_SUCCESS; } } -#else - (void)sess; #endif return WOLFSSL_FAILURE; } @@ -31918,6 +32059,7 @@ unsigned long wolfSSL_SESSION_get_ticket_lifetime_hint( const WOLFSSL_SESSION* sess) { WOLFSSL_ENTER("wolfSSL_SESSION_get_ticket_lifetime_hint"); + sess = GetSessionPtr(sess); if (sess) { return sess->timeout; } @@ -31928,6 +32070,7 @@ long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess) { long timeout = 0; WOLFSSL_ENTER("wolfSSL_SESSION_get_timeout"); + sess = GetSessionPtr(sess); if (sess) timeout = sess->timeout; return timeout; @@ -31938,6 +32081,7 @@ long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess) { long bornOn = 0; WOLFSSL_ENTER("wolfSSL_SESSION_get_time"); + sess = GetSessionPtr(sess); if (sess) bornOn = sess->bornOn; return bornOn; @@ -31946,11 +32090,13 @@ long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess) long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t) { word32 tmptime; - if (!ses || t < 0) + + ses = GetSessionPtr(ses); + if (ses == NULL || t < 0) { return BAD_FUNC_ARG; + } tmptime = t & 0xFFFFFFFF; - ses->timeout = tmptime; return WOLFSSL_SUCCESS; @@ -47512,7 +47658,8 @@ int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data) { WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data"); #ifdef HAVE_EX_DATA - if(session != NULL) { + session = GetSessionPtr(session); + if (session != NULL) { return wolfSSL_CRYPTO_set_ex_data(&session->ex_data, idx, data); } #else @@ -48486,7 +48633,8 @@ WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl) const byte* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, unsigned int* idLen) { WOLFSSL_ENTER("wolfSSL_SESSION_get_id"); - if(!sess || !idLen) { + sess = GetSessionPtr(sess); + if (sess == NULL || idLen == NULL) { WOLFSSL_MSG("Bad func args. Please provide idLen"); return NULL; } @@ -48598,10 +48746,9 @@ int wolfSSL_SESSION_print(WOLFSSL_BIO *bp, const WOLFSSL_SESSION *x) unsigned char buf[SECRET_LEN]; unsigned int sz = 0, i; int ret; - WOLFSSL_SESSION* session = (WOLFSSL_SESSION*)x; + WOLFSSL_SESSION* session = GetSessionPtr(x); if (session == NULL) { - WOLFSSL_MSG("Bad NULL argument"); return WOLFSSL_FAILURE; } @@ -48633,7 +48780,7 @@ int wolfSSL_SESSION_print(WOLFSSL_BIO *bp, const WOLFSSL_SESSION *x) if (wolfSSL_BIO_printf(bp, " Session-ID-ctx: \n") <= 0) return WOLFSSL_FAILURE; - ret = wolfSSL_SESSION_get_master_key(x, buf, sizeof(buf)); + ret = wolfSSL_SESSION_get_master_key(session, buf, sizeof(buf)); if (wolfSSL_BIO_printf(bp, " Master-Key: ") <= 0) return WOLFSSL_FAILURE; @@ -48653,18 +48800,18 @@ int wolfSSL_SESSION_print(WOLFSSL_BIO *bp, const WOLFSSL_SESSION *x) return WOLFSSL_FAILURE; #ifdef HAVE_SESSION_TICKET - if (wolfSSL_SESSION_print_ticket(bp, x, " ") != WOLFSSL_SUCCESS) + if (wolfSSL_SESSION_print_ticket(bp, session, " ") != WOLFSSL_SUCCESS) return WOLFSSL_FAILURE; #endif #if !defined(NO_SESSION_CACHE) && (defined(OPENSSL_EXTRA) || \ defined(HAVE_EXT_CACHE)) if (wolfSSL_BIO_printf(bp, " Start Time: %ld\n", - wolfSSL_SESSION_get_time(x)) <= 0) + wolfSSL_SESSION_get_time(session)) <= 0) return WOLFSSL_FAILURE; if (wolfSSL_BIO_printf(bp, " Timeout : %ld (sec)\n", - wolfSSL_SESSION_get_timeout(x)) <= 0) + wolfSSL_SESSION_get_timeout(session)) <= 0) return WOLFSSL_FAILURE; #endif /* !NO_SESSION_CACHE && OPENSSL_EXTRA || HAVE_EXT_CACHE */ @@ -56461,13 +56608,14 @@ int wolfSSL_CTX_get_security_level(const WOLFSSL_CTX* ctx) */ int wolfSSL_SESSION_is_resumable(const WOLFSSL_SESSION *s) { + s = GetSessionPtr(s); if (s == NULL) return 0; - #ifdef HAVE_SESSION_TICKET +#ifdef HAVE_SESSION_TICKET if (s->ticketLen > 0) return 1; - #endif +#endif if (s->sessionIDSz > 0) return 1; diff --git a/tests/api.c b/tests/api.c index 10290f437..568e2564f 100644 --- a/tests/api.c +++ b/tests/api.c @@ -39177,20 +39177,21 @@ static void test_wolfSSL_cert_cb(void) static void test_wolfSSL_SESSION(void) { #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \ - !defined(NO_RSA) && defined(HAVE_EXT_CACHE) && \ - defined(HAVE_IO_TESTS_DEPENDENCIES) && !defined(NO_SESSION_CACHE) + !defined(NO_RSA) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \ + !defined(NO_SESSION_CACHE) WOLFSSL* ssl; WOLFSSL_CTX* ctx; WOLFSSL_SESSION* sess; WOLFSSL_SESSION* sess_copy; +#ifdef OPENSSL_EXTRA unsigned char* sessDer = NULL; unsigned char* ptr = NULL; -#ifdef OPENSSL_EXTRA const unsigned char context[] = "user app context"; unsigned int contextSz = (unsigned int)sizeof(context); + int sz; #endif - int ret, err, sockfd, sz; + int ret, err, sockfd; tcp_ready ready; func_args server_args; THREAD_TYPE serverThread; @@ -39208,9 +39209,12 @@ static void test_wolfSSL_SESSION(void) AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); #endif - AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM)); - AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM)); - AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0), SSL_SUCCESS); + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, + WOLFSSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, + WOLFSSL_FILETYPE_PEM)); + AssertIntEQ(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0), + WOLFSSL_SUCCESS); #ifdef WOLFSSL_ENCRYPTED_KEYS wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif @@ -39239,7 +39243,7 @@ static void test_wolfSSL_SESSION(void) /* client connection */ ssl = wolfSSL_new(ctx); tcp_connect(&sockfd, wolfSSLIP, ready.port, 0, 0, ssl); - AssertIntEQ(wolfSSL_set_fd(ssl, sockfd), SSL_SUCCESS); + AssertIntEQ(wolfSSL_set_fd(ssl, sockfd), WOLFSSL_SUCCESS); #ifdef WOLFSSL_ASYNC_CRYPT err = 0; /* Reset error */ @@ -39286,15 +39290,17 @@ static void test_wolfSSL_SESSION(void) } while (err == WC_PENDING_E); AssertIntEQ(ret, 23); + AssertPtrNE((sess = wolfSSL_get1_session(ssl)), NULL); /* ref count 1 */ + AssertPtrNE((sess_copy = wolfSSL_get1_session(ssl)), NULL); /* ref count 2 */ + AssertPtrEq(sess, sess_copy); /* they should be the same pointer */ + wolfSSL_SESSION_free(sess_copy); sess_copy = NULL; + wolfSSL_SESSION_free(sess); sess = NULL; /* free session ref */ + sess = wolfSSL_get_session(ssl); - #if defined(OPENSSL_EXTRA) +#ifdef OPENSSL_EXTRA AssertIntEQ(SSL_SESSION_is_resumable(NULL), 0); AssertIntEQ(SSL_SESSION_is_resumable(sess), 1); - #else - AssertIntEQ(wolfSSL_SESSION_is_resumable(NULL), 0); - AssertIntEQ(wolfSSL_SESSION_is_resumable(sess), 1); - #endif AssertIntEQ(wolfSSL_SESSION_has_ticket(NULL), 0); AssertIntEQ(wolfSSL_SESSION_get_ticket_lifetime_hint(NULL), 0); @@ -39305,6 +39311,7 @@ static void test_wolfSSL_SESSION(void) #else AssertIntEQ(wolfSSL_SESSION_has_ticket(sess), 0); #endif +#endif /* OPENSSL_EXTRA */ wolfSSL_shutdown(ssl); wolfSSL_free(ssl); @@ -39337,24 +39344,32 @@ static void test_wolfSSL_SESSION(void) } #endif +#ifdef HAVE_EXT_CACHE AssertNotNull(sess_copy = wolfSSL_SESSION_dup(sess)); wolfSSL_SESSION_free(sess_copy); + sess_copy = NULL; +#endif +#ifdef OPENSSL_EXTRA /* get session from DER and update the timeout */ AssertIntEQ(wolfSSL_i2d_SSL_SESSION(NULL, &sessDer), BAD_FUNC_ARG); AssertIntGT((sz = wolfSSL_i2d_SSL_SESSION(sess, &sessDer)), 0); wolfSSL_SESSION_free(sess); + sess = NULL; ptr = sessDer; AssertNull(sess = wolfSSL_d2i_SSL_SESSION(NULL, NULL, sz)); AssertNotNull(sess = wolfSSL_d2i_SSL_SESSION(NULL, (const unsigned char**)&ptr, sz)); XFREE(sessDer, NULL, DYNAMIC_TYPE_OPENSSL); + sessDer = NULL; + AssertIntGT(wolfSSL_SESSION_get_time(sess), 0); AssertIntEQ(wolfSSL_SSL_SESSION_set_timeout(sess, 500), SSL_SUCCESS); +#endif /* successful set session test */ AssertNotNull(ssl = wolfSSL_new(ctx)); - AssertIntEQ(wolfSSL_set_session(ssl, sess), SSL_SUCCESS); + AssertIntEQ(wolfSSL_set_session(ssl, sess), WOLFSSL_SUCCESS); #ifdef HAVE_SESSION_TICKET /* Test set/get session ticket */ @@ -39364,7 +39379,8 @@ static void test_wolfSSL_SESSION(void) word32 bufSz = (word32)sizeof(buf); AssertIntEQ(SSL_SUCCESS, - wolfSSL_set_SessionTicket(ssl, (byte *)ticket, (word32)XSTRLEN(ticket))); + wolfSSL_set_SessionTicket(ssl, (byte *)ticket, + (word32)XSTRLEN(ticket))); AssertIntEQ(SSL_SUCCESS, wolfSSL_get_SessionTicket(ssl, (byte *)buf, &bufSz)); AssertStrEQ(ticket, buf); @@ -39372,7 +39388,6 @@ static void test_wolfSSL_SESSION(void) #endif #ifdef OPENSSL_EXTRA - /* session timeout case */ /* make the session to be expired */ AssertIntEQ(SSL_SESSION_set_timeout(sess,1), SSL_SUCCESS); @@ -39393,16 +39408,17 @@ static void test_wolfSSL_SESSION(void) SSL_SUCCESS); AssertIntEQ(wolfSSL_set_session(ssl, sess), SSL_FAILURE); wolfSSL_free(ssl); + AssertIntEQ(SSL_CTX_set_session_id_context(NULL, context, contextSz), SSL_FAILURE); AssertIntEQ(SSL_CTX_set_session_id_context(ctx, context, contextSz), SSL_SUCCESS); AssertNotNull(ssl = wolfSSL_new(ctx)); AssertIntEQ(wolfSSL_set_session(ssl, sess), SSL_FAILURE); -#endif - wolfSSL_free(ssl); +#endif /* OPENSSL_EXTRA */ - SSL_SESSION_free(sess); + wolfSSL_free(ssl); + wolfSSL_SESSION_free(sess); wolfSSL_CTX_free(ctx); printf(resultFmt, passed); #endif diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 7d3823bd4..ec3ea5502 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3340,57 +3340,68 @@ struct WOLFSSL_X509_CHAIN { x509_buffer certs[MAX_CHAIN_DEPTH]; /* only allow max depth 4 for now */ }; +#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_SESSION_CACHE_REF) + /* enable allocation of a smaller reference for the internal cache, + * to prevent client from using internal cache reference. */ + #define ENABLE_CLIENT_SESSION_REF +#endif + +typedef enum WOLFSSL_SESSION_TYPE { + WOLFSSL_SESSION_TYPE_UNKNOWN, + WOLFSSL_SESSION_TYPE_SSL, /* in ssl->session */ + WOLFSSL_SESSION_TYPE_CACHE, /* pointer to internal cache */ + WOLFSSL_SESSION_TYPE_HEAP /* allocated from heap SESSION_new */ +#ifdef ENABLE_CLIENT_SESSION_REF + ,WOLFSSL_SESSION_TYPE_REF /* smaller allocation with reference to internal cache */ +#endif +} WOLFSSL_SESSION_TYPE; /* wolfSSL session type */ struct WOLFSSL_SESSION { - int cacheRow; /* row in session cache */ - word32 bornOn; /* create time in seconds */ - word32 timeout; /* timeout in seconds */ - byte sessionID[ID_LEN]; /* id for protocol */ + WOLFSSL_SESSION_TYPE type; + byte side; /* Either WOLFSSL_CLIENT_END or + WOLFSSL_SERVER_END */ + + int cacheRow; /* row in session cache */ + word32 bornOn; /* create time in seconds */ + word32 timeout; /* timeout in seconds */ + + byte sessionID[ID_LEN]; /* id for protocol */ byte sessionIDSz; - byte masterSecret[SECRET_LEN]; /* stored secret */ - word16 haveEMS; /* ext master secret flag */ -#ifdef SESSION_CERTS -#ifdef OPENSSL_EXTRA - WOLFSSL_X509* peer; /* peer cert */ -#endif - WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */ - #ifdef WOLFSSL_ALT_CERT_CHAINS - WOLFSSL_X509_CHAIN altChain; /* peer alt cert chain, static */ - #endif + + byte* masterSecret; /* stored secret */ + word16 haveEMS; /* ext master secret flag */ +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + WOLFSSL_X509* peer; /* peer cert */ #endif #if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ defined(HAVE_SESSION_TICKET)) - ProtocolVersion version; /* which version was used */ + ProtocolVersion version; /* which version was used */ #endif #if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) - byte cipherSuite0; /* first byte, normally 0 */ - byte cipherSuite; /* 2nd byte, actual suite */ + byte cipherSuite0; /* first byte, normally 0 */ + byte cipherSuite; /* 2nd byte, actual suite */ #endif #ifndef NO_CLIENT_CACHE - word16 idLen; /* serverID length */ - byte serverID[SERVER_ID_LEN]; /* for easier client lookup */ + word16 idLen; /* serverID length */ + byte* serverID; /* for easier client lookup */ #endif #ifdef OPENSSL_EXTRA - byte sessionCtxSz; /* sessionCtx length */ - byte sessionCtx[ID_LEN]; /* app specific context id */ -#ifndef SINGLE_THREADED - wolfSSL_Mutex refMutex; /* ref count mutex */ -#endif - int refCount; /* reference count */ + byte sessionCtxSz; /* sessionCtx length */ + byte* sessionCtx; /* app specific context id */ #endif /* OPENSSL_EXTRA */ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - byte peerVerifyRet; /* cert verify error */ + byte peerVerifyRet; /* cert verify error */ #endif #ifdef WOLFSSL_TLS13 word16 namedGroup; #endif #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) #ifdef WOLFSSL_TLS13 - word32 ticketSeen; /* Time ticket seen (ms) */ - word32 ticketAdd; /* Added by client */ - TicketNonce ticketNonce; /* Nonce used to derive PSK */ + word32 ticketSeen; /* Time ticket seen (ms) */ + word32 ticketAdd; /* Added by client */ + TicketNonce ticketNonce; /* Nonce used to derive PSK */ #endif #ifdef WOLFSSL_EARLY_DATA word32 maxEarlyDataSz; @@ -3399,23 +3410,53 @@ struct WOLFSSL_SESSION { #ifdef HAVE_SESSION_TICKET byte* ticket; word16 ticketLen; - byte staticTicket[SESSION_TICKET_LEN]; - byte isDynamic; + word16 ticketLenAlloc; /* is dynamic */ #endif -#if defined(HAVE_EXT_CACHE) || defined(OPENSSL_EXTRA) - byte isAlloced; + int refCount; /* reference count */ + void* heap; + +#ifdef ENABLE_CLIENT_SESSION_REF + /* pointer to WOLFSSL_SESSION in internal cache (for WOLFSSL_SESSION_TYPE_REF) */ + void* refPtr; +#endif + + /* Below buffers are not allocated for the WOLFSSL_SESSION_TYPE_REF, instead + * the above pointers reference the session cache for backwards + * compatibility. For all other session types the above pointers reference + * these buffers directly */ + byte _masterSecret[SECRET_LEN]; +#ifndef NO_CLIENT_CACHE + byte _serverID[SERVER_ID_LEN]; +#endif +#ifdef HAVE_SESSION_TICKET + byte _staticTicket[SESSION_TICKET_LEN]; +#endif +#ifdef OPENSSL_EXTRA + byte _sessionCtx[ID_LEN]; +#endif + +#ifdef SESSION_CERTS + WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */ + #ifdef WOLFSSL_ALT_CERT_CHAINS + WOLFSSL_X509_CHAIN altChain; /* peer alt cert chain, static */ + #endif #endif #ifdef HAVE_EX_DATA WOLFSSL_CRYPTO_EX_DATA ex_data; #endif - byte side; /* Either WOLFSSL_CLIENT_END or - WOLFSSL_SERVER_END */ +#ifdef OPENSSL_EXTRA + #ifndef SINGLE_THREADED + wolfSSL_Mutex refMutex; /* ref count mutex */ + #endif +#endif }; +WOLFSSL_LOCAL WOLFSSL_SESSION* NewSession(void* heap); WOLFSSL_LOCAL WOLFSSL_SESSION* GetSession(WOLFSSL*, byte*, byte); +WOLFSSL_LOCAL WOLFSSL_SESSION* GetSessionRef(WOLFSSL*); WOLFSSL_LOCAL int SetSession(WOLFSSL*, WOLFSSL_SESSION*); -WOLFSSL_LOCAL void FreeSession(WOLFSSL_SESSION*, int); +WOLFSSL_LOCAL void FreeSession(WOLFSSL_SESSION*); typedef int (*hmacfp) (WOLFSSL*, byte*, const byte*, word32, int, int, int, int); diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index e97e95322..cad636554 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -354,6 +354,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define SSL_set_session_id_context wolfSSL_set_session_id_context #define SSL_set_connect_state wolfSSL_set_connect_state #define SSL_set_accept_state wolfSSL_set_accept_state +#define SSL_SESSION_new wolfSSL_SESSION_new #define SSL_session_reused wolfSSL_session_reused #define SSL_SESSION_up_ref wolfSSL_SESSION_up_ref #define SSL_SESSION_dup wolfSSL_SESSION_dup diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index ff33c9c06..e34d5ceb3 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1446,6 +1446,7 @@ WOLFSSL_API int wolfSSL_session_reused(WOLFSSL*); WOLFSSL_API int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session); WOLFSSL_API WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session); WOLFSSL_API WOLFSSL_SESSION* wolfSSL_SESSION_new(void); +WOLFSSL_API WOLFSSL_SESSION* wolfSSL_SESSION_new_ex(void* heap); WOLFSSL_API void wolfSSL_SESSION_free(WOLFSSL_SESSION* session); WOLFSSL_API int wolfSSL_SESSION_set_cipher(WOLFSSL_SESSION* session, const WOLFSSL_CIPHER* cipher); @@ -1468,7 +1469,6 @@ WOLFSSL_API const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* sessio WOLFSSL_API const char* wolfSSL_get_cipher(WOLFSSL*); WOLFSSL_API void wolfSSL_sk_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk); WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl); - /* what's ref count */ WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_new(void); #if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA) diff --git a/wolfssl/test.h b/wolfssl/test.h index 8753df920..8c7840b91 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -2269,7 +2269,7 @@ static WC_INLINE int my_psk_use_session_cb(WOLFSSL* ssl, printf("use psk session callback \n"); - lsess = wolfSSL_SESSION_new(); + lsess = SSL_SESSION_new(); if (lsess == NULL) { return 0; } @@ -2305,6 +2305,7 @@ static WC_INLINE int my_psk_use_session_cb(WOLFSSL* ssl, *id = NULL; *idlen = 0; *sess = NULL; + SSL_SESSION_free(lsess); return 0; } #else diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 77a8ec67a..0fbc45a74 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -751,7 +751,11 @@ decouple library dependencies with standard string, memory and so on. #endif #ifndef OFFSETOF - #define OFFSETOF(type, field) ((size_t)&(((type *)0)->field)) + #if defined(__clang__) || defined(__GNUC__) + #define OFFSETOF(type, field) __builtin_offsetof(type, field) + #else + #define OFFSETOF(type, field) ((size_t)&(((type *)0)->field)) + #endif #endif @@ -851,6 +855,7 @@ decouple library dependencies with standard string, memory and so on. DYNAMIC_TYPE_AES = 93, DYNAMIC_TYPE_CMAC = 94, DYNAMIC_TYPE_FALCON = 95, + DYNAMIC_TYPE_SESSION = 96, DYNAMIC_TYPE_SNIFFER_SERVER = 1000, DYNAMIC_TYPE_SNIFFER_SESSION = 1001, DYNAMIC_TYPE_SNIFFER_PB = 1002,