tls13: support ticketNonce bigger than MAX_TICKET_NONCE_SZ

to enable it, use WOLFSSL_TICKET_NONCE_MALLOC define
This commit is contained in:
Marco Oliverio
2022-09-14 15:35:12 +02:00
parent 1a983b4a8f
commit 56d6087749
9 changed files with 529 additions and 16 deletions

View File

@@ -1340,6 +1340,15 @@ if(WOLFSSL_SESSION_TICKET)
"-DHAVE_SESSION_TICKET")
endif()
add_option("WOLFSSL_TICKET_NONCE_MALLOC"
"Enable dynamic allocation of ticket nonces (default: disabled)"
"no" "yes;no")
if(WOLFSSL_TICKET_NONCE_MALLOC)
list(APPEND WOLFSSL_DEFINITIONS
"-DWOLFSSL_TICKET_NONCE_MALLOC")
endif()
# Extended master secret extension
add_option("WOLFSSL_EXTENDED_MASTER"
"Enable Extended Master Secret (default: enabled)"

View File

@@ -4903,6 +4903,17 @@ then
AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SESSION_TICKET"
fi
AC_ARG_ENABLE([ticket-nonce-malloc],
[AS_HELP_STRING([--enable-ticket-nonce-malloc], [Enable dynamic allocation of ticket nonces (default: disabled)])],
[ ENABLED_TICKET_NONCE_MALLOC=$enableval ],
[ ENABLED_TICKET_NONCE_MALLOC=no ]
)
if test "$ENABLED_TICKET_NONCE_MALLOC" = "yes"
then
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TICKET_NONCE_MALLOC"
fi
# Extended Master Secret Extension
AC_ARG_ENABLE([extended-master],
[AS_HELP_STRING([--enable-extended-master],[Enable Extended Master Secret (default: enabled)])],

View File

@@ -33986,6 +33986,11 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif
/* Resumption master secret. */
XMEMCPY(it->msecret, ssl->session->masterSecret, SECRET_LEN);
if (ssl->session->ticketNonce.len > MAX_TICKET_NONCE_STATIC_SZ) {
WOLFSSL_MSG("Bad ticket nonce value");
ret = BAD_TICKET_MSG_SZ;
goto error;
}
XMEMCPY(it->ticketNonce, ssl->session->ticketNonce.data,
ssl->session->ticketNonce.len);
it->ticketNonceLen = ssl->session->ticketNonce.len;
@@ -34264,6 +34269,20 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#endif
/* Resumption master secret. */
XMEMCPY(ssl->session->masterSecret, it->msecret, SECRET_LEN);
if (it->ticketNonceLen > MAX_TICKET_NONCE_STATIC_SZ) {
WOLFSSL_MSG("Unsupported ticketNonce len in ticket");
return BAD_TICKET_ENCRYPT;
}
#if defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
if (ssl->session->ticketNonce.data
!= ssl->session->ticketNonce.dataStatic) {
XFREE(ssl->session->ticketNonce.data, ssl->heap,
DYNAMIC_TYPE_SESSION_TICK);
ssl->session->ticketNonce.data =
ssl->session->ticketNonce.dataStatic;
}
#endif /* defined(WOLFSSL_TICKET_NONCE_MALLOC) && FIPS_VERSION_GE(5,3) */
XMEMCPY(ssl->session->ticketNonce.data, it->ticketNonce,
it->ticketNonceLen);
ssl->session->ticketNonce.len = it->ticketNonceLen;

View File

@@ -3292,7 +3292,7 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
/* ticket nonce */
len = input[0];
if (len > MAX_TICKET_NONCE_SZ) {
if (len > MAX_TICKET_NONCE_STATIC_SZ) {
SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
return -1;
}
@@ -3302,7 +3302,7 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
/* store nonce in server for DeriveResumptionPSK */
session->sslServer->session->ticketNonce.len = len;
if (len > 0)
XMEMCPY(&session->sslServer->session->ticketNonce.data, input, len);
XMEMCPY(session->sslServer->session->ticketNonce.data, input, len);
#endif
input += len;
*sslBytes -= len;

316
src/ssl.c
View File

@@ -13555,6 +13555,40 @@ static int SslSessionCacheOff(const WOLFSSL* ssl, const WOLFSSL_SESSION* session
;
}
#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TLS13) && \
defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
/**
* SessionTicketNoncePrealloc() - prealloc a buffer for ticket nonces
* @output: [in] pointer to WOLFSSL_SESSION object that will soon be a
* destination of a session duplication
* @buf: [out] address of the preallocated buf
* @len: [out] len of the preallocated buf
*
* prealloc a buffer that will likely suffice to contain a ticket nonce. It's
* used when copying session under lock, when syscalls need to be avoided. If
* output already has a dynamic buffer, it's reused.
*/
static int SessionTicketNoncePrealloc(byte** buf, byte* len, void *heap)
{
(void)heap;
*buf = (byte*)XMALLOC(PREALLOC_SESSION_TICKET_NONCE_LEN, heap,
DYNAMIC_TYPE_SESSION_TICK);
if (*buf == NULL) {
WOLFSSL_MSG("Failed to preallocate ticket nonce buffer");
*len = 0;
return WOLFSSL_FAILURE;
}
*len = PREALLOC_SESSION_TICKET_NONCE_LEN;
return 0;
}
#endif /* HAVE_SESSION_TICKET && WOLFSSL_TLS13 */
static int wolfSSL_DupSessionEx(const WOLFSSL_SESSION* input,
WOLFSSL_SESSION* output, int avoidSysCalls, byte* ticketNonceBuf,
byte* ticketNonceLen, byte* preallocUsed);
int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output)
{
@@ -13571,6 +13605,11 @@ int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output)
#else
byte* tmpTicket = NULL;
#endif
#ifdef WOLFSSL_TLS13
byte *preallocNonce = NULL;
byte preallocNonceLen = 0;
byte preallocNonceUsed = 0;
#endif /* WOLFSSL_TLS13 */
byte tmpBufSet = 0;
#endif
#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
@@ -13678,6 +13717,30 @@ int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output)
}
#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)))
if (output->ticketNonce.data != output->ticketNonce.dataStatic) {
XFREE(output->ticketNonce.data, output->heap,
DYNAMIC_TYPE_SESSION_TICK);
output->ticketNonce.data = output->ticketNonce.dataStatic;
output->ticketNonce.len = 0;
}
error = SessionTicketNoncePrealloc(&preallocNonce, &preallocNonceLen,
output->heap);
if (error != 0) {
if (tmpBufSet) {
output->ticket = output->staticTicket;
output->ticketLenAlloc = 0;
}
#ifdef WOLFSSL_SMALL_STACK
if (tmpTicket != NULL)
XFREE(tmpTicket, output->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return WOLFSSL_FAILURE;
}
#endif /* WOLFSSL_TLS13 && HAVE_SESSION_TICKET*/
/* lock row */
sessRow = &SessionCache[row];
if (SESSION_ROW_LOCK(sessRow) != 0) {
@@ -13687,6 +13750,10 @@ int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output)
output->ticket = output->staticTicket;
output->ticketLenAlloc = 0;
}
#ifdef WOLFSSL_TLS13
if (preallocNonce != NULL)
XFREE(preallocNonce, output->heap, DYNAMIC_TYPE_SESSION_TICK);
#endif /* WOLFSSL_TLS13 */
#ifdef WOLFSSL_SMALL_STACK
if (tmpTicket != NULL)
XFREE(tmpTicket, output->heap, DYNAMIC_TYPE_TMP_BUFFER);
@@ -13731,7 +13798,13 @@ int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output)
sess->peer = NULL;
}
#endif
#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TLS13)
error = wolfSSL_DupSessionEx(sess, output, 1,
preallocNonce, &preallocNonceLen, &preallocNonceUsed);
#else
error = wolfSSL_DupSession(sess, output, 1);
#endif /* WOLFSSL_TSL */
#ifdef HAVE_EX_DATA
output->ownExData = 0; /* Session cache owns external data */
#endif
@@ -13780,6 +13853,45 @@ int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output)
if (tmpTicket != NULL)
XFREE(tmpTicket, output->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
if (error == WOLFSSL_SUCCESS && preallocNonceUsed) {
if (preallocNonceLen < PREALLOC_SESSION_TICKET_NONCE_LEN) {
/* buffer bigger than needed */
#ifndef XREALLOC
output->ticketNonce.data = (byte*)XMALLOC(preallocNonceLen,
output->heap, DYNAMIC_TYPE_SESSION_TICK);
if (output->ticketNonce.data != NULL)
XMEMCPY(output->ticketNonce.data, preallocNonce,
preallocNonceLen);
XFREE(preallocNonce, output->heap, DYNAMIC_TYPE_SESSION_TICK);
preallocNonce = NULL;
#else
output->ticketNonce.data = XREALLOC(preallocNonce,
preallocNonceLen, output->heap, DYNAMIC_TYPE_SESSION_TICK);
if (output->ticketNonce.data != NULL) {
/* don't free the reallocated pointer */
preallocNonce = NULL;
}
#endif /* !XREALLOC */
if (output->ticketNonce.data == NULL) {
output->ticketNonce.data = output->ticketNonce.dataStatic;
output->ticketNonce.len = 0;
error = WOLFSSL_FAILURE;
/* preallocNonce will be free'd after the if */
}
}
else {
output->ticketNonce.data = preallocNonce;
output->ticketNonce.len = preallocNonceLen;
preallocNonce = NULL;
}
}
if (preallocNonce != NULL)
XFREE(preallocNonce, output->heap, DYNAMIC_TYPE_SESSION_TICK);
#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/
#endif
#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
@@ -14091,7 +14203,14 @@ int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession,
byte ticBuffUsed = 0;
byte* ticBuff = NULL;
int ticLen = 0;
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
byte *preallocNonce = NULL;
byte preallocNonceLen = 0;
byte preallocNonceUsed = 0;
byte *toFree = NULL;
#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC */
#endif /* HAVE_SESSION_TICKET */
int ret = 0;
int row;
int i;
@@ -14113,7 +14232,6 @@ int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession,
return MEMORY_E;
}
/* Find a position for the new session in cache and use that */
#ifdef HAVE_SESSION_TICKET
ticLen = addSession->ticketLen;
/* Alloc Memory here to avoid syscalls during lock */
@@ -14124,13 +14242,35 @@ int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession,
return MEMORY_E;
}
}
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
if (addSession->ticketNonce.data != addSession->ticketNonce.dataStatic) {
/* use the AddSession->heap even if the buffer maybe saved in
* CachedSession objects. CachedSession heap and AddSession heap should
* be the same */
preallocNonce = (byte*)XMALLOC(addSession->ticketNonce.len,
addSession->heap, DYNAMIC_TYPE_SESSION_TICK);
if (preallocNonce == NULL) {
if (ticBuff != NULL)
XFREE(ticBuff, addSession->heap, DYNAMIC_TYPE_SESSION_TICK);
return MEMORY_E;
}
preallocNonceLen = addSession->ticketNonce.len;
}
#endif /* WOLFSSL_TLS13 && WOLFSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3) */
#endif /* HAVE_SESSION_TICKET */
/* Find a position for the new session in cache and use that */
/* Use the session object in the cache for external cache if required */
row = (int)(HashObject(id, ID_LEN, &ret) % SESSION_ROWS);
if (ret != 0) {
WOLFSSL_MSG("Hash session failed");
#ifdef HAVE_SESSION_TICKET
XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK);
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKE_NONCE_MALLOC)
if (preallocNonce != NULL)
XFREE(preallocNonce, addSession->heap, DYNAMIC_TYPE_SESSION_TICK);
#endif
#endif
return ret;
}
@@ -14139,6 +14279,10 @@ int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession,
if (SESSION_ROW_LOCK(sessRow) != 0) {
#ifdef HAVE_SESSION_TICKET
XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK);
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKE_NONCE_MALLOC)
if (preallocNonce != NULL)
XFREE(preallocNonce, addSession->heap, DYNAMIC_TYPE_SESSION_TICK);
#endif
#endif
WOLFSSL_MSG("Session row lock failed");
return BAD_MUTEX_E;
@@ -14193,6 +14337,19 @@ int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession,
cacheSession->ticket = ticBuff;
cacheSession->ticketLenAlloc = (word16) ticLen;
}
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
/* cache entry never used */
if (cacheSession->ticketNonce.data == NULL)
cacheSession->ticketNonce.data = cacheSession->ticketNonce.dataStatic;
if (cacheSession->ticketNonce.data !=
cacheSession->ticketNonce.dataStatic) {
toFree = cacheSession->ticketNonce.data;
cacheSession->ticketNonce.data = cacheSession->ticketNonce.dataStatic;
cacheSession->ticketNonce.len = 0;
}
#endif /* WOFLSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/
#endif
#ifdef SESSION_CERTS
if (overwrite &&
@@ -14206,7 +14363,15 @@ int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession,
#endif /* SESSION_CERTS */
cacheSession->heap = NULL;
/* Copy data into the cache object */
#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TLS13) && \
defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
ret = wolfSSL_DupSessionEx(addSession, cacheSession, 1, preallocNonce,
&preallocNonceLen, &preallocNonceUsed) == WOLFSSL_FAILURE;
#else
ret = wolfSSL_DupSession(addSession, cacheSession, 1) == WOLFSSL_FAILURE;
#endif /* HAVE_SESSION_TICKET && WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC
&& FIPS_VERSION_GE(5,3)*/
if (ret == 0) {
/* Increment the totalCount and the nextIdx */
@@ -14226,6 +14391,17 @@ int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession,
cacheSession->rem_sess_cb = ctx->rem_sess_cb;
}
#endif
#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TLS13) && \
defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
if (preallocNonce != NULL && preallocNonceUsed) {
cacheSession->ticketNonce.data = preallocNonce;
cacheSession->ticketNonce.len = preallocNonceLen;
preallocNonce = NULL;
preallocNonceLen = 0;
}
#endif /* HAVE_SESSION_TICKET && WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC
* && FIPS_VERSION_GE(5,3)*/
}
#ifdef HAVE_SESSION_TICKET
else if (ticBuffUsed) {
@@ -14253,6 +14429,13 @@ int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession,
XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK);
if (cacheTicBuff != NULL)
XFREE(cacheTicBuff, 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)))
if (preallocNonce != NULL)
XFREE(preallocNonce, addSession->heap, DYNAMIC_TYPE_SESSION_TICK);
if (toFree != NULL)
XFREE(toFree, addSession->heap, DYNAMIC_TYPE_SESSION_TICK);
#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/
#endif
#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
@@ -20024,6 +20207,10 @@ WOLFSSL_SESSION* wolfSSL_NewSession(void* heap)
#endif
#ifdef HAVE_SESSION_TICKET
ret->ticket = ret->staticTicket;
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
ret->ticketNonce.data = ret->ticketNonce.dataStatic;
#endif
#endif
#ifdef HAVE_STUNNEL
/* stunnel has this funny mechanism of storing the "is_authenticated"
@@ -20086,11 +20273,16 @@ int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session)
* sessions from cache. When a cache row is locked, we
* don't want to block other threads with long running
* system calls.
* @param ticketNonceBuf If not null and @avoidSysCalls is true, the copy of the
* ticketNonce will happen in this pre allocated buffer
* @param ticketNonceLen @ticketNonceBuf len as input, used length on output
* @param ticketNonceUsed if @ticketNonceBuf was used to copy the ticket noncet
* @return WOLFSSL_SUCCESS on success
* WOLFSSL_FAILURE on failure
*/
int wolfSSL_DupSession(const WOLFSSL_SESSION* input, WOLFSSL_SESSION* output,
int avoidSysCalls)
static int wolfSSL_DupSessionEx(const WOLFSSL_SESSION* input,
WOLFSSL_SESSION* output, int avoidSysCalls, byte* ticketNonceBuf,
byte* ticketNonceLen, byte* preallocUsed)
{
#ifdef HAVE_SESSION_TICKET
int ticLenAlloc = 0;
@@ -20100,6 +20292,9 @@ int wolfSSL_DupSession(const WOLFSSL_SESSION* input, WOLFSSL_SESSION* output,
int ret = WOLFSSL_SUCCESS;
(void)avoidSysCalls;
(void)ticketNonceBuf;
(void)ticketNonceLen;
(void)preallocUsed;
input = ClientSessionToSession(input);
output = ClientSessionToSession(output);
@@ -20114,7 +20309,27 @@ int wolfSSL_DupSession(const WOLFSSL_SESSION* input, WOLFSSL_SESSION* output,
ticBuff = output->ticket;
ticLenAlloc = output->ticketLenAlloc;
}
#endif
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
/* free the data, it would be better to re-use the buffer but this
* maintain the code simpler. A smart allocator should re-use the free'd
* buffer in the next malloc without much performance penalties. */
if (output->ticketNonce.data != output->ticketNonce.dataStatic) {
/* Callers that avoid syscall should never calls this with
* output->tickeNonce.data being a dynamic buffer.*/
if (avoidSysCalls) {
WOLFSSL_MSG("can't avoid syscalls with dynamic TicketNonce buffer");
return WOLFSSL_FAILURE;
}
XFREE(output->ticketNonce.data,
output->heap, DYNAMIC_TYPE_SESSION_TICK);
output->ticketNonce.data = output->ticketNonce.dataStatic;
output->ticketNonce.len = 0;
}
#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/
#endif /* HAVE_SESSION_TICKET */
#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
if (output->peer != NULL) {
@@ -20130,6 +20345,12 @@ int wolfSSL_DupSession(const WOLFSSL_SESSION* input, WOLFSSL_SESSION* output,
XMEMCPY((byte*)output + copyOffset, (byte*)input + copyOffset,
sizeof(WOLFSSL_SESSION) - copyOffset);
#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TLS13) && \
defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
/* fix pointer to static after the copy */
output->ticketNonce.data = output->ticketNonce.dataStatic;
#endif
/* Set sane values for copy */
#ifndef NO_SESSION_CACHE
if (output->type != WOLFSSL_SESSION_TYPE_CACHE)
@@ -20223,10 +20444,74 @@ int wolfSSL_DupSession(const WOLFSSL_SESSION* input, WOLFSSL_SESSION* output,
}
}
ticBuff = NULL;
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
if (preallocUsed != NULL)
*preallocUsed = 0;
if (input->ticketNonce.len > MAX_TICKET_NONCE_STATIC_SZ &&
ret == WOLFSSL_SUCCESS) {
/* TicketNonce does not fit in the static buffer */
if (!avoidSysCalls) {
output->ticketNonce.data = (byte*)XMALLOC(input->ticketNonce.len,
output->heap, DYNAMIC_TYPE_SESSION_TICK);
if (output->ticketNonce.data == NULL) {
WOLFSSL_MSG("Failed to allocate space for ticket nonce");
output->ticketNonce.data = output->ticketNonce.dataStatic;
output->ticketNonce.len = 0;
ret = WOLFSSL_FAILURE;
}
else {
output->ticketNonce.len = input->ticketNonce.len;
XMEMCPY(output->ticketNonce.data, input->ticketNonce.data,
input->ticketNonce.len);
ret = WOLFSSL_SUCCESS;
}
}
/* we can't do syscalls. Use prealloc buffers if provided from the
* caller. */
else if (ticketNonceBuf != NULL &&
*ticketNonceLen >= input->ticketNonce.len) {
XMEMCPY(ticketNonceBuf, input->ticketNonce.data,
input->ticketNonce.len);
*ticketNonceLen = input->ticketNonce.len;
if (preallocUsed != NULL)
*preallocUsed = 1;
ret = WOLFSSL_SUCCESS;
}
else {
WOLFSSL_MSG("TicketNonce bigger than static buffer, and we can't "
"do syscalls");
ret = WOLFSSL_FAILURE;
}
}
#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/
#endif /* HAVE_SESSION_TICKET */
return ret;
}
/**
* Deep copy the contents from input to output.
* @param input The source of the copy.
* @param output The destination of the copy.
* @param avoidSysCalls If true, then system calls will be avoided or an error
* will be returned if it is not possible to proceed
* without a system call. This is useful for fetching
* sessions from cache. When a cache row is locked, we
* don't want to block other threads with long running
* system calls.
* @return WOLFSSL_SUCCESS on success
* WOLFSSL_FAILURE on failure
*/
int wolfSSL_DupSession(const WOLFSSL_SESSION* input, WOLFSSL_SESSION* output,
int avoidSysCalls)
{
return wolfSSL_DupSessionEx(input, output, avoidSysCalls, NULL, NULL, NULL);
}
WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session)
{
#ifdef HAVE_EXT_CACHE
@@ -20316,6 +20601,13 @@ void wolfSSL_FreeSession(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session)
if (session->ticketLenAlloc > 0) {
XFREE(session->ticket, session->heap, 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)))
if (session->ticketNonce.data != session->ticketNonce.dataStatic) {
XFREE(session->ticketNonce.data, session->heap,
DYNAMIC_TYPE_SESSION_TICK);
}
#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/
#endif
#ifdef HAVE_EX_DATA_CLEANUP_HOOKS
@@ -25764,7 +26056,19 @@ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess,
ret = BUFFER_ERROR;
goto end;
}
#if defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
ret = SessionTicketNoncePopulate(s, data + idx, s->ticketNonce.len);
if (ret != 0)
goto end;
#else
if (s->ticketNonce.len > MAX_TICKET_NONCE_STATIC_SZ) {
ret = BUFFER_ERROR;
goto end;
}
XMEMCPY(s->ticketNonce.data, data + idx, s->ticketNonce.len);
#endif /* defined(WOLFSSL_TICKET_NONCE_MALLOC) && FIPS_VERSION_GE(5,3) */
idx += s->ticketNonce.len;
#endif
#ifdef WOLFSSL_EARLY_DATA

View File

@@ -1036,6 +1036,7 @@ int DeriveMasterSecret(WOLFSSL* ssl)
#define RESUMPTION_LABEL_SZ 10
/* Resumption label for generating PSK associated with the ticket. */
static const byte resumptionLabel[RESUMPTION_LABEL_SZ+1] = "resumption";
/* Derive the PSK associated with the ticket.
*
* ssl The SSL/TLS object.
@@ -1078,10 +1079,17 @@ int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, byte* secret)
}
PRIVATE_KEY_UNLOCK();
#if defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
ret = wc_Tls13_HKDF_Expand_Label_Alloc(secret, ssl->specs.hash_size,
ssl->session->masterSecret, ssl->specs.hash_size, protocol, protocolLen,
resumptionLabel, RESUMPTION_LABEL_SZ, nonce, nonceLen, digestAlg,
ssl->heap);
#else
ret = wc_Tls13_HKDF_Expand_Label(secret, ssl->specs.hash_size,
ssl->session->masterSecret, ssl->specs.hash_size,
protocol, protocolLen, resumptionLabel,
RESUMPTION_LABEL_SZ, nonce, nonceLen, digestAlg);
ssl->session->masterSecret, ssl->specs.hash_size, protocol, protocolLen,
resumptionLabel, RESUMPTION_LABEL_SZ, nonce, nonceLen, digestAlg);
#endif /* !defined(HAVE_FIPS) || FIPS_VERSION_GE(5,3) */
PRIVATE_KEY_LOCK();
return ret;
}
@@ -9181,6 +9189,31 @@ static int DoTls13EndOfEarlyData(WOLFSSL* ssl, const byte* input,
#endif /* !NO_WOLFSSL_SERVER */
#endif /* WOLFSSL_EARLY_DATA */
#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
int SessionTicketNoncePopulate(WOLFSSL_SESSION *session, const byte *nonce,
byte len)
{
if (session->ticketNonce.data
!= session->ticketNonce.dataStatic) {
XFREE(session->ticketNonce.data, heap,
DYNAMIC_TYPE_SESSION_TICK);
session->ticketNonce.data = session->ticketNonce.dataStatic;
session->ticketNonce.len = 0;
}
if (len > MAX_TICKET_NONCE_STATIC_SZ) {
WOLFSSL_MSG("Using dynamic nonce buffer");
session->ticketNonce.data = (byte*)XMALLOC(len,
session->heap, DYNAMIC_TYPE_SESSION_TICK);
if (session->ticketNonce.data == NULL)
return MEMORY_ERROR;
}
XMEMCPY(session->ticketNonce.data, nonce, len);
session->ticketNonce.len = len;
return 0;
}
#endif
#ifndef NO_WOLFSSL_CLIENT
/* Handle a New Session Ticket handshake message.
* Message contains the information required to perform resumption.
@@ -9232,11 +9265,14 @@ static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input,
if ((*inOutIdx - begin) + 1 > size)
return BUFFER_ERROR;
nonceLength = input[*inOutIdx];
if (nonceLength > MAX_TICKET_NONCE_SZ) {
#if !defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,3))
if (nonceLength > MAX_TICKET_NONCE_STATIC_SZ) {
WOLFSSL_MSG("Nonce length not supported");
WOLFSSL_ERROR_VERBOSE(INVALID_PARAMETER);
return INVALID_PARAMETER;
}
#endif /* WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3) */
*inOutIdx += 1;
if ((*inOutIdx - begin) + nonceLength > size)
return BUFFER_ERROR;
@@ -9268,9 +9304,22 @@ static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input,
#ifdef WOLFSSL_EARLY_DATA
ssl->session->maxEarlyDataSz = ssl->options.maxEarlyDataSz;
#endif
#if defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
ret = SessionTicketNoncePopulate(ssl->session, nonce, nonceLength);
if (ret != 0)
return ret;
#else
ssl->session->ticketNonce.len = nonceLength;
if (nonceLength > MAX_TICKET_NONCE_STATIC_SZ) {
ret = BUFFER_ERROR;
return ret;
}
if (nonceLength > 0)
XMEMCPY(&ssl->session->ticketNonce.data, nonce, nonceLength);
XMEMCPY(ssl->session->ticketNonce.data, nonce, nonceLength);
#endif /* defined(WOLFSSL_TICKET_NONCE_MALLOC) && FIPS_VERSION_GE(5,3) */
ssl->session->namedGroup = ssl->namedGroup;
if ((*inOutIdx - begin) + EXTS_SZ > size)

View File

@@ -437,6 +437,13 @@ int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen,
int idx = 0;
byte data[MAX_TLS13_HKDF_LABEL_SZ];
/* okmLen (2) + protocol|label len (1) + info len(1) + protocollen +
* labellen + infolen */
idx = 4 + protocolLen + labelLen + infoLen;
if (idx > MAX_TLS13_HKDF_LABEL_SZ)
return BUFFER_E;
idx = 0;
/* Output length. */
data[idx++] = (byte)(okmLen >> 8);
data[idx++] = (byte)okmLen;
@@ -481,6 +488,95 @@ int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen,
return ret;
}
#if defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
/* Expand data using HMAC, salt and label and info.
* TLS v1.3 defines this function.
*
* okm The generated pseudorandom key - output key material.
* okmLen The length of generated pseudorandom key -
* output key material.
* prk The salt - pseudo-random key.
* prkLen The length of the salt - pseudo-random key.
* protocol The TLS protocol label.
* protocolLen The length of the TLS protocol label.
* info The information to expand.
* infoLen The length of the information.
* digest The type of digest to use.
*
* This functions is very similar to wc_Tls13_HKDF_Expand_Label() but it
* allocate memory if the stack space usually used isn't enough.
*
* returns 0 on success, otherwise failure.
*/
int wc_Tls13_HKDF_Expand_Label_Alloc(byte* okm, word32 okmLen,
const byte* prk, word32 prkLen, const byte* protocol,
word32 protocolLen, const byte* label, word32 labelLen,
const byte* info, word32 infoLen, int digest, void* heap)
{
int ret = 0;
int idx = 0;
int len;
byte *data;
(void)heap;
/* okmLen (2) + protocol|label len (1) + info len(1) + protocollen +
* labellen + infolen */
len = 4 + protocolLen + labelLen + infoLen;
data = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_TMP_BUFFER);
if (data == NULL)
return BUFFER_E;
/* Output length. */
data[idx++] = (byte)(okmLen >> 8);
data[idx++] = (byte)okmLen;
/* Length of protocol | label. */
data[idx++] = (byte)(protocolLen + labelLen);
/* Protocol */
XMEMCPY(&data[idx], protocol, protocolLen);
idx += protocolLen;
/* Label */
XMEMCPY(&data[idx], label, labelLen);
idx += labelLen;
/* Length of hash of messages */
data[idx++] = (byte)infoLen;
/* Hash of messages */
XMEMCPY(&data[idx], info, infoLen);
idx += infoLen;
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Add("wc_Tls13_HKDF_Expand_Label data", data, idx);
#endif
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG(" PRK");
WOLFSSL_BUFFER(prk, prkLen);
WOLFSSL_MSG(" Info");
WOLFSSL_BUFFER(data, idx);
WOLFSSL_MSG_EX(" Digest %d", digest);
#endif
ret = wc_HKDF_Expand(digest, prk, prkLen, data, idx, okm, okmLen);
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG(" OKM");
WOLFSSL_BUFFER(okm, okmLen);
#endif
ForceZero(data, idx);
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Check(data, len);
#endif
XFREE(data, heap, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
#endif
/* defined(WOLFSSL_TICKET_NONCE_MALLOC) && (!defined(HAVE_FIPS) ||
* FIPS_VERSION_GE(5,3)) */
#endif /* HAVE_HKDF && !NO_HMAC */

View File

@@ -1388,7 +1388,7 @@ enum Misc {
SESSION_ADD_SZ = 4, /* session age add */
TICKET_NONCE_LEN_SZ = 1, /* Ticket nonce length size */
DEF_TICKET_NONCE_SZ = 1, /* Default ticket nonce size */
MAX_TICKET_NONCE_SZ = 8, /* maximum ticket nonce size */
MAX_TICKET_NONCE_STATIC_SZ = 8, /* maximum ticket nonce static size */
MAX_LIFETIME = 604800, /* maximum ticket lifetime */
RAN_LEN = 32, /* random length */
@@ -1754,6 +1754,10 @@ enum Misc {
#define PREALLOC_SESSION_TICKET_LEN 512
#endif
#ifndef PREALLOC_SESSION_TICKET_NONCE_LEN
#define PREALLOC_SESSION_TICKET_NONCE_LEN 32
#endif
#ifndef SESSION_TICKET_HINT_DEFAULT
#define SESSION_TICKET_HINT_DEFAULT 300
#endif
@@ -2789,7 +2793,7 @@ typedef struct InternalTicket {
byte ageAdd[AGEADD_LEN]; /* Obfuscation of age */
byte namedGroup[NAMEDGROUP_LEN]; /* Named group used */
byte ticketNonceLen;
byte ticketNonce[MAX_TICKET_NONCE_SZ];
byte ticketNonce[MAX_TICKET_NONCE_STATIC_SZ];
#ifdef WOLFSSL_EARLY_DATA
byte maxEarlyDataSz[MAXEARLYDATASZ_LEN]; /* Max size of
* early data */
@@ -3693,8 +3697,15 @@ WOLFSSL_LOCAL int wolfSSL_quic_add_transport_extensions(WOLFSSL *ssl, int msg_ty
*/
typedef struct TicketNonce {
byte len;
byte data[MAX_TICKET_NONCE_SZ];
#if defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
byte *data;
byte dataStatic[MAX_TICKET_NONCE_STATIC_SZ];
#else
byte data[MAX_TICKET_NONCE_STATIC_SZ];
#endif /* WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3) */
} TicketNonce;
#endif
/* wolfSSL session type */
@@ -3790,6 +3801,13 @@ struct WOLFSSL_SESSION {
#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)))
WOLFSSL_LOCAL int SessionTicketNoncePopulate(WOLFSSL_SESSION *session,
const byte* nonce, byte len);
#endif /* WOLFSSL_TLS13 && */
WOLFSSL_LOCAL int wolfSSL_RAND_Init(void);
WOLFSSL_LOCAL WOLFSSL_SESSION* wolfSSL_NewSession(void* heap);

View File

@@ -85,6 +85,13 @@ WOLFSSL_API int wc_Tls13_HKDF_Expand_Label(byte* okm, word32 okmLen,
const byte* label, word32 labelLen,
const byte* info, word32 infoLen,
int digest);
#if defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
WOLFSSL_API int wc_Tls13_HKDF_Expand_Label_Alloc(byte* okm, word32 okmLen,
const byte* prk, word32 prkLen, const byte* protocol, word32 protocolLen,
const byte* label, word32 labelLen, const byte* info, word32 infoLen,
int digest, void* heap);
#endif /* !defined(HAVE_FIPS) || FIPS_VERSION_GE(5,3) */
#endif /* HAVE_HKDF */