mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-10-24 04:09:07 +03:00
ssl_sess: sanitize session cache save and restore, copy full session row, and add unit tests.
This commit is contained in:
2
.github/scripts/check-headers.sh
vendored
2
.github/scripts/check-headers.sh
vendored
@@ -59,7 +59,7 @@ else
|
||||
mapfile -t HEADERS < <(
|
||||
git ls-files 'wolfssl/*.h' 'wolfssl/wolfcrypt/*.h' \
|
||||
'wolfssl/wolfcrypt/port/**/*.h' 'wolfssl/openssl/*.h' \
|
||||
| grep -vE '^wolfssl/(options|internal|certs_test|certs_test_sm|debug-trace-error-codes|debug-untrace-error-codes)\.h$' \
|
||||
| grep -vE '^wolfssl/(options|internal|ssl_sess|certs_test|certs_test_sm|debug-trace-error-codes|debug-untrace-error-codes)\.h$' \
|
||||
| grep -vE '^wolfssl/wolfcrypt/(fips_test|selftest|tfm)\.h$' \
|
||||
| grep -vE '^wolfssl/wolfcrypt/port/aria/aria-crypt(ocb)?\.h$' \
|
||||
| grep -vE '^wolfssl/wolfcrypt/port/autosar/(CryIf|Crypto)\.h$' \
|
||||
|
||||
@@ -4790,6 +4790,7 @@ include(GNUInstallDirs)
|
||||
|
||||
set(HEADER_EXCLUDE
|
||||
"internal.h"
|
||||
"ssl_sess.h"
|
||||
"wolfssl/wolfcrypt/port/nrf51.h"
|
||||
"wolfssl/wolfcrypt/port/arm"
|
||||
"wolfssl/wolfcrypt/port/cypress"
|
||||
|
||||
@@ -30,6 +30,14 @@
|
||||
--disable-tlsv12` and `--enable-dtls --enable-dtls13 --enable-dtlscid
|
||||
--enable-session-ticket --disable-tlsv12` now build and test cleanly.
|
||||
|
||||
* **Behavioral change (`WOLFSSL_CACHE_VERSION` version bump)**:
|
||||
The `PERSIST_SESSION_CACHE` feature was fixed to now correctly save the
|
||||
entire session cache, rather than just the first session member of each row.
|
||||
This changes the on-disk layout of the session cache, and therefore the
|
||||
`WOLFSSL_CACHE_VERSION` was bumped from v2 to v3 to reflect this change.
|
||||
Session caches previously saved with v2 (both file and mem) are no longer
|
||||
restorable.
|
||||
|
||||
* **Behavioral change (`wc_PufReadSram` health tests the raw SRAM readout)**:
|
||||
the raw readout is now health tested before the context accepts it, and a
|
||||
readout that cannot be SRAM power-on noise is rejected with `PUF_READ_E`
|
||||
|
||||
@@ -171,6 +171,7 @@ INCL_TARGS := wolfssl/callbacks.h \
|
||||
wolfssl/error-ssl.h \
|
||||
wolfssl/include.am \
|
||||
wolfssl/internal.h \
|
||||
wolfssl/ssl_sess.h \
|
||||
wolfssl/ocsp.h \
|
||||
wolfssl/options.h \
|
||||
wolfssl/options.h.in \
|
||||
|
||||
471
src/ssl_sess.c
471
src/ssl_sess.c
@@ -28,87 +28,7 @@
|
||||
#else
|
||||
|
||||
#ifndef NO_SESSION_CACHE
|
||||
|
||||
/* basic config gives a cache with 33 sessions, adequate for clients and
|
||||
embedded servers
|
||||
|
||||
TITAN_SESSION_CACHE allows just over 2 million sessions, for servers
|
||||
with titanic amounts of memory with long session ID timeouts and high
|
||||
levels of traffic.
|
||||
|
||||
ENABLE_SESSION_CACHE_ROW_LOCK: Allows row level locking for increased
|
||||
performance with large session caches
|
||||
|
||||
HUGE_SESSION_CACHE yields 65,791 sessions, for servers under heavy load,
|
||||
allows over 13,000 new sessions per minute or over 200 new sessions per
|
||||
second
|
||||
|
||||
BIG_SESSION_CACHE yields 20,027 sessions
|
||||
|
||||
MEDIUM_SESSION_CACHE allows 1055 sessions, adequate for servers that
|
||||
aren't under heavy load, basically allows 200 new sessions per minute
|
||||
|
||||
SMALL_SESSION_CACHE only stores 6 sessions, good for embedded clients
|
||||
or systems where the default of is too much RAM.
|
||||
SessionCache takes about 2K, ClientCache takes about 3Kbytes
|
||||
|
||||
MICRO_SESSION_CACHE only stores 1 session, good for embedded clients
|
||||
or systems where memory is at a premium.
|
||||
SessionCache takes about 400 bytes, ClientCache takes 576 bytes
|
||||
|
||||
default SESSION_CACHE stores 33 sessions (no XXX_SESSION_CACHE defined)
|
||||
SessionCache takes about 13K bytes, ClientCache takes 17K bytes
|
||||
*/
|
||||
#if defined(TITAN_SESSION_CACHE)
|
||||
#define SESSIONS_PER_ROW 31
|
||||
#define SESSION_ROWS 64937
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
#define ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
#endif
|
||||
#elif defined(HUGE_SESSION_CACHE)
|
||||
#define SESSIONS_PER_ROW 11
|
||||
#define SESSION_ROWS 5981
|
||||
#elif defined(BIG_SESSION_CACHE)
|
||||
#define SESSIONS_PER_ROW 7
|
||||
#define SESSION_ROWS 2861
|
||||
#elif defined(MEDIUM_SESSION_CACHE)
|
||||
#define SESSIONS_PER_ROW 5
|
||||
#define SESSION_ROWS 211
|
||||
#elif defined(SMALL_SESSION_CACHE)
|
||||
#define SESSIONS_PER_ROW 2
|
||||
#define SESSION_ROWS 3
|
||||
#elif defined(MICRO_SESSION_CACHE)
|
||||
#define SESSIONS_PER_ROW 1
|
||||
#define SESSION_ROWS 1
|
||||
#else
|
||||
#define SESSIONS_PER_ROW 3
|
||||
#define SESSION_ROWS 11
|
||||
#endif
|
||||
#define INVALID_SESSION_ROW (-1)
|
||||
|
||||
#ifdef NO_SESSION_CACHE_ROW_LOCK
|
||||
#undef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
#endif
|
||||
|
||||
typedef struct SessionRow {
|
||||
int nextIdx; /* where to place next one */
|
||||
int totalCount; /* sessions ever on this row */
|
||||
word32 cacheGen; /* next entry generation */
|
||||
#ifdef SESSION_CACHE_DYNAMIC_MEM
|
||||
WOLFSSL_SESSION* Sessions[SESSIONS_PER_ROW];
|
||||
void* heap;
|
||||
#else
|
||||
WOLFSSL_SESSION Sessions[SESSIONS_PER_ROW];
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
/* not included in import/export */
|
||||
wolfSSL_RwLock row_lock;
|
||||
int lock_valid;
|
||||
#endif
|
||||
} SessionRow;
|
||||
#define SIZEOF_SESSION_ROW \
|
||||
(WC_OFFSETOF(SessionRow, Sessions) + sizeof(WOLFSSL_SESSION))
|
||||
#include <wolfssl/ssl_sess.h>
|
||||
|
||||
static WC_THREADSHARED SessionRow SessionCache[SESSION_ROWS];
|
||||
|
||||
@@ -129,55 +49,13 @@
|
||||
#endif
|
||||
|
||||
#if !defined(NO_SESSION_CACHE_REF) && defined(NO_CLIENT_CACHE)
|
||||
#error ClientCache is required when not using NO_SESSION_CACHE_REF
|
||||
#error ClientCache is required when not using NO_SESSION_CACHE_REF
|
||||
#endif
|
||||
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
|
||||
#ifndef CLIENT_SESSIONS_MULTIPLIER
|
||||
#ifdef NO_SESSION_CACHE_REF
|
||||
#define CLIENT_SESSIONS_MULTIPLIER 1
|
||||
#else
|
||||
/* ClientSession objects are lightweight (compared to
|
||||
* WOLFSSL_SESSION) so to decrease chance that user will reuse
|
||||
* the wrong session, increase the ClientCache size. This will
|
||||
* make the entire ClientCache about the size of one
|
||||
* WOLFSSL_SESSION object. */
|
||||
#define CLIENT_SESSIONS_MULTIPLIER 8
|
||||
#endif
|
||||
#endif
|
||||
#define CLIENT_SESSIONS_PER_ROW \
|
||||
(SESSIONS_PER_ROW * CLIENT_SESSIONS_MULTIPLIER)
|
||||
#define CLIENT_SESSION_ROWS (SESSION_ROWS * CLIENT_SESSIONS_MULTIPLIER)
|
||||
|
||||
#if CLIENT_SESSIONS_PER_ROW > 65535
|
||||
#error CLIENT_SESSIONS_PER_ROW too big
|
||||
#endif
|
||||
#if CLIENT_SESSION_ROWS > 65535
|
||||
#error CLIENT_SESSION_ROWS too big
|
||||
#endif
|
||||
|
||||
struct ClientSession {
|
||||
word16 serverRow; /* SessionCache Row id */
|
||||
word16 serverIdx; /* SessionCache Idx (column) */
|
||||
word32 sessionIDHash;
|
||||
word32 cacheGen; /* SessionCache entry generation */
|
||||
};
|
||||
#ifndef WOLFSSL_CLIENT_SESSION_DEFINED
|
||||
typedef struct ClientSession ClientSession;
|
||||
#define WOLFSSL_CLIENT_SESSION_DEFINED
|
||||
#endif
|
||||
|
||||
typedef struct ClientRow {
|
||||
int nextIdx; /* where to place next one */
|
||||
int totalCount; /* sessions ever on this row */
|
||||
ClientSession Clients[CLIENT_SESSIONS_PER_ROW];
|
||||
} ClientRow;
|
||||
|
||||
static WC_THREADSHARED ClientRow ClientCache[CLIENT_SESSION_ROWS];
|
||||
/* Client Cache */
|
||||
/* uses session mutex */
|
||||
|
||||
/* ClientCache mutex */
|
||||
static WC_THREADSHARED wolfSSL_Mutex clisession_mutex
|
||||
WOLFSSL_MUTEX_INITIALIZER_CLAUSE(clisession_mutex);
|
||||
@@ -188,31 +66,31 @@
|
||||
|
||||
void EvictSessionFromCache(WOLFSSL_SESSION* session)
|
||||
{
|
||||
#ifdef HAVE_EX_DATA
|
||||
#ifdef HAVE_EX_DATA
|
||||
byte save_ownExData = session->ownExData;
|
||||
session->ownExData = 1; /* Make sure ex_data access doesn't lead back
|
||||
* into the cache. */
|
||||
#endif
|
||||
#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA)
|
||||
#endif /* HAVE_EX_DATA */
|
||||
#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA)
|
||||
if (session->rem_sess_cb != NULL) {
|
||||
session->rem_sess_cb(NULL, session);
|
||||
session->rem_sess_cb = NULL;
|
||||
}
|
||||
#endif
|
||||
#endif /* HAVE_EXT_CACHE || HAVE_EX_DATA */
|
||||
ForceZero(session->masterSecret, SECRET_LEN);
|
||||
XMEMSET(session->sessionID, 0, ID_LEN);
|
||||
session->sessionIDSz = 0;
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
if (session->ticketLenAlloc > 0) {
|
||||
XFREE(session->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK);
|
||||
session->ticket = session->staticTicket;
|
||||
session->ticketLen = 0;
|
||||
session->ticketLenAlloc = 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_EX_DATA
|
||||
#endif /* HAVE_SESSION_TICKET */
|
||||
#ifdef HAVE_EX_DATA
|
||||
session->ownExData = save_ownExData;
|
||||
#endif
|
||||
#endif /* HAVE_EX_DATA */
|
||||
|
||||
#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) && \
|
||||
defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
|
||||
@@ -394,40 +272,16 @@ int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession)
|
||||
* cache.
|
||||
*/
|
||||
#if defined(PERSIST_SESSION_CACHE) && !defined(SESSION_CACHE_DYNAMIC_MEM)
|
||||
|
||||
/* for persistence, if changes to layout need to increment and modify
|
||||
save_session_cache() and restore_session_cache and memory versions too */
|
||||
#define WOLFSSL_CACHE_VERSION 3
|
||||
|
||||
/* Session Cache Header information */
|
||||
typedef struct {
|
||||
int version; /* cache layout version id */
|
||||
int rows; /* session rows */
|
||||
int columns; /* session columns */
|
||||
int sessionSz; /* sizeof WOLFSSL_SESSION */
|
||||
} cache_header_t;
|
||||
|
||||
/* current persistence layout is:
|
||||
|
||||
1) cache_header_t
|
||||
2) SessionCache
|
||||
3) ClientCache
|
||||
|
||||
update WOLFSSL_CACHE_VERSION if change layout for the following
|
||||
PERSISTENT_SESSION_CACHE functions
|
||||
*/
|
||||
|
||||
/* get how big the the session cache save buffer needs to be */
|
||||
int wolfSSL_get_session_cache_memsize(void)
|
||||
{
|
||||
int sz = (int)(sizeof(SessionCache) + sizeof(cache_header_t));
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
sz += (int)(sizeof(ClientCache));
|
||||
#endif
|
||||
#endif
|
||||
return sz;
|
||||
}
|
||||
|
||||
|
||||
/* Persist session cache to memory */
|
||||
int wolfSSL_memsave_session_cache(void* mem, int sz)
|
||||
{
|
||||
@@ -441,25 +295,26 @@ int wolfSSL_memsave_session_cache(void* mem, int sz)
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
row = (SessionRow*)((byte*)mem + sizeof(cache_header));
|
||||
|
||||
if (sz < wolfSSL_get_session_cache_memsize()) {
|
||||
WOLFSSL_MSG("Memory buffer too small");
|
||||
return BUFFER_E;
|
||||
}
|
||||
|
||||
XMEMSET(mem, 0, sz);
|
||||
row = (SessionRow*)((byte*)mem + sizeof(cache_header));
|
||||
|
||||
cache_header.version = WOLFSSL_CACHE_VERSION;
|
||||
cache_header.rows = SESSION_ROWS;
|
||||
cache_header.columns = SESSIONS_PER_ROW;
|
||||
cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION);
|
||||
XMEMCPY(mem, &cache_header, sizeof(cache_header));
|
||||
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
if (SESSION_ROW_RD_LOCK(row) != 0) {
|
||||
WOLFSSL_MSG("Session cache mutex lock failed");
|
||||
return BAD_MUTEX_E;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
for (i = 0; i < cache_header.rows; ++i) {
|
||||
#ifdef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
if (SESSION_ROW_RD_LOCK(&SessionCache[i]) != 0) {
|
||||
@@ -473,62 +328,144 @@ int wolfSSL_memsave_session_cache(void* mem, int sz)
|
||||
SESSION_ROW_UNLOCK(&SessionCache[i]);
|
||||
#endif
|
||||
}
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
SESSION_ROW_UNLOCK(row);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
if (wc_LockMutex(&clisession_mutex) != 0) {
|
||||
WOLFSSL_MSG("Client cache mutex lock failed");
|
||||
return BAD_MUTEX_E;
|
||||
}
|
||||
XMEMCPY(row, ClientCache, sizeof(ClientCache));
|
||||
wc_UnLockMutex(&clisession_mutex);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
WOLFSSL_LEAVE("wolfSSL_memsave_session_cache", WOLFSSL_SUCCESS);
|
||||
|
||||
return WOLFSSL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#if !defined(SESSION_CACHE_DYNAMIC_MEM) && \
|
||||
(defined(HAVE_SESSION_TICKET) || \
|
||||
(defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)))
|
||||
static void SessionSanityPointerSet(SessionRow* row)
|
||||
/* attempt to sanitize a restored session row:
|
||||
* - shallow copy pointers are nulled, and ex_data is zeroed.
|
||||
* - ticket len is clamped
|
||||
* - fields that cannot be meaningfully sanitized will error out if invalid.
|
||||
*
|
||||
* returns 0 on success
|
||||
* returns -1 on error
|
||||
* */
|
||||
static int SessionSanityPointerSet(int row)
|
||||
{
|
||||
int j;
|
||||
SessionRow * srow = NULL;
|
||||
int ret = 0;
|
||||
int j;
|
||||
|
||||
/* Reset pointers to safe values after raw copy */
|
||||
if (row < 0 || row >= SESSION_ROWS) {
|
||||
WOLFSSL_MSG_EX("session sanity: bad row index: %d", row);
|
||||
return -1;
|
||||
}
|
||||
|
||||
srow = &SessionCache[row];
|
||||
|
||||
if (srow->nextIdx < 0 || srow->nextIdx >= SESSIONS_PER_ROW) {
|
||||
WOLFSSL_MSG_EX("session sanity: bad row cache index: %d",
|
||||
srow->nextIdx);
|
||||
srow->nextIdx = 0;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (srow->totalCount < 0 || srow->totalCount > SESSIONS_PER_ROW) {
|
||||
WOLFSSL_MSG_EX("session sanity: bad row cotal count: %d",
|
||||
srow->totalCount);
|
||||
srow->totalCount = 0;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
/* Reset pointers to safe values after raw copy.
|
||||
* Don't break early on error, we always sanitize the entire row. */
|
||||
for (j = 0; j < SESSIONS_PER_ROW; j++) {
|
||||
WOLFSSL_SESSION* s = &row->Sessions[j];
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
WOLFSSL_SESSION * s = &srow->Sessions[j];
|
||||
|
||||
/* set type and cacheRow index */
|
||||
s->type = WOLFSSL_SESSION_TYPE_CACHE;
|
||||
s->cacheRow = row;
|
||||
|
||||
/* clamp ticketLen */
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
s->ticket = s->staticTicket;
|
||||
s->ticketLenAlloc = 0;
|
||||
if (s->ticketLen > SESSION_TICKET_LEN) {
|
||||
s->ticketLen = SESSION_TICKET_LEN;
|
||||
}
|
||||
#endif
|
||||
#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) && \
|
||||
defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
|
||||
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
|
||||
#endif /* HAVE_SESSION_TICKET */
|
||||
#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) && \
|
||||
defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
|
||||
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && \
|
||||
FIPS_VERSION_GE(5,3)))
|
||||
s->ticketNonce.data = s->ticketNonce.dataStatic;
|
||||
if (s->ticketNonce.len > MAX_TICKET_NONCE_STATIC_SZ) {
|
||||
s->ticketNonce.len = MAX_TICKET_NONCE_STATIC_SZ;
|
||||
}
|
||||
#endif
|
||||
#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
|
||||
#endif /* WOLFSSL_TLS13 && HAVE_SESSION_TICKET && etc. */
|
||||
|
||||
#ifdef SESSION_CERTS
|
||||
if (s->chain.count < 0 || s->chain.count > MAX_CHAIN_DEPTH) {
|
||||
WOLFSSL_MSG_EX("session sanity: bad chain count: %d",
|
||||
s->chain.count);
|
||||
s->chain.count = 0;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (s->chain.count) {
|
||||
int k;
|
||||
for (k = 0; k < s->chain.count; ++k) {
|
||||
if (s->chain.certs[k].length < 0 ||
|
||||
s->chain.certs[k].length > MAX_X509_SIZE) {
|
||||
WOLFSSL_MSG_EX("session sanity: cert[%d] bad length: %d",
|
||||
k, s->chain.certs[k].length);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* SESSION_CERTS */
|
||||
|
||||
#ifdef WOLFSSL_SESSION_ID_CTX
|
||||
/* sessionCtx is deep copied, but can't exceed ID_LEN. */
|
||||
if (s->sessionCtxSz > ID_LEN) {
|
||||
WOLFSSL_MSG_EX("session sanity: sessionCtxSz: %d",
|
||||
s->sessionCtxSz);
|
||||
ret = -1;
|
||||
}
|
||||
#endif /* WOLFSSL_SESSION_ID_CTX */
|
||||
|
||||
/* Sanitize the restored session: none of the following fields are
|
||||
* meaningful after session restoration.
|
||||
*
|
||||
* We could null these instead in wolfSSL_[mem]save_session_cache(),
|
||||
* but that would require an extra scratch copy (because we save from
|
||||
* the live session). */
|
||||
#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
|
||||
s->peer = NULL;
|
||||
#endif
|
||||
#endif /* SESSION_CERTS && OPENSSL_EXTRA */
|
||||
#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA)
|
||||
s->rem_sess_cb = NULL;
|
||||
#endif /* HAVE_EXT_CACHE || HAVE_EX_DATA */
|
||||
s->heap = NULL;
|
||||
#ifdef HAVE_EX_DATA
|
||||
XMEMSET(&s->ex_data, 0, sizeof(WOLFSSL_CRYPTO_EX_DATA));
|
||||
s->ownExData = 1;
|
||||
#endif /* HAVE_EX_DATA */
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Restore the persistent session cache from memory */
|
||||
int wolfSSL_memrestore_session_cache(const void* mem, int sz)
|
||||
{
|
||||
int i;
|
||||
word32 cacheGen;
|
||||
int ret = 0;
|
||||
cache_header_t cache_header;
|
||||
SessionRow* row;
|
||||
|
||||
@@ -555,12 +492,12 @@ int wolfSSL_memrestore_session_cache(const void* mem, int sz)
|
||||
return CACHE_MATCH_ERROR;
|
||||
}
|
||||
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
if (SESSION_ROW_WR_LOCK(&SessionCache[0]) != 0) {
|
||||
WOLFSSL_MSG("Session cache mutex lock failed");
|
||||
return BAD_MUTEX_E;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
for (i = 0; i < cache_header.rows; ++i) {
|
||||
#ifdef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
if (SESSION_ROW_WR_LOCK(&SessionCache[i]) != 0) {
|
||||
@@ -576,31 +513,42 @@ int wolfSSL_memrestore_session_cache(const void* mem, int sz)
|
||||
* the restored ClientCache entries were issued against. */
|
||||
if (SessionCache[i].cacheGen < cacheGen)
|
||||
SessionCache[i].cacheGen = cacheGen;
|
||||
#if !defined(SESSION_CACHE_DYNAMIC_MEM) && \
|
||||
(defined(HAVE_SESSION_TICKET) || \
|
||||
(defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)))
|
||||
SessionSanityPointerSet(&SessionCache[i]);
|
||||
#endif
|
||||
|
||||
ret = SessionSanityPointerSet(i);
|
||||
#ifdef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
SESSION_ROW_UNLOCK(&SessionCache[i]);
|
||||
#endif
|
||||
if (ret) {
|
||||
/* session data is corrupted
|
||||
* Wiping the rows must not restart the generation counters. */
|
||||
int j;
|
||||
for (j = 0; j < SESSION_ROWS; j++) {
|
||||
cacheGen = SessionCache[j].cacheGen;
|
||||
XMEMSET(&SessionCache[j], 0, sizeof(SessionCache[j]));
|
||||
SessionCache[j].cacheGen = cacheGen;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
SESSION_ROW_UNLOCK(&SessionCache[0]);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
if (wc_LockMutex(&clisession_mutex) != 0) {
|
||||
WOLFSSL_MSG("Client cache mutex lock failed");
|
||||
return BAD_MUTEX_E;
|
||||
if (ret == 0) {
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
if (wc_LockMutex(&clisession_mutex) != 0) {
|
||||
WOLFSSL_MSG("Client cache mutex lock failed");
|
||||
return BAD_MUTEX_E;
|
||||
}
|
||||
XMEMCPY(ClientCache, row, sizeof(ClientCache));
|
||||
wc_UnLockMutex(&clisession_mutex);
|
||||
#endif
|
||||
}
|
||||
XMEMCPY(ClientCache, row, sizeof(ClientCache));
|
||||
wc_UnLockMutex(&clisession_mutex);
|
||||
#endif
|
||||
|
||||
WOLFSSL_LEAVE("wolfSSL_memrestore_session_cache", WOLFSSL_SUCCESS);
|
||||
WOLFSSL_LEAVE("wolfSSL_memrestore_session_cache",
|
||||
ret == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE);
|
||||
|
||||
return WOLFSSL_SUCCESS;
|
||||
return ret == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
|
||||
}
|
||||
|
||||
#if !defined(NO_FILESYSTEM)
|
||||
@@ -635,13 +583,13 @@ int wolfSSL_save_session_cache(const char *fname)
|
||||
return FWRITE_ERROR;
|
||||
}
|
||||
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
if (SESSION_ROW_RD_LOCK(&SessionCache[0]) != 0) {
|
||||
WOLFSSL_MSG("Session cache mutex lock failed");
|
||||
XFCLOSE(file);
|
||||
return BAD_MUTEX_E;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
/* session cache */
|
||||
for (i = 0; i < cache_header.rows; ++i) {
|
||||
#ifdef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
@@ -662,11 +610,11 @@ int wolfSSL_save_session_cache(const char *fname)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
SESSION_ROW_UNLOCK(&SessionCache[0]);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
/* client cache */
|
||||
if (wc_LockMutex(&clisession_mutex) != 0) {
|
||||
WOLFSSL_MSG("Client cache mutex lock failed");
|
||||
@@ -679,7 +627,7 @@ int wolfSSL_save_session_cache(const char *fname)
|
||||
rc = FWRITE_ERROR;
|
||||
}
|
||||
wc_UnLockMutex(&clisession_mutex);
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
|
||||
XFCLOSE(file);
|
||||
WOLFSSL_LEAVE("wolfSSL_save_session_cache", rc);
|
||||
@@ -687,7 +635,6 @@ int wolfSSL_save_session_cache(const char *fname)
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* Restore the persistent session cache from file */
|
||||
/* doesn't use memstore because of additional memory use */
|
||||
int wolfSSL_restore_session_cache(const char *fname)
|
||||
@@ -703,13 +650,14 @@ int wolfSSL_restore_session_cache(const char *fname)
|
||||
|
||||
file = XFOPEN(fname, "rb");
|
||||
if (file == XBADFILE) {
|
||||
WOLFSSL_MSG("Couldn't open session cache save file");
|
||||
WOLFSSL_MSG_EX("Couldn't open session cache save file: %s", fname);
|
||||
return WOLFSSL_BAD_FILE;
|
||||
}
|
||||
/* cache header */
|
||||
ret = (int)XFREAD(&cache_header, sizeof(cache_header), 1, file);
|
||||
if (ret != 1) {
|
||||
WOLFSSL_MSG("Session cache header file read failed");
|
||||
WOLFSSL_MSG_EX("Session cache header file read failed: %s: %d", fname,
|
||||
ret);
|
||||
XFCLOSE(file);
|
||||
return FREAD_ERROR;
|
||||
}
|
||||
@@ -718,18 +666,18 @@ int wolfSSL_restore_session_cache(const char *fname)
|
||||
cache_header.columns != SESSIONS_PER_ROW ||
|
||||
cache_header.sessionSz != (int)sizeof(WOLFSSL_SESSION)) {
|
||||
|
||||
WOLFSSL_MSG("Session cache header match failed");
|
||||
WOLFSSL_MSG_EX("Session cache header match failed: %s", fname);
|
||||
XFCLOSE(file);
|
||||
return CACHE_MATCH_ERROR;
|
||||
}
|
||||
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
if (SESSION_ROW_WR_LOCK(&SessionCache[0]) != 0) {
|
||||
WOLFSSL_MSG("Session cache mutex lock failed");
|
||||
XFCLOSE(file);
|
||||
return BAD_MUTEX_E;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
/* session cache */
|
||||
for (i = 0; i < cache_header.rows; ++i) {
|
||||
#ifdef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
@@ -742,51 +690,61 @@ int wolfSSL_restore_session_cache(const char *fname)
|
||||
|
||||
cacheGen = SessionCache[i].cacheGen;
|
||||
ret = (int)XFREAD(&SessionCache[i], SIZEOF_SESSION_ROW, 1, file);
|
||||
if (ret != 1) {
|
||||
WOLFSSL_MSG("Session cache member file read failed");
|
||||
rc = FREAD_ERROR;
|
||||
}
|
||||
/* Generations already handed to live handles must not be reissued.
|
||||
* The entry keeps the one it was saved with, which is the generation
|
||||
* the restored ClientCache entries were issued against. */
|
||||
if (ret != 1 || SessionCache[i].cacheGen < cacheGen)
|
||||
if (rc != WOLFSSL_SUCCESS || SessionCache[i].cacheGen < cacheGen) {
|
||||
SessionCache[i].cacheGen = cacheGen;
|
||||
#if !defined(SESSION_CACHE_DYNAMIC_MEM) && \
|
||||
(defined(HAVE_SESSION_TICKET) || \
|
||||
(defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)))
|
||||
SessionSanityPointerSet(&SessionCache[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rc == WOLFSSL_SUCCESS) {
|
||||
/* file read success. now sanitize the imported session row. */
|
||||
ret = SessionSanityPointerSet(i);
|
||||
|
||||
if (ret) {
|
||||
/* session data is corrupted */
|
||||
rc = WOLFSSL_FAILURE;
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
SESSION_ROW_UNLOCK(&SessionCache[i]);
|
||||
#endif
|
||||
if (ret != 1) {
|
||||
if (rc != WOLFSSL_SUCCESS) {
|
||||
int j;
|
||||
WOLFSSL_MSG("Session cache member file read failed");
|
||||
/* Wiping the rows must not restart the generation counters. */
|
||||
for (j = 0; j < SESSION_ROWS; j++) {
|
||||
cacheGen = SessionCache[j].cacheGen;
|
||||
XMEMSET(&SessionCache[j], 0, sizeof(SessionCache[j]));
|
||||
SessionCache[j].cacheGen = cacheGen;
|
||||
}
|
||||
rc = FREAD_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
SESSION_ROW_UNLOCK(&SessionCache[0]);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
/* client cache */
|
||||
if (wc_LockMutex(&clisession_mutex) != 0) {
|
||||
WOLFSSL_MSG("Client cache mutex lock failed");
|
||||
XFCLOSE(file);
|
||||
return BAD_MUTEX_E;
|
||||
if (rc == WOLFSSL_SUCCESS) {
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
/* client cache */
|
||||
if (wc_LockMutex(&clisession_mutex) != 0) {
|
||||
WOLFSSL_MSG("Client cache mutex lock failed");
|
||||
XFCLOSE(file);
|
||||
return BAD_MUTEX_E;
|
||||
}
|
||||
ret = (int)XFREAD(ClientCache, sizeof(ClientCache), 1, file);
|
||||
if (ret != 1) {
|
||||
WOLFSSL_MSG("Client cache member file read failed");
|
||||
XMEMSET(ClientCache, 0, sizeof ClientCache);
|
||||
rc = FREAD_ERROR;
|
||||
}
|
||||
wc_UnLockMutex(&clisession_mutex);
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
}
|
||||
ret = (int)XFREAD(ClientCache, sizeof(ClientCache), 1, file);
|
||||
if (ret != 1) {
|
||||
WOLFSSL_MSG("Client cache member file read failed");
|
||||
XMEMSET(ClientCache, 0, sizeof ClientCache);
|
||||
rc = FREAD_ERROR;
|
||||
}
|
||||
wc_UnLockMutex(&clisession_mutex);
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
|
||||
XFCLOSE(file);
|
||||
WOLFSSL_LEAVE("wolfSSL_restore_session_cache", rc);
|
||||
@@ -797,7 +755,6 @@ int wolfSSL_restore_session_cache(const char *fname)
|
||||
#endif /* !NO_FILESYSTEM */
|
||||
#endif /* PERSIST_SESSION_CACHE && !SESSION_CACHE_DYNAMIC_MEM */
|
||||
|
||||
|
||||
/* on by default if built in but allow user to turn off */
|
||||
WOLFSSL_ABI
|
||||
long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode)
|
||||
@@ -1058,8 +1015,9 @@ WOLFSSL_SESSION* wolfSSL_GetSessionClient(WOLFSSL* ssl, const byte* id, int len)
|
||||
WOLFSSL_SESSION* current;
|
||||
SessionRow* sessRow;
|
||||
|
||||
if (clSess[idx].serverRow >= SESSION_ROWS) {
|
||||
WOLFSSL_MSG("Client cache serverRow invalid");
|
||||
if (clSess[idx].serverRow >= SESSION_ROWS ||
|
||||
clSess[idx].serverIdx >= SESSIONS_PER_ROW ) {
|
||||
WOLFSSL_MSG("Client cache serverRow or serverIdx invalid");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1070,11 +1028,11 @@ WOLFSSL_SESSION* wolfSSL_GetSessionClient(WOLFSSL* ssl, const byte* id, int len)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef SESSION_CACHE_DYNAMIC_MEM
|
||||
#ifdef SESSION_CACHE_DYNAMIC_MEM
|
||||
current = sessRow->Sessions[clSess[idx].serverIdx];
|
||||
#else
|
||||
#else
|
||||
current = &sessRow->Sessions[clSess[idx].serverIdx];
|
||||
#endif
|
||||
#endif
|
||||
/* Require the same length as well as the same bytes. Comparing only
|
||||
* the requested length lets a short ID alias the prefix of a longer
|
||||
* cached one, mixing sessions the application meant to keep apart. */
|
||||
@@ -1556,7 +1514,8 @@ int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session)
|
||||
|
||||
/* We need to lock the session as the first step if its in the cache */
|
||||
if (session->type == WOLFSSL_SESSION_TYPE_CACHE) {
|
||||
if (session->cacheRow < SESSION_ROWS) {
|
||||
if (session->cacheRow != INVALID_SESSION_ROW &&
|
||||
session->cacheRow < SESSION_ROWS) {
|
||||
sessRow = &SessionCache[session->cacheRow];
|
||||
if (SESSION_ROW_RD_LOCK(sessRow) != 0) {
|
||||
WOLFSSL_MSG("Session row lock failed");
|
||||
@@ -1983,11 +1942,11 @@ int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession,
|
||||
}
|
||||
|
||||
for (i = 0; i < SESSIONS_PER_ROW && i < sessRow->totalCount; i++) {
|
||||
#ifdef SESSION_CACHE_DYNAMIC_MEM
|
||||
#ifdef SESSION_CACHE_DYNAMIC_MEM
|
||||
cacheSession = sessRow->Sessions[i];
|
||||
#else
|
||||
#else
|
||||
cacheSession = &sessRow->Sessions[i];
|
||||
#endif
|
||||
#endif
|
||||
if (cacheSession && XMEMCMP(id,
|
||||
cacheSession->sessionID, ID_LEN) == 0 &&
|
||||
cacheSession->side == side) {
|
||||
@@ -2000,6 +1959,22 @@ int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession,
|
||||
|
||||
if (!overwrite)
|
||||
idx = (word32)sessRow->nextIdx;
|
||||
|
||||
if (idx >= SESSIONS_PER_ROW) {
|
||||
/* bad index, possible corrupted session cache memory.
|
||||
* reset index to a safe value, unlock the row, and return error. */
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK);
|
||||
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
|
||||
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
|
||||
XFREE(preallocNonce, addSession->heap, DYNAMIC_TYPE_SESSION_TICK);
|
||||
#endif
|
||||
#endif
|
||||
WOLFSSL_MSG_EX("Invalid session cache index: %d", idx);
|
||||
sessRow->nextIdx = 0;
|
||||
SESSION_ROW_UNLOCK(sessRow);
|
||||
return MEMORY_E;
|
||||
}
|
||||
#ifdef SESSION_INDEX
|
||||
if (sessionIndex != NULL)
|
||||
*sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx;
|
||||
|
||||
@@ -1933,3 +1933,840 @@ int test_wolfSSL_client_cache_id_overwrite(void)
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
#if defined(PERSIST_SESSION_CACHE) && !defined(NO_SESSION_CACHE) && \
|
||||
!defined(SESSION_CACHE_DYNAMIC_MEM) && !defined(TITAN_SESSION_CACHE) && \
|
||||
!defined(HUGE_SESSION_CACHE)
|
||||
/* Several tests to ensure persistent session cache is saved and restored
|
||||
* with expected behavior. */
|
||||
#include <wolfssl/ssl_sess.h>
|
||||
|
||||
#if (defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA))
|
||||
static int test_rem_sess_cb_count = 0;
|
||||
|
||||
static void test_rem_sess_cb(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* sess)
|
||||
{
|
||||
(void)ctx; (void)sess;
|
||||
WOLFSSL_MSG_EX("info: test test_rem_sess_cb called: %d",
|
||||
test_rem_sess_cb_count);
|
||||
test_rem_sess_cb_count++;
|
||||
}
|
||||
#endif /* HAVE_EXT_CACHE || HAVE_EX_DATA */
|
||||
|
||||
struct sess_cache_t {
|
||||
cache_header_t hdr;
|
||||
SessionRow s_rows[SESSION_ROWS];
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
ClientRow c_rows[CLIENT_SESSION_ROWS];
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
};
|
||||
|
||||
typedef struct sess_cache_t sess_cache_t;
|
||||
|
||||
/* Set the session cache to canary values for testing.
|
||||
* Will be checked later in test_sanity_sessions(). */
|
||||
static void test_set_sessions(sess_cache_t * cache_mem)
|
||||
{
|
||||
size_t i = 0;
|
||||
size_t j = 0;
|
||||
|
||||
for (i = 0; i < SESSION_ROWS; ++i) {
|
||||
SessionRow * row = &cache_mem->s_rows[i];
|
||||
for (j = 0; j < SESSIONS_PER_ROW; ++j) {
|
||||
WOLFSSL_SESSION * s = &row->Sessions[j];
|
||||
s->timeout = 1;
|
||||
s->bornOn = 0;
|
||||
/* label sessions with something predictable */
|
||||
s->sessionIDSz = 2;
|
||||
s->sessionID[0] = (byte)i;
|
||||
s->sessionID[1] = (byte)j;
|
||||
/* set type, ticketLen, rem_sess_cb, heap, peer, etc to test
|
||||
* canary values. These should be sanitized on session restore. */
|
||||
s->type = WOLFSSL_SESSION_TYPE_UNKNOWN;
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
s->ticketLen = SESSION_TICKET_LEN + 1;
|
||||
s->ticketLenAlloc = 1;
|
||||
#endif /* HAVE_SESSION_TICKET */
|
||||
#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA)
|
||||
s->rem_sess_cb = test_rem_sess_cb;
|
||||
#endif /* HAVE_EXT_CACHE || HAVE_EX_DATA */
|
||||
s->heap = (void *)0x77;
|
||||
#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
|
||||
s->peer = (WOLFSSL_X509 *)0x77;
|
||||
#endif /* SESSION_CERTS && OPENSSL_EXTRA */
|
||||
#ifdef HAVE_EX_DATA
|
||||
XMEMSET(&s->ex_data, 0x77, sizeof(WOLFSSL_CRYPTO_EX_DATA));
|
||||
s->ownExData = 1;
|
||||
#endif /* HAVE_EX_DATA */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define field_null_or_fail(what, s, name, fld) do { \
|
||||
if ((s)->fld != NULL) { \
|
||||
WOLFSSL_MSG_EX("error: %s: s = %p, id = 0x%02x%02x, %s = %p", \
|
||||
(what), (s), (s)->sessionID[0], (s)->sessionID[1], \
|
||||
(name), (s)->fld); \
|
||||
ret = -1; \
|
||||
goto sanity_fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* sanity check the restored session cache.
|
||||
* return 0 on success
|
||||
* return -1 on error */
|
||||
static int test_sanity_sessions(const sess_cache_t * cache_mem,
|
||||
const char * what)
|
||||
{
|
||||
int ret = -1;
|
||||
size_t i = 0;
|
||||
size_t j = 0;
|
||||
(void)what; /* only used in WOLFSSL_MSG_EX */
|
||||
|
||||
/* walk sessions, check for expected values */
|
||||
for (i = 0; i < SESSION_ROWS; ++i) {
|
||||
const SessionRow * row = &cache_mem->s_rows[i];
|
||||
for (j = 0; j < SESSIONS_PER_ROW; ++j) {
|
||||
const WOLFSSL_SESSION * s = &row->Sessions[j];
|
||||
#ifdef HAVE_EX_DATA
|
||||
const WOLFSSL_CRYPTO_EX_DATA * ex_data = &s->ex_data;
|
||||
size_t k = 0;
|
||||
#endif /* HAVE_EX_DATA */
|
||||
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
if (s->ticketLenAlloc != 0 ||
|
||||
s->ticketLen > SESSION_TICKET_LEN) {
|
||||
WOLFSSL_MSG_EX("error: %s: s = %p, id = 0x%02x%02x: "
|
||||
"ticketLenAlloc = %d, ticketLen = %d\n",
|
||||
what, s,
|
||||
s->sessionID[0], s->sessionID[1],
|
||||
s->ticketLenAlloc, s->ticketLen);
|
||||
ret = -1;
|
||||
goto sanity_fail;
|
||||
}
|
||||
#endif /* HAVE_SESSION_TICKET */
|
||||
|
||||
if (s->type != WOLFSSL_SESSION_TYPE_CACHE) {
|
||||
WOLFSSL_MSG_EX("error: %s: s = %p, id = 0x%02x%02x: "
|
||||
"type not cache: 0x%02x", what, s,
|
||||
s->sessionID[0], s->sessionID[1],
|
||||
s->type);
|
||||
ret = -1;
|
||||
goto sanity_fail;
|
||||
}
|
||||
|
||||
if (s->sessionIDSz != 2) {
|
||||
WOLFSSL_MSG_EX("error: %s: s = %p: got id sz = %d"
|
||||
", expected id sz = 2", what,
|
||||
s, s->sessionIDSz);
|
||||
ret = -1;
|
||||
goto sanity_fail;
|
||||
}
|
||||
|
||||
if (s->sessionID[0] != (byte)i ||
|
||||
s->sessionID[1] != (byte)j) {
|
||||
WOLFSSL_MSG_EX("error: %s: s = %p, got id = 0x%02x%02x:"
|
||||
", expected id = 0x%02x%02x", what, s,
|
||||
s->sessionID[0], s->sessionID[1],
|
||||
(byte)i, (byte)j);
|
||||
ret = -1;
|
||||
goto sanity_fail;
|
||||
}
|
||||
|
||||
/* all the remaining fields should have been sanitized as null */
|
||||
field_null_or_fail(what, s, "heap", heap);
|
||||
#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
|
||||
field_null_or_fail(what, s, "peer", peer);
|
||||
#endif /* SESSION_CERTS && OPENSSL_EXTRA */
|
||||
#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA)
|
||||
field_null_or_fail(what, s, "rem_sess_cb", rem_sess_cb);
|
||||
#endif /* HAVE_EXT_CACHE || HAVE_EX_DATA */
|
||||
|
||||
#ifdef HAVE_EX_DATA
|
||||
/* The sane default ex_data state is:
|
||||
* - s->ownExData == 1
|
||||
* - s->ex_data* zeroed. */
|
||||
if (s->ownExData != 1) {
|
||||
WOLFSSL_MSG_EX("error: s = %p, id = 0x%02x%02x, ownExData = %d",
|
||||
s, s->sessionID[0], s->sessionID[1],
|
||||
s->ownExData);
|
||||
ret = -1;
|
||||
goto sanity_fail;
|
||||
}
|
||||
|
||||
for (k = 0; k < MAX_EX_DATA; ++k) {
|
||||
if (ex_data->ex_data[k]
|
||||
#ifdef HAVE_EX_DATA_CLEANUP_HOOKS
|
||||
|| ex_data->ex_data_cleanup_routines[k]
|
||||
#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */
|
||||
) {
|
||||
WOLFSSL_MSG_EX("error: s = %p, id = 0x%02x%02x:"
|
||||
"ex_data[%zu] not null", s,
|
||||
s->sessionID[0], s->sessionID[1], k);
|
||||
ret = -1;
|
||||
goto sanity_fail;
|
||||
}
|
||||
} /* for k */
|
||||
#endif /* HAVE_EX_DATA */
|
||||
} /* for j */
|
||||
} /* for i */
|
||||
|
||||
ret = 0;
|
||||
sanity_fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Tests mem[save, restore]_session_cache.
|
||||
*
|
||||
* returns -1 on err
|
||||
* returns 0 on success
|
||||
* */
|
||||
static int test_mem_session_cache(void)
|
||||
{
|
||||
int ret = -1;
|
||||
int mem_sz = 0;
|
||||
sess_cache_t * cache_mem = NULL;
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
ClientRow * c_rows = NULL;
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
int rst_err = 0;
|
||||
#if !defined(BIG_SESSION_CACHE) && !defined(MEDIUM_SESSION_CACHE)
|
||||
int i = 0;
|
||||
#endif /* !BIG_SESSION_CACHE && !MEDIUM_SESSION_CACHE */
|
||||
|
||||
#if (defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA))
|
||||
/* reset callback count */
|
||||
test_rem_sess_cb_count = 0;
|
||||
#endif /* HAVE_EXT_CACHE || HAVE_EX_DATA */
|
||||
|
||||
/* get session cache size, and allocate scratch copy */
|
||||
mem_sz = wolfSSL_get_session_cache_memsize();
|
||||
if (mem_sz != sizeof(sess_cache_t)) {
|
||||
WOLFSSL_MSG_EX("error: got mem_sz %d, expected %zu\n", mem_sz,
|
||||
sizeof(sess_cache_t));
|
||||
return -1;
|
||||
}
|
||||
|
||||
cache_mem = (sess_cache_t *)XMALLOC((size_t)mem_sz, NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (cache_mem == NULL) {
|
||||
WOLFSSL_MSG_EX("error: xmalloc(%zu) failed", (size_t) mem_sz);
|
||||
return -1;
|
||||
}
|
||||
|
||||
XMEMSET(cache_mem, 0, sizeof(sess_cache_t));
|
||||
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
/* allocate scratch ClientCache */
|
||||
c_rows = (ClientRow *)XMALLOC(sizeof(ClientRow) * CLIENT_SESSION_ROWS,
|
||||
NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (c_rows == NULL) {
|
||||
WOLFSSL_MSG_EX("error: xmalloc(%zu) failed",
|
||||
sizeof(ClientRow) * CLIENT_SESSION_ROWS);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
|
||||
/* save session cache to cache_mem struct */
|
||||
if (wolfSSL_memsave_session_cache(cache_mem, mem_sz) != WOLFSSL_SUCCESS) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* setup test sessions */
|
||||
test_set_sessions(cache_mem);
|
||||
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
/* copy current client cache */
|
||||
XMEMCPY(c_rows, &cache_mem->c_rows, sizeof(cache_mem->c_rows));
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
|
||||
/* restore session cache from mem */
|
||||
if (wolfSSL_memrestore_session_cache(cache_mem, mem_sz) != WOLFSSL_SUCCESS) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* wipe our session struct in memory */
|
||||
XMEMSET(cache_mem, 0, sizeof(sess_cache_t));
|
||||
|
||||
/* save session cache back to cache_mem struct */
|
||||
if (wolfSSL_memsave_session_cache(cache_mem, mem_sz) != WOLFSSL_SUCCESS) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* sanity check values */
|
||||
ret = test_sanity_sessions(cache_mem, "mem");
|
||||
if (ret) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
/* verify we got back the exact client cache */
|
||||
ret = XMEMCMP(c_rows, &cache_mem->c_rows, sizeof(cache_mem->c_rows));
|
||||
if (ret) {
|
||||
WOLFSSL_MSG_EX("error: mem restore c_rows diff: %d", ret);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
|
||||
/* eviction: flush sessions older than time 2 (0 + 1 < 2). */
|
||||
wolfSSL_CTX_flush_sessions(NULL, 2);
|
||||
|
||||
#if (defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA))
|
||||
/* if all else succeeded, finally check the callback count. it should not
|
||||
* fire for sessions restored from persistent storage. */
|
||||
if (test_rem_sess_cb_count != 0) {
|
||||
ret = -1;
|
||||
}
|
||||
#endif /* HAVE_EXT_CACHE || HAVE_EX_DATA */
|
||||
|
||||
/* verify that invalid cache gives CACHE_MATCH_ERROR */
|
||||
cache_mem->hdr.version = WOLFSSL_CACHE_VERSION - 1;
|
||||
rst_err = wolfSSL_memrestore_session_cache(cache_mem, mem_sz);
|
||||
if (rst_err != WC_NO_ERR_TRACE(CACHE_MATCH_ERROR)) {
|
||||
WOLFSSL_MSG_EX("error: memrestore: hdr.version: got %d, expected %d",
|
||||
rst_err, CACHE_MATCH_ERROR);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cache_mem->hdr.version = WOLFSSL_CACHE_VERSION;
|
||||
cache_mem->hdr.rows = SESSION_ROWS - 1;
|
||||
rst_err = wolfSSL_memrestore_session_cache(cache_mem, mem_sz);
|
||||
if (rst_err != WC_NO_ERR_TRACE(CACHE_MATCH_ERROR)) {
|
||||
WOLFSSL_MSG_EX("error: memrestore: hdr.rows: got %d, expected %d",
|
||||
rst_err, CACHE_MATCH_ERROR);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cache_mem->hdr.rows = SESSION_ROWS;
|
||||
cache_mem->hdr.columns = SESSIONS_PER_ROW - 1;
|
||||
rst_err = wolfSSL_memrestore_session_cache(cache_mem, mem_sz);
|
||||
if (rst_err != WC_NO_ERR_TRACE(CACHE_MATCH_ERROR)) {
|
||||
WOLFSSL_MSG_EX("error: memrestore: hdr.columns: got %d, expected %d",
|
||||
rst_err, CACHE_MATCH_ERROR);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cache_mem->hdr.columns = SESSIONS_PER_ROW;
|
||||
cache_mem->hdr.sessionSz = (int)(sizeof(WOLFSSL_SESSION) - 1);
|
||||
rst_err = wolfSSL_memrestore_session_cache(cache_mem, mem_sz);
|
||||
if (rst_err != WC_NO_ERR_TRACE(CACHE_MATCH_ERROR)) {
|
||||
WOLFSSL_MSG_EX("error: memrestore: hdr.sessionSz: got %d, expected %d",
|
||||
rst_err, CACHE_MATCH_ERROR);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cache_mem->hdr.sessionSz = (int)(sizeof(WOLFSSL_SESSION));
|
||||
|
||||
#if !defined(BIG_SESSION_CACHE) && !defined(MEDIUM_SESSION_CACHE)
|
||||
/* test rejection of invalid session row */
|
||||
for (i = 0; i < SESSION_ROWS; ++i) {
|
||||
/* nextIdx is [0, SESSIONS_PER_ROW - 1] */
|
||||
int nextIdx = cache_mem->s_rows[i].nextIdx;
|
||||
cache_mem->s_rows[i].nextIdx = -1;
|
||||
|
||||
rst_err = wolfSSL_memrestore_session_cache(cache_mem, mem_sz);
|
||||
if (rst_err != WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
|
||||
WOLFSSL_MSG_EX("error: restore: nextIdx: got %d, expected %d",
|
||||
rst_err, WOLFSSL_FAILURE);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cache_mem->s_rows[i].nextIdx = SESSIONS_PER_ROW;
|
||||
|
||||
rst_err = wolfSSL_memrestore_session_cache(cache_mem, mem_sz);
|
||||
if (rst_err != WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
|
||||
WOLFSSL_MSG_EX("error: restore: nextIdx: got %d, expected %d",
|
||||
rst_err, WOLFSSL_FAILURE);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* restore original value */
|
||||
cache_mem->s_rows[i].nextIdx = nextIdx;
|
||||
|
||||
rst_err = wolfSSL_memrestore_session_cache(cache_mem, mem_sz);
|
||||
if (rst_err != WC_NO_ERR_TRACE(WOLFSSL_SUCCESS)) {
|
||||
WOLFSSL_MSG_EX("error: restore: nextIdx: got %d, expected %d",
|
||||
rst_err, WOLFSSL_SUCCESS);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < SESSION_ROWS; ++i) {
|
||||
/* totalCount is [0, SESSIONS_PER_ROW] */
|
||||
int totalCount = cache_mem->s_rows[i].totalCount;
|
||||
cache_mem->s_rows[i].totalCount = -1;
|
||||
|
||||
rst_err = wolfSSL_memrestore_session_cache(cache_mem, mem_sz);
|
||||
if (rst_err != WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
|
||||
WOLFSSL_MSG_EX("error: restore: totalCount: got %d, expected %d",
|
||||
rst_err, WOLFSSL_FAILURE);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cache_mem->s_rows[i].totalCount = SESSIONS_PER_ROW + 1;
|
||||
|
||||
rst_err = wolfSSL_memrestore_session_cache(cache_mem, mem_sz);
|
||||
if (rst_err != WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
|
||||
WOLFSSL_MSG_EX("error: restore: totalCount: got %d, expected %d",
|
||||
rst_err, WOLFSSL_FAILURE);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* restore original value */
|
||||
cache_mem->s_rows[i].totalCount = totalCount;
|
||||
|
||||
rst_err = wolfSSL_memrestore_session_cache(cache_mem, mem_sz);
|
||||
if (rst_err != WC_NO_ERR_TRACE(WOLFSSL_SUCCESS)) {
|
||||
WOLFSSL_MSG_EX("error: restore: totalCount: got %d, expected %d",
|
||||
rst_err, WOLFSSL_SUCCESS);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
#endif /* !BIG_SESSION_CACHE && !MEDIUM_SESSION_CACHE */
|
||||
|
||||
cleanup:
|
||||
if (cache_mem != NULL) {
|
||||
XFREE(cache_mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
cache_mem = NULL;
|
||||
}
|
||||
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
if (c_rows != NULL) {
|
||||
XFREE(c_rows, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
c_rows = NULL;
|
||||
}
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
|
||||
/* always clean up cache after test */
|
||||
wolfSSL_CTX_flush_sessions(NULL, -1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if !defined(NO_FILESYSTEM)
|
||||
/* write cache_mem to file.
|
||||
*
|
||||
* returns 0 on success
|
||||
* returns < 0 on error */
|
||||
static int test_write_file(const char * fname,
|
||||
const sess_cache_t * cache_mem)
|
||||
{
|
||||
XFILE file = XBADFILE;
|
||||
size_t n_write = 0;
|
||||
int ret = -1;
|
||||
size_t i = 0;
|
||||
|
||||
file = XFOPEN(fname, "w+b");
|
||||
if (file == XBADFILE) {
|
||||
WOLFSSL_MSG_EX("error: open(%s, w+b)", fname);
|
||||
goto write_file_cleanup;
|
||||
}
|
||||
|
||||
n_write = (int)XFWRITE(&cache_mem->hdr, sizeof(cache_header_t), 1, file);
|
||||
if (n_write != 1) {
|
||||
WOLFSSL_MSG_EX("error: write %s: %zu", fname, n_write);
|
||||
goto write_file_cleanup;
|
||||
}
|
||||
|
||||
/* we need to write SIZEOF_SESSION_ROW, one row at a time, so the row lock
|
||||
* fields are skipped. */
|
||||
for (i = 0; i < SESSION_ROWS; ++i) {
|
||||
n_write = (int)XFWRITE(&cache_mem->s_rows[i], SIZEOF_SESSION_ROW, 1, file);
|
||||
if (n_write != 1) {
|
||||
WOLFSSL_MSG_EX("error: write %s: %zu", fname, n_write);
|
||||
goto write_file_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
n_write = (int)XFWRITE(&cache_mem->c_rows, sizeof(cache_mem->c_rows), 1, file);
|
||||
if (n_write != 1) {
|
||||
WOLFSSL_MSG_EX("error: write %s: %zu", fname, n_write);
|
||||
goto write_file_cleanup;
|
||||
}
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
|
||||
ret = 0;
|
||||
write_file_cleanup:
|
||||
if (file != XBADFILE) {
|
||||
XFCLOSE(file);
|
||||
file = XBADFILE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* read cache_mem from file.
|
||||
*
|
||||
* returns 0 on success
|
||||
* returns < 0 on error */
|
||||
static int test_read_file(const char * fname,
|
||||
sess_cache_t * cache_mem)
|
||||
{
|
||||
XFILE file = XBADFILE;
|
||||
size_t n_read = 0;
|
||||
int ret = -1;
|
||||
size_t i = 0;
|
||||
|
||||
file = XFOPEN(fname, "rb");
|
||||
if (file == XBADFILE) {
|
||||
WOLFSSL_MSG_EX("error: open(%s, rb)", fname);
|
||||
goto read_file_cleanup;
|
||||
}
|
||||
|
||||
n_read = (int)XFREAD(&cache_mem->hdr, sizeof(cache_header_t), 1, file);
|
||||
if (n_read != 1) {
|
||||
WOLFSSL_MSG_EX("error: read %s: %zu", fname, n_read);
|
||||
goto read_file_cleanup;
|
||||
}
|
||||
|
||||
/* we need to read SIZEOF_SESSION_ROW, one row at a time, so the row lock
|
||||
* fields are skipped. */
|
||||
for (i = 0; i < SESSION_ROWS; ++i) {
|
||||
n_read = (int)XFREAD(&cache_mem->s_rows[i], SIZEOF_SESSION_ROW, 1, file);
|
||||
if (n_read != 1) {
|
||||
WOLFSSL_MSG_EX("error: read %s: %zu", fname, n_read);
|
||||
goto read_file_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
n_read = (int)XFREAD(&cache_mem->c_rows, sizeof(cache_mem->c_rows), 1, file);
|
||||
if (n_read != 1) {
|
||||
WOLFSSL_MSG_EX("error: read %s: %zu", fname, n_read);
|
||||
goto read_file_cleanup;
|
||||
}
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
|
||||
ret = 0;
|
||||
|
||||
read_file_cleanup:
|
||||
if (file != XBADFILE) {
|
||||
XFCLOSE(file);
|
||||
file = XBADFILE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Tests file [save, restore]_session_cache.
|
||||
*
|
||||
* returns -1 on err
|
||||
* returns 0 on success
|
||||
* */
|
||||
static int test_file_session_cache(void)
|
||||
{
|
||||
int ret = -1;
|
||||
int mem_sz = 0;
|
||||
sess_cache_t * cache_mem = NULL;
|
||||
const char * fname = "tmp_test_session_cache.bin";
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
ClientRow * c_rows = NULL;
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
int rst_err = 0;
|
||||
#if !defined(BIG_SESSION_CACHE) && !defined(MEDIUM_SESSION_CACHE)
|
||||
int i = 0;
|
||||
#endif /* !BIG_SESSION_CACHE && !MEDIUM_SESSION_CACHE */
|
||||
|
||||
#if (defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA))
|
||||
/* reset callback count */
|
||||
test_rem_sess_cb_count = 0;
|
||||
#endif /* HAVE_EXT_CACHE || HAVE_EX_DATA */
|
||||
|
||||
/* get session cache size, and allocate scratch copy */
|
||||
mem_sz = wolfSSL_get_session_cache_memsize();
|
||||
if (mem_sz != sizeof(sess_cache_t)) {
|
||||
WOLFSSL_MSG_EX("error: got mem_sz %d, expected %zu\n", mem_sz,
|
||||
sizeof(sess_cache_t));
|
||||
return -1;
|
||||
}
|
||||
|
||||
cache_mem = (sess_cache_t *)XMALLOC((size_t)mem_sz, NULL,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (cache_mem == NULL) {
|
||||
WOLFSSL_MSG_EX("error: xmalloc(%zu) failed", (size_t) mem_sz);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
/* allocate scratch ClientCache */
|
||||
c_rows = (ClientRow *)XMALLOC(sizeof(ClientRow) * CLIENT_SESSION_ROWS,
|
||||
NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (c_rows == NULL) {
|
||||
WOLFSSL_MSG_EX("error: xmalloc(%zu) failed",
|
||||
sizeof(ClientRow) * CLIENT_SESSION_ROWS);
|
||||
goto file_cleanup;
|
||||
}
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
|
||||
/* save session cache to file fname */
|
||||
if (wolfSSL_save_session_cache(fname) != WOLFSSL_SUCCESS) {
|
||||
ret = -1;
|
||||
goto file_cleanup;
|
||||
}
|
||||
|
||||
/* read it into cache_mem struct */
|
||||
ret = test_read_file(fname, cache_mem);
|
||||
if (ret) {
|
||||
goto file_cleanup;
|
||||
}
|
||||
|
||||
/* setup test sessions */
|
||||
test_set_sessions(cache_mem);
|
||||
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
/* copy current client cache */
|
||||
XMEMCPY(c_rows, &cache_mem->c_rows, sizeof(cache_mem->c_rows));
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
|
||||
/* write test sessions back to file */
|
||||
ret = test_write_file(fname, cache_mem);
|
||||
if (ret) {
|
||||
goto file_cleanup;
|
||||
}
|
||||
|
||||
/* restore session cache from file */
|
||||
if (wolfSSL_restore_session_cache(fname) != WOLFSSL_SUCCESS) {
|
||||
ret = -1;
|
||||
goto file_cleanup;
|
||||
}
|
||||
|
||||
/* save session cache back to file fname */
|
||||
if (wolfSSL_save_session_cache(fname) != WOLFSSL_SUCCESS) {
|
||||
ret = -1;
|
||||
goto file_cleanup;
|
||||
}
|
||||
|
||||
/* wipe our session struct in memory */
|
||||
XMEMSET(cache_mem, 0, sizeof(sess_cache_t));
|
||||
|
||||
/* read it into cache_mem struct */
|
||||
ret = test_read_file(fname, cache_mem);
|
||||
if (ret) {
|
||||
goto file_cleanup;
|
||||
}
|
||||
|
||||
/* sanity check values */
|
||||
ret = test_sanity_sessions(cache_mem, "file");
|
||||
if (ret) {
|
||||
goto file_cleanup;
|
||||
}
|
||||
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
/* verify we got back the exact client cache */
|
||||
ret = XMEMCMP(c_rows, &cache_mem->c_rows, sizeof(cache_mem->c_rows));
|
||||
if (ret) {
|
||||
WOLFSSL_MSG_EX("error: file restore c_rows diff: %d", ret);
|
||||
ret = -1;
|
||||
goto file_cleanup;
|
||||
}
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
|
||||
/* eviction: flush sessions older than time 2 (0 + 1 < 2). */
|
||||
wolfSSL_CTX_flush_sessions(NULL, 2);
|
||||
|
||||
/* verify that invalid cache gives CACHE_MATCH_ERROR */
|
||||
cache_mem->hdr.version = WOLFSSL_CACHE_VERSION - 1;
|
||||
ret = test_write_file(fname, cache_mem);
|
||||
if (ret) { goto file_cleanup; }
|
||||
rst_err = wolfSSL_restore_session_cache(fname);
|
||||
if (rst_err != WC_NO_ERR_TRACE(CACHE_MATCH_ERROR)) {
|
||||
WOLFSSL_MSG_EX("error: restore: hdr.version: got %d, expected %d",
|
||||
rst_err, CACHE_MATCH_ERROR);
|
||||
ret = -1;
|
||||
goto file_cleanup;
|
||||
}
|
||||
|
||||
cache_mem->hdr.version = WOLFSSL_CACHE_VERSION;
|
||||
cache_mem->hdr.rows = SESSION_ROWS - 1;
|
||||
ret = test_write_file(fname, cache_mem);
|
||||
if (ret) { goto file_cleanup; }
|
||||
rst_err = wolfSSL_restore_session_cache(fname);
|
||||
if (rst_err != WC_NO_ERR_TRACE(CACHE_MATCH_ERROR)) {
|
||||
WOLFSSL_MSG_EX("error: restore: hdr.rows: got %d, expected %d",
|
||||
rst_err, CACHE_MATCH_ERROR);
|
||||
ret = -1;
|
||||
goto file_cleanup;
|
||||
}
|
||||
|
||||
cache_mem->hdr.rows = SESSION_ROWS;
|
||||
cache_mem->hdr.columns = SESSIONS_PER_ROW - 1;
|
||||
ret = test_write_file(fname, cache_mem);
|
||||
if (ret) { goto file_cleanup; }
|
||||
rst_err = wolfSSL_restore_session_cache(fname);
|
||||
if (rst_err != WC_NO_ERR_TRACE(CACHE_MATCH_ERROR)) {
|
||||
WOLFSSL_MSG_EX("error: restore: hdr.columns: got %d, expected %d",
|
||||
rst_err, CACHE_MATCH_ERROR);
|
||||
ret = -1;
|
||||
goto file_cleanup;
|
||||
}
|
||||
|
||||
cache_mem->hdr.columns = SESSIONS_PER_ROW;
|
||||
cache_mem->hdr.sessionSz = (int)(sizeof(WOLFSSL_SESSION) - 1);
|
||||
ret = test_write_file(fname, cache_mem);
|
||||
if (ret) { goto file_cleanup; }
|
||||
rst_err = wolfSSL_restore_session_cache(fname);
|
||||
if (rst_err != WC_NO_ERR_TRACE(CACHE_MATCH_ERROR)) {
|
||||
WOLFSSL_MSG_EX("error: restore: hdr.sessionSz: got %d, expected %d",
|
||||
rst_err, CACHE_MATCH_ERROR);
|
||||
ret = -1;
|
||||
goto file_cleanup;
|
||||
}
|
||||
|
||||
cache_mem->hdr.sessionSz = (int)(sizeof(WOLFSSL_SESSION));
|
||||
|
||||
#if !defined(BIG_SESSION_CACHE) && !defined(MEDIUM_SESSION_CACHE)
|
||||
/* test rejection of invalid session row */
|
||||
for (i = 0; i < SESSION_ROWS; ++i) {
|
||||
/* nextIdx is [0, SESSIONS_PER_ROW - 1] */
|
||||
int nextIdx = cache_mem->s_rows[i].nextIdx;
|
||||
cache_mem->s_rows[i].nextIdx = -1;
|
||||
|
||||
ret = test_write_file(fname, cache_mem);
|
||||
if (ret) { goto file_cleanup; }
|
||||
rst_err = wolfSSL_restore_session_cache(fname);
|
||||
if (rst_err != WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
|
||||
WOLFSSL_MSG_EX("error: restore: nextIdx: got %d, expected %d",
|
||||
rst_err, WOLFSSL_FAILURE);
|
||||
ret = -1;
|
||||
goto file_cleanup;
|
||||
}
|
||||
|
||||
cache_mem->s_rows[i].nextIdx = SESSIONS_PER_ROW;
|
||||
|
||||
ret = test_write_file(fname, cache_mem);
|
||||
if (ret) { goto file_cleanup; }
|
||||
rst_err = wolfSSL_restore_session_cache(fname);
|
||||
if (rst_err != WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
|
||||
WOLFSSL_MSG_EX("error: restore: nextIdx: got %d, expected %d",
|
||||
rst_err, WOLFSSL_FAILURE);
|
||||
ret = -1;
|
||||
goto file_cleanup;
|
||||
}
|
||||
|
||||
/* restore original value */
|
||||
cache_mem->s_rows[i].nextIdx = nextIdx;
|
||||
ret = test_write_file(fname, cache_mem);
|
||||
if (ret) { goto file_cleanup; }
|
||||
|
||||
rst_err = wolfSSL_restore_session_cache(fname);
|
||||
if (rst_err != WC_NO_ERR_TRACE(WOLFSSL_SUCCESS)) {
|
||||
WOLFSSL_MSG_EX("error: restore: nextIdx: got %d, expected %d",
|
||||
rst_err, WOLFSSL_SUCCESS);
|
||||
ret = -1;
|
||||
goto file_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < SESSION_ROWS; ++i) {
|
||||
int totalCount = cache_mem->s_rows[i].totalCount;
|
||||
/* totalCount is [0, SESSIONS_PER_ROW] */
|
||||
cache_mem->s_rows[i].totalCount = -1;
|
||||
|
||||
ret = test_write_file(fname, cache_mem);
|
||||
if (ret) { goto file_cleanup; }
|
||||
rst_err = wolfSSL_restore_session_cache(fname);
|
||||
if (rst_err != WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
|
||||
WOLFSSL_MSG_EX("error: restore: totalCount: got %d, expected %d",
|
||||
rst_err, WOLFSSL_FAILURE);
|
||||
ret = -1;
|
||||
goto file_cleanup;
|
||||
}
|
||||
|
||||
cache_mem->s_rows[i].totalCount = SESSIONS_PER_ROW + 1;
|
||||
|
||||
ret = test_write_file(fname, cache_mem);
|
||||
if (ret) { goto file_cleanup; }
|
||||
rst_err = wolfSSL_restore_session_cache(fname);
|
||||
if (rst_err != WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
|
||||
WOLFSSL_MSG_EX("error: restore: totalCount: got %d, expected %d",
|
||||
rst_err, WOLFSSL_FAILURE);
|
||||
ret = -1;
|
||||
goto file_cleanup;
|
||||
}
|
||||
|
||||
/* restore original value */
|
||||
cache_mem->s_rows[i].totalCount = totalCount;
|
||||
ret = test_write_file(fname, cache_mem);
|
||||
if (ret) { goto file_cleanup; }
|
||||
|
||||
rst_err = wolfSSL_restore_session_cache(fname);
|
||||
if (rst_err != WC_NO_ERR_TRACE(WOLFSSL_SUCCESS)) {
|
||||
WOLFSSL_MSG_EX("error: restore: totalCount: got %d, expected %d",
|
||||
rst_err, WOLFSSL_SUCCESS);
|
||||
ret = -1;
|
||||
goto file_cleanup;
|
||||
}
|
||||
}
|
||||
#endif /* !BIG_SESSION_CACHE && !MEDIUM_SESSION_CACHE */
|
||||
|
||||
file_cleanup:
|
||||
/* remove session cache file. the file existing and being removed
|
||||
* is part of the expected result. */
|
||||
{
|
||||
int rc = remove(fname);
|
||||
if (rc) {
|
||||
fprintf(stderr, "remove(%s) failed: %d\n", fname, rc);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
#if (defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA))
|
||||
/* if all else succeeded, finally check the callback count. it should not
|
||||
* fire for sessions restored from persistent storage. */
|
||||
if (test_rem_sess_cb_count != 0) {
|
||||
ret = -1;
|
||||
}
|
||||
#endif /* HAVE_EXT_CACHE || HAVE_EX_DATA */
|
||||
|
||||
if (cache_mem != NULL) {
|
||||
XFREE(cache_mem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
cache_mem = NULL;
|
||||
}
|
||||
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
if (c_rows != NULL) {
|
||||
XFREE(c_rows, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
c_rows = NULL;
|
||||
}
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
|
||||
/* always clean up cache after test */
|
||||
wolfSSL_CTX_flush_sessions(NULL, -1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* !NO_FILESYSTEM */
|
||||
|
||||
int test_wolfSSL_session_cache_restore(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
ExpectIntEQ(test_mem_session_cache(), 0);
|
||||
#if !defined(NO_FILESYSTEM)
|
||||
ExpectIntEQ(test_file_session_cache(), 0);
|
||||
#endif /* NO_FILESYSTEM */
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
#else
|
||||
int test_wolfSSL_session_cache_restore(void)
|
||||
{
|
||||
return TEST_SKIPPED;
|
||||
}
|
||||
#endif /* PERSIST_SESSION_CACHE && !NO_SESSION_CACHE &&
|
||||
* !SESSION_CACHE_DYNAMIC_MEM && !TITAN_SESSION_CACHE &&
|
||||
* !HUGE_SESSION_CACHE */
|
||||
|
||||
@@ -39,6 +39,7 @@ int test_wolfSSL_SESSION_get_ex_new_index(void);
|
||||
int test_wolfSSL_GetSessionAtIndex(void);
|
||||
int test_wolfSSL_client_cache_id_prefix(void);
|
||||
int test_wolfSSL_client_cache_id_overwrite(void);
|
||||
int test_wolfSSL_session_cache_restore(void);
|
||||
|
||||
#define TEST_SESSION_DECLS \
|
||||
TEST_DECL_GROUP("session", test_wolfSSL_CTX_add_session), \
|
||||
@@ -55,6 +56,7 @@ int test_wolfSSL_client_cache_id_overwrite(void);
|
||||
TEST_DECL_GROUP("session", test_wolfSSL_SESSION_get_ex_new_index), \
|
||||
TEST_DECL_GROUP("session", test_wolfSSL_GetSessionAtIndex), \
|
||||
TEST_DECL_GROUP("session", test_wolfSSL_client_cache_id_prefix), \
|
||||
TEST_DECL_GROUP("session", test_wolfSSL_client_cache_id_overwrite)
|
||||
TEST_DECL_GROUP("session", test_wolfSSL_client_cache_id_overwrite), \
|
||||
TEST_DECL_GROUP("session", test_wolfSSL_session_cache_restore)
|
||||
|
||||
#endif /* WOLFCRYPT_TEST_SESSION_H */
|
||||
|
||||
@@ -27,7 +27,8 @@ nobase_include_HEADERS+= \
|
||||
wolfssl/wolfio.h
|
||||
|
||||
noinst_HEADERS+= \
|
||||
wolfssl/internal.h
|
||||
wolfssl/internal.h \
|
||||
wolfssl/ssl_sess.h
|
||||
|
||||
# For distro build don't install options.h.
|
||||
# It depends on the architecture and conflicts with Multi-Arch.
|
||||
|
||||
@@ -5057,7 +5057,7 @@ typedef struct TicketNonce {
|
||||
byte data[MAX_TICKET_NONCE_STATIC_SZ];
|
||||
#endif /* WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3) */
|
||||
} TicketNonce;
|
||||
#endif
|
||||
#endif /* WOLFSSL_TLS13 && (HAVE_SESSION_TICKET || !NO_PSK) */
|
||||
|
||||
/* wolfSSL session type */
|
||||
struct WOLFSSL_SESSION {
|
||||
@@ -5067,16 +5067,16 @@ struct WOLFSSL_SESSION {
|
||||
#ifndef NO_SESSION_CACHE
|
||||
int cacheRow; /* row in session cache */
|
||||
word32 cacheGen; /* writes into this entry */
|
||||
#endif
|
||||
#endif /* !NO_SESSION_CACHE */
|
||||
wolfSSL_Ref ref;
|
||||
byte altSessionID[ID_LEN];
|
||||
byte haveAltSessionID:1;
|
||||
#ifdef HAVE_EX_DATA
|
||||
byte ownExData:1;
|
||||
#endif
|
||||
#endif /* HAVE_EX_DATA */
|
||||
#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA)
|
||||
Rem_Sess_Cb rem_sess_cb;
|
||||
#endif
|
||||
#endif /* HAVE_EXT_CACHE || HAVE_EX_DATA */
|
||||
void* heap;
|
||||
/* WARNING The above fields (up to and including the heap) are not copied
|
||||
* in wolfSSL_DupSession. Place new fields after the heap
|
||||
@@ -5096,41 +5096,41 @@ struct WOLFSSL_SESSION {
|
||||
word16 haveEMS; /* ext master secret flag */
|
||||
#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
|
||||
WOLFSSL_X509* peer; /* peer cert */
|
||||
#endif
|
||||
#endif /* SESSION_CERTS && OPENSSL_EXTRA */
|
||||
ProtocolVersion version; /* which version was used */
|
||||
#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 */
|
||||
#endif
|
||||
#endif /* SESSION_CERTS || !NO_RESUME_SUITE_CHECK || ... */
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
word16 idLen; /* serverID length */
|
||||
byte serverID[SERVER_ID_LEN]; /* for easier client lookup */
|
||||
#endif
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
#ifdef WOLFSSL_SESSION_ID_CTX
|
||||
byte sessionCtxSz; /* sessionCtx length */
|
||||
byte sessionCtx[ID_LEN]; /* app specific context id */
|
||||
#endif /* WOLFSSL_SESSION_ID_CTX */
|
||||
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
|
||||
byte peerVerifyRet; /* cert verify error */
|
||||
#endif
|
||||
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
|
||||
#ifdef WOLFSSL_TLS13
|
||||
word16 namedGroup;
|
||||
#endif
|
||||
#endif /* WOLFSSL_TLS13 */
|
||||
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
|
||||
#ifdef WOLFSSL_TLS13
|
||||
#ifdef WOLFSSL_32BIT_MILLI_TIME
|
||||
#ifdef WOLFSSL_TLS13
|
||||
#ifdef WOLFSSL_32BIT_MILLI_TIME
|
||||
word32 ticketSeen; /* Time ticket seen (ms) */
|
||||
#else
|
||||
#else
|
||||
sword64 ticketSeen; /* Time ticket seen (ms) */
|
||||
#endif
|
||||
#endif /* WOLFSSL_32BIT_MILLI_TIME */
|
||||
word32 ticketAdd; /* Added by client */
|
||||
TicketNonce ticketNonce; /* Nonce used to derive PSK */
|
||||
#endif
|
||||
#ifdef WOLFSSL_EARLY_DATA
|
||||
#endif /* WOLFSSL_TLS13 */
|
||||
#ifdef WOLFSSL_EARLY_DATA
|
||||
word32 maxEarlyDataSz;
|
||||
#endif
|
||||
#endif
|
||||
#endif /* WOLFSSL_EARLY_DATA */
|
||||
#endif /* HAVE_SESSION_TICKET || !NO_PSK */
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
byte staticTicket[SESSION_TICKET_LEN];
|
||||
byte* ticket;
|
||||
@@ -5138,25 +5138,25 @@ struct WOLFSSL_SESSION {
|
||||
word16 ticketLenAlloc; /* is dynamic */
|
||||
#ifdef HAVE_SNI
|
||||
byte sniHash[TICKET_BINDING_HASH_SZ]; /* SNI at issue */
|
||||
#endif
|
||||
#ifdef HAVE_ALPN
|
||||
#endif /* HAVE_SNI */
|
||||
#ifdef HAVE_ALPN
|
||||
byte alpnHash[TICKET_BINDING_HASH_SZ]; /* ALPN at issue */
|
||||
#endif
|
||||
#endif
|
||||
#endif /* HAVE_ALPN */
|
||||
#endif /* HAVE_SESSION_TICKET */
|
||||
|
||||
#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 /* WOLFSSL_ALT_CERT_CHAINS */
|
||||
#endif
|
||||
#ifdef HAVE_EX_DATA
|
||||
WOLFSSL_CRYPTO_EX_DATA ex_data;
|
||||
#endif
|
||||
#endif /* HAVE_EX_DATA */
|
||||
#ifdef HAVE_MAX_FRAGMENT
|
||||
byte mfl; /* max fragment length negotiated i.e.
|
||||
* WOLFSSL_MFL_2_8 (6) */
|
||||
#endif
|
||||
#endif /* HAVE_MAX_FRAGMENT */
|
||||
byte isSetup:1;
|
||||
};
|
||||
|
||||
|
||||
193
wolfssl/ssl_sess.h
Normal file
193
wolfssl/ssl_sess.h
Normal file
@@ -0,0 +1,193 @@
|
||||
/* ssl_sess.h
|
||||
*
|
||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
#ifndef WOLFSSL_SSL_SESS_H
|
||||
#define WOLFSSL_SSL_SESS_H
|
||||
|
||||
#ifndef NO_SESSION_CACHE
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* basic config gives a cache with 33 sessions, adequate for clients and
|
||||
embedded servers
|
||||
|
||||
TITAN_SESSION_CACHE allows just over 2 million sessions, for servers
|
||||
with titanic amounts of memory with long session ID timeouts and high
|
||||
levels of traffic.
|
||||
|
||||
ENABLE_SESSION_CACHE_ROW_LOCK: Allows row level locking for increased
|
||||
performance with large session caches
|
||||
|
||||
HUGE_SESSION_CACHE yields 65,791 sessions, for servers under heavy load,
|
||||
allows over 13,000 new sessions per minute or over 200 new sessions per
|
||||
second
|
||||
|
||||
BIG_SESSION_CACHE yields 20,027 sessions
|
||||
|
||||
MEDIUM_SESSION_CACHE allows 1055 sessions, adequate for servers that
|
||||
aren't under heavy load, basically allows 200 new sessions per minute
|
||||
|
||||
SMALL_SESSION_CACHE only stores 6 sessions, good for embedded clients
|
||||
or systems where the default is too much RAM.
|
||||
SessionCache takes about 2K, ClientCache takes about 3Kbytes
|
||||
|
||||
MICRO_SESSION_CACHE only stores 1 session, good for embedded clients
|
||||
or systems where memory is at a premium.
|
||||
SessionCache takes about 400 bytes, ClientCache takes 576 bytes
|
||||
|
||||
default SESSION_CACHE stores 33 sessions (no XXX_SESSION_CACHE defined)
|
||||
SessionCache takes about 13K bytes, ClientCache takes 17K bytes
|
||||
*/
|
||||
#if defined(TITAN_SESSION_CACHE)
|
||||
#define SESSIONS_PER_ROW 31
|
||||
#define SESSION_ROWS 64937
|
||||
#ifndef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
#define ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
#endif
|
||||
#elif defined(HUGE_SESSION_CACHE)
|
||||
#define SESSIONS_PER_ROW 11
|
||||
#define SESSION_ROWS 5981
|
||||
#elif defined(BIG_SESSION_CACHE)
|
||||
#define SESSIONS_PER_ROW 7
|
||||
#define SESSION_ROWS 2861
|
||||
#elif defined(MEDIUM_SESSION_CACHE)
|
||||
#define SESSIONS_PER_ROW 5
|
||||
#define SESSION_ROWS 211
|
||||
#elif defined(SMALL_SESSION_CACHE)
|
||||
#define SESSIONS_PER_ROW 2
|
||||
#define SESSION_ROWS 3
|
||||
#elif defined(MICRO_SESSION_CACHE)
|
||||
#define SESSIONS_PER_ROW 1
|
||||
#define SESSION_ROWS 1
|
||||
#else
|
||||
#define SESSIONS_PER_ROW 3
|
||||
#define SESSION_ROWS 11
|
||||
#endif
|
||||
|
||||
#define INVALID_SESSION_ROW (-1)
|
||||
|
||||
#ifdef NO_SESSION_CACHE_ROW_LOCK
|
||||
#undef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
#endif
|
||||
|
||||
typedef struct SessionRow {
|
||||
int nextIdx; /* where to place next one */
|
||||
int totalCount; /* sessions ever on this row */
|
||||
word32 cacheGen; /* next entry generation */
|
||||
#ifdef SESSION_CACHE_DYNAMIC_MEM
|
||||
WOLFSSL_SESSION* Sessions[SESSIONS_PER_ROW];
|
||||
void* heap;
|
||||
#else
|
||||
WOLFSSL_SESSION Sessions[SESSIONS_PER_ROW];
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
/* not included in import/export */
|
||||
wolfSSL_RwLock row_lock;
|
||||
int lock_valid;
|
||||
#endif
|
||||
} SessionRow;
|
||||
|
||||
#if defined(PERSIST_SESSION_CACHE) && !defined(SESSION_CACHE_DYNAMIC_MEM)
|
||||
/* when writing / restoring from storage, do not read the full struct,
|
||||
* as this would clobber active row locks. */
|
||||
#ifdef ENABLE_SESSION_CACHE_ROW_LOCK
|
||||
#define SIZEOF_SESSION_ROW WC_OFFSETOF(SessionRow, row_lock)
|
||||
#else
|
||||
#define SIZEOF_SESSION_ROW (sizeof(SessionRow))
|
||||
#endif /* ENABLE_SESSION_CACHE_ROW_LOCK */
|
||||
#endif /* PERSIST_SESSION_CACHE && !SESSION_CACHE_DYNAMIC_MEM */
|
||||
|
||||
#ifndef NO_CLIENT_CACHE
|
||||
#ifndef CLIENT_SESSIONS_MULTIPLIER
|
||||
#ifdef NO_SESSION_CACHE_REF
|
||||
#define CLIENT_SESSIONS_MULTIPLIER 1
|
||||
#else
|
||||
/* ClientSession objects are lightweight (compared to
|
||||
* WOLFSSL_SESSION) so to decrease chance that user will reuse
|
||||
* the wrong session, increase the ClientCache size. This will
|
||||
* make the entire ClientCache about the size of one
|
||||
* WOLFSSL_SESSION object. */
|
||||
#define CLIENT_SESSIONS_MULTIPLIER 8
|
||||
#endif
|
||||
#endif
|
||||
#define CLIENT_SESSIONS_PER_ROW \
|
||||
(SESSIONS_PER_ROW * CLIENT_SESSIONS_MULTIPLIER)
|
||||
#define CLIENT_SESSION_ROWS (SESSION_ROWS * CLIENT_SESSIONS_MULTIPLIER)
|
||||
|
||||
#if CLIENT_SESSIONS_PER_ROW > 65535
|
||||
#error CLIENT_SESSIONS_PER_ROW too big
|
||||
#endif
|
||||
#if CLIENT_SESSION_ROWS > 65535
|
||||
#error CLIENT_SESSION_ROWS too big
|
||||
#endif
|
||||
|
||||
struct ClientSession {
|
||||
word16 serverRow; /* SessionCache Row id */
|
||||
word16 serverIdx; /* SessionCache Idx (column) */
|
||||
word32 sessionIDHash;
|
||||
word32 cacheGen; /* SessionCache entry generation */
|
||||
};
|
||||
#ifndef WOLFSSL_CLIENT_SESSION_DEFINED
|
||||
typedef struct ClientSession ClientSession;
|
||||
#define WOLFSSL_CLIENT_SESSION_DEFINED
|
||||
#endif
|
||||
|
||||
typedef struct ClientRow {
|
||||
int nextIdx; /* where to place next one */
|
||||
int totalCount; /* sessions ever on this row */
|
||||
ClientSession Clients[CLIENT_SESSIONS_PER_ROW];
|
||||
} ClientRow;
|
||||
#endif /* !NO_CLIENT_CACHE */
|
||||
|
||||
#if defined(PERSIST_SESSION_CACHE) && !defined(SESSION_CACHE_DYNAMIC_MEM)
|
||||
/* for persistence, if changes to layout need to increment and modify
|
||||
save_session_cache() and restore_session_cache and memory versions too */
|
||||
#define WOLFSSL_CACHE_VERSION 3
|
||||
|
||||
/* Session Cache Header information */
|
||||
typedef struct {
|
||||
int version; /* cache layout version id */
|
||||
int rows; /* session rows */
|
||||
int columns; /* session columns */
|
||||
int sessionSz; /* sizeof WOLFSSL_SESSION */
|
||||
} cache_header_t;
|
||||
|
||||
/* current persistence layout is:
|
||||
|
||||
1) cache_header_t
|
||||
2) SessionCache
|
||||
3) ClientCache
|
||||
|
||||
update WOLFSSL_CACHE_VERSION if change layout for the following
|
||||
PERSISTENT_SESSION_CACHE functions
|
||||
*/
|
||||
#endif /* PERSIST_SESSION_CACHE && !SESSION_CACHE_DYNAMIC_MEM */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* !NO_SESSION_CACHE */
|
||||
|
||||
#endif /* WOLFSSL_SSL_SESS_H */
|
||||
Reference in New Issue
Block a user