Initial support for deep copying of session

This commit is contained in:
Nickolas Lapp
2016-04-08 11:14:00 -06:00
parent f27aca0956
commit 5f9c1ffca6
7 changed files with 149 additions and 48 deletions

View File

@ -2652,6 +2652,7 @@ void SSL_ResourceFree(WOLFSSL* ssl)
#if defined(KEEP_PEER_CERT) || defined(GOAHEAD_WS)
FreeX509(&ssl->peerCert);
#endif
#ifdef HAVE_SESSION_TICKET
if (ssl->session.isDynamic) {
XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
@ -2797,6 +2798,7 @@ void FreeHandshakeResources(WOLFSSL* ssl)
#ifdef HAVE_QSH
QSH_FreeAll(ssl);
#endif
#ifdef HAVE_SESSION_TICKET
if (ssl->session.isDynamic) {
XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
@ -15966,7 +15968,7 @@ int DoSessionTicket(WOLFSSL* ssl,
if (ssl->options.resuming) { /* let's try */
int ret = -1;
WOLFSSL_SESSION* session = GetSession(ssl,
ssl->arrays->masterSecret);
ssl->arrays->masterSecret, 1);
#ifdef HAVE_SESSION_TICKET
if (ssl->options.useTicket == 1) {
session = &ssl->session;
@ -15981,9 +15983,6 @@ int DoSessionTicket(WOLFSSL* ssl,
WOLFSSL_MSG("Unsupported cipher suite, OldClientHello");
return UNSUPPORTED_SUITE;
}
#ifdef SESSION_CERTS
ssl->session = *session; /* restore session certs. */
#endif
ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom,
RAN_LEN);
@ -16361,7 +16360,7 @@ int DoSessionTicket(WOLFSSL* ssl,
if (ssl->options.resuming) {
int ret = -1;
WOLFSSL_SESSION* session = GetSession(ssl,
ssl->arrays->masterSecret);
ssl->arrays->masterSecret, 1);
#ifdef HAVE_SESSION_TICKET
if (ssl->options.useTicket == 1) {
session = &ssl->session;
@ -16377,9 +16376,6 @@ int DoSessionTicket(WOLFSSL* ssl,
WOLFSSL_MSG("Unsupported cipher suite, ClientHello");
return UNSUPPORTED_SUITE;
}
#ifdef SESSION_CERTS
ssl->session = *session; /* restore session certs. */
#endif
ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom,
RAN_LEN);

View File

@ -1560,7 +1560,7 @@ static int ProcessServerHello(const byte* input, int* sslBytes,
if (doResume ) {
int ret = 0;
SSL_SESSION* resume = GetSession(session->sslServer,
session->sslServer->arrays->masterSecret);
session->sslServer->arrays->masterSecret, 0);
if (resume == NULL) {
SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
return -1;
@ -1825,7 +1825,7 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes,
if (ret == 0 && session->flags.cached == 0) {
if (session->sslServer->options.haveSessionId) {
WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL);
WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0);
if (sess == NULL)
AddSession(session->sslServer); /* don't re add */
session->flags.cached = 1;

149
src/ssl.c
View File

@ -1265,29 +1265,34 @@ WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, byte* buf, word32 bufSz)
if (ssl == NULL || (buf == NULL && bufSz > 0))
return BAD_FUNC_ARG;
/* 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;
}
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;
ssl->session.ticketLen = (word16)bufSz;
XMEMCPY(ssl->session.ticket, buf, bufSz);
} else { /* Ticket requires dynamic ticket storage */
/*Not big enough space, need to alloc */
if (!(ssl->session.ticketLen >= bufSz)) {
if(ssl->session.isDynamic)
XFREE(ssl->session.ticket);
ssl->session.ticket = XMALLOC(bufSz, ssl->heap, DYNAMIC_TYPE_TICK);
if(!ssl->session.ticket)
return MEMORY_ERROR;
ssl->session.isDynamic = 1;
ssl->session.ticket = ssl->session.staticTicket;
ssl->session.ticketLen = (word16)bufSz;
XMEMCPY(ssl->session.ticket, buf, bufSz);
} else { /* Ticket requires dynamic ticket storage */
/*Not big enough space, need to alloc */
if (!(ssl->session.ticketLen >= bufSz)) {
if(ssl->session.isDynamic)
XFREE(ssl->session.ticket, ssl->heap,
DYNAMIC_TYPE_SESSION_TICK);
ssl->session.ticket = XMALLOC(bufSz, ssl->heap,
DYNAMIC_TYPE_SESSION_TICK);
if(!ssl->session.ticket)
return MEMORY_ERROR;
ssl->session.isDynamic = 1;
}
XMEMCPY(ssl->session.ticket, buf, bufSz);
}
XMEMCPY(ssl->session.ticket, buf, bufSz);
ssl->session.ticketLen = bufSz;
}
ssl->session.ticketLen = (word16)bufSz;
return SSL_SUCCESS;
}
@ -5201,7 +5206,7 @@ WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl)
{
WOLFSSL_ENTER("SSL_get_session");
if (ssl)
return GetSession(ssl, 0);
return GetSession(ssl, 0, 0);
return NULL;
}
@ -6949,7 +6954,8 @@ WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len)
#endif /* NO_CLIENT_CACHE */
WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret)
WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret,
byte restoreSessionCerts)
{
WOLFSSL_SESSION* ret = 0;
const byte* id = NULL;
@ -6958,6 +6964,8 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret)
int count;
int error = 0;
(void) restoreSessionCerts;
if (ssl->options.sessionCacheOff)
return NULL;
@ -7005,6 +7013,17 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret)
ret = current;
if (masterSecret)
XMEMCPY(masterSecret, current->masterSecret, SECRET_LEN);
#ifdef SESSION_CERTS
/* If set, we should copy the session certs from the ssl object
* to the session we are returning so we can resume */
if (restoreSessionCerts) {
ret->chain = ssl->session.chain;
ret->version = ssl->session.version;
ret->cipherSuite0 = ssl->session.cipherSuite0;
ret->cipherSuite = ssl->session.cipherSuite;
}
#endif /* SESSION_CERTS */
} else {
WOLFSSL_MSG("Session timed out");
}
@ -7020,13 +7039,92 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret)
}
int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom)
{
int ticketLen;
int doDynamicCopy;
WOLFSSL_SESSION* copyInto = &ssl->session;
void* tmpBuff = NULL;
int ret = SSL_SUCCESS;
(void)ticketLen;
(void)doDynamicCopy;
(void)tmpBuff;
if (!ssl || !copyFrom)
return BAD_FUNC_ARG;
if (LockMutex(&session_mutex) != 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_SESS_TICK);
copyInto->ticket = copyInto->staticTicket;
copyInto->isDynamic = 0;
}
/* Size of ticket to alloc if needed; Use later for alloc outside lock */
if (copyFrom) {
doDynamicCopy = 1;
ticketLen = copyFrom->ticketLen;
}
#endif
*copyInto = *copyFrom;
if (UnLockMutex(&session_mutex) != 0) {
return BAD_MUTEX_E;
}
#ifdef HAVE_SESSION_TICKET
/* If doing dynamic copy, need to alloc outside lock, then inside a lock
* confirm the size still matches and memcpy */
if (doDynamicCopy) {
tmpBuff = XMALLOC(ticketLen, ssl->heap, DYNAMIC_TYPE_SESSION_TICK);
if (!tmpBuff)
return MEMORY_ERROR;
if (LockMutex(&session_mutex) != 0) {
XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESS_TICK);
return BAD_MUTEX_E;
}
if (ticketLen != copyFrom->ticketLen) {
/* Another thread modified the ssl-> session ticket during alloc.
* Treat as error, as ticket different than when copy requested */
ret = VAR_STATE_CHANGE_E;
}
if (ret == SSL_SUCCESS) {
copyInto->ticket = tmpBuff;
XMEMCPY(copyInto->ticket, copyFrom->ticket, ticketLen);
}
}
if (UnLockMutex(&session_mutex) != 0) {
if (ret == SSL_SUCCESS)
ret = BAD_MUTEX_E;
}
if (ret != SSL_SUCCESS) {
/* cleanup */
if (tmpBuff)
XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESS_TICK);
copyInto->ticket = copyInto->staticTicket;
copyInto->isDynamic = 0;
}
#endif /* HAVE_SESSION_TICKET */
return ret;
}
int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session)
{
if (ssl->options.sessionCacheOff)
return SSL_FAILURE;
if (LowResTimer() < (session->bornOn + session->timeout)) {
ssl->session = *session;
GetDeepCopySession(ssl, session);
ssl->options.resuming = 1;
#ifdef SESSION_CERTS
@ -7034,7 +7132,6 @@ int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session)
ssl->options.cipherSuite0 = session->cipherSuite0;
ssl->options.cipherSuite = session->cipherSuite;
#endif
return SSL_SUCCESS;
}
return SSL_FAILURE; /* session timed out */
@ -7397,10 +7494,12 @@ int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak,
#else /* NO_SESSION_CACHE */
/* No session cache version */
WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret)
WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret,
byte restoreSessionCerts)
{
(void)ssl;
(void)masterSecret;
(void)restoreSessionCerts;
return NULL;
}

View File

@ -101,6 +101,9 @@ const char* wc_GetErrorString(int error)
case MEMORY_E :
return "out of memory error";
case VAR_STATE_CHANGE_E :
return "Variable state modified by different thread";
case RSA_WRONG_TYPE_E :
return "RSA wrong block type for RSA function";

View File

@ -2164,11 +2164,11 @@ struct WOLFSSL_X509_CHAIN {
/* wolfSSL session type */
struct WOLFSSL_SESSION {
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 */
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 */
#ifdef SESSION_CERTS
WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */
ProtocolVersion version; /* which version was used */
@ -2176,23 +2176,23 @@ struct WOLFSSL_SESSION {
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[SERVER_ID_LEN]; /* for easier client lookup */
#endif
#ifdef HAVE_SESSION_TICKET
byte* ticket;
word16 ticketLen;
byte staticTicket[SESSION_TICKET_LEN];
byte isDynamic;
byte* ticket;
word16 ticketLen;
byte staticTicket[SESSION_TICKET_LEN];
byte isDynamic;
#endif
#ifdef HAVE_STUNNEL
void* ex_data[MAX_EX_DATA];
void* ex_data[MAX_EX_DATA];
#endif
};
WOLFSSL_LOCAL
WOLFSSL_SESSION* GetSession(WOLFSSL*, byte*);
WOLFSSL_SESSION* GetSession(WOLFSSL*, byte*, byte);
WOLFSSL_LOCAL
int SetSession(WOLFSSL*, WOLFSSL_SESSION*);

View File

@ -287,6 +287,7 @@ WOLFSSL_API void wolfSSL_set_quiet_shutdown(WOLFSSL*, int);
WOLFSSL_API int wolfSSL_get_error(WOLFSSL*, int);
WOLFSSL_API int wolfSSL_get_alert_history(WOLFSSL*, WOLFSSL_ALERT_HISTORY *);
WOLFSSL_API int GetDeepCopySession(WOLFSSL*, WOLFSSL_SESSION*);
WOLFSSL_API int wolfSSL_set_session(WOLFSSL* ssl,WOLFSSL_SESSION* session);
WOLFSSL_API long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* session, long t);
WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl);

View File

@ -59,6 +59,8 @@ enum {
MP_ZERO_E = -121, /* got a mp zero result, not expected */
MEMORY_E = -125, /* out of memory error */
VAR_STATE_CHANGE_E = -126, /* var state modified by different thread */
RSA_WRONG_TYPE_E = -130, /* RSA wrong block type for RSA function */
RSA_BUFFER_E = -131, /* RSA buffer error, output too small or