Adds Session Ticket TLS Extension handling.
New Session Ticket Handshake Message handling is still needed for Session Tickets to work.
This commit is contained in:
parent
6a75c8d144
commit
a937040087
@ -1233,7 +1233,7 @@ typedef enum {
|
||||
MAX_FRAGMENT_LENGTH = 0x0001,
|
||||
TRUNCATED_HMAC = 0x0004,
|
||||
ELLIPTIC_CURVES = 0x000a,
|
||||
/*SESSION_TICKET = 0x0023, not used yet in switch statements */
|
||||
SESSION_TICKET = 0x0023,
|
||||
SECURE_RENEGOTIATION = 0xff01
|
||||
} TLSX_Type;
|
||||
|
||||
@ -1317,7 +1317,6 @@ CYASSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions);
|
||||
typedef struct EllipticCurve {
|
||||
word16 name; /* CurveNames */
|
||||
struct EllipticCurve* next; /* List Behavior */
|
||||
|
||||
} EllipticCurve;
|
||||
|
||||
CYASSL_LOCAL int TLSX_UseSupportedCurve(TLSX** extensions, word16 name);
|
||||
@ -1354,6 +1353,20 @@ CYASSL_LOCAL int TLSX_UseSecureRenegotiation(TLSX** extensions);
|
||||
|
||||
#endif /* HAVE_SECURE_RENEGOTIATION */
|
||||
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
|
||||
typedef struct SessionTicket {
|
||||
word32 lifetime;
|
||||
byte* data;
|
||||
word16 size;
|
||||
} SessionTicket;
|
||||
|
||||
CYASSL_LOCAL int TLSX_UseSessionTicket(TLSX** extensions,
|
||||
SessionTicket* ticket);
|
||||
CYASSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime,
|
||||
byte* data, word16 size);
|
||||
CYASSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket);
|
||||
#endif /* HAVE_SESSION_TICKET */
|
||||
|
||||
/* CyaSSL context type */
|
||||
struct CYASSL_CTX {
|
||||
@ -2043,6 +2056,23 @@ struct CYASSL {
|
||||
#ifdef HAVE_SECURE_RENEGOTIATION
|
||||
SecureRenegotiation* secure_renegotiation; /* valid pointer indicates */
|
||||
#endif /* user turned on */
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
#ifndef NO_CYASSL_CLIENT
|
||||
/*
|
||||
Create cantidate_ticket when processing New Session Ticket Handshake
|
||||
Message. When the ticket is validated at Finished Handshake Message,
|
||||
move canditate_ticket to session_ticket and call:
|
||||
TLSX_UseSessionTicket(&ssl->extensions, ssl->session_ticket);
|
||||
|
||||
If the session_ticket must be destroyed, call:
|
||||
TLSX_UseSessionTicket(&ssl->extensions, NULL);
|
||||
This function doesn't free an early ticket, but will erase it's
|
||||
reference inside the extensions.
|
||||
*/
|
||||
SessionTicket* candidate_ticket;
|
||||
SessionTicket* session_ticket;
|
||||
#endif
|
||||
#endif
|
||||
#endif /* HAVE_TLS_EXTENSIONS */
|
||||
#ifdef HAVE_NETX
|
||||
NetX_Ctx nxCtx; /* NetX IO Context */
|
||||
|
12
cyassl/ssl.h
12
cyassl/ssl.h
@ -1316,7 +1316,17 @@ CYASSL_API int CyaSSL_CTX_UseSupportedCurve(CYASSL_CTX* ctx,
|
||||
CYASSL_API int CyaSSL_UseSecureRenegotiation(CYASSL* ssl);
|
||||
CYASSL_API int CyaSSL_Rehandshake(CYASSL* ssl);
|
||||
|
||||
#endif /* HAVE_SECURE_RENEGOTIATION */
|
||||
#endif
|
||||
|
||||
/* Session Ticket */
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
#ifndef NO_CYASSL_CLIENT
|
||||
|
||||
CYASSL_API int CyaSSL_UseSessionTicket(CYASSL* ssl);
|
||||
CYASSL_API int CyaSSL_CTX_UseSessionTicket(CYASSL_CTX* ctx);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define CYASSL_CRL_MONITOR 0x01 /* monitor this dir flag */
|
||||
#define CYASSL_CRL_START_MON 0x02 /* start monitoring flag */
|
||||
|
@ -596,6 +596,10 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args)
|
||||
if (CyaSSL_CTX_UseTruncatedHMAC(ctx) != SSL_SUCCESS)
|
||||
err_sys("UseTruncatedHMAC failed");
|
||||
#endif
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
if (CyaSSL_CTX_UseSessionTicket(ctx) != SSL_SUCCESS)
|
||||
err_sys("UseSessionTicket failed");
|
||||
#endif
|
||||
|
||||
if (benchmark) {
|
||||
/* time passed in number of connects give average */
|
||||
|
@ -1745,6 +1745,12 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
|
||||
#ifdef HAVE_SECURE_RENEGOTIATION
|
||||
ssl->secure_renegotiation = NULL;
|
||||
#endif
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
#ifndef NO_CYASSL_CLIENT
|
||||
ssl->candidate_ticket = NULL;
|
||||
ssl->session_ticket = NULL;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ssl->rng = NULL;
|
||||
@ -2001,6 +2007,12 @@ void SSL_ResourceFree(CYASSL* ssl)
|
||||
#ifdef HAVE_TLS_EXTENSIONS
|
||||
TLSX_FreeAll(ssl->extensions);
|
||||
#endif
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
#ifndef NO_CYASSL_CLIENT
|
||||
TLSX_SessionTicket_Free(ssl->candidate_ticket);
|
||||
TLSX_SessionTicket_Free(ssl->session_ticket);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAVE_NETX
|
||||
if (ssl->nxCtx.nxPacket)
|
||||
nx_packet_release(ssl->nxCtx.nxPacket);
|
||||
|
20
src/ssl.c
20
src/ssl.c
@ -796,6 +796,26 @@ int CyaSSL_Rehandshake(CYASSL* ssl)
|
||||
|
||||
#endif /* HAVE_SECURE_RENEGOTIATION */
|
||||
|
||||
/* Session Ticket */
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
#ifndef NO_CYASSL_CLIENT
|
||||
int CyaSSL_UseSessionTicket(CYASSL* ssl)
|
||||
{
|
||||
if (ssl == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
return TLSX_UseSessionTicket(&ssl->extensions, NULL);
|
||||
}
|
||||
|
||||
int CyaSSL_CTX_UseSessionTicket(CYASSL_CTX* ctx)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
return TLSX_UseSessionTicket(&ctx->extensions, NULL);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CYASSL_LEANPSK
|
||||
|
||||
|
186
src/tls.c
186
src/tls.c
@ -1314,20 +1314,6 @@ int TLSX_UseMaxFragment(TLSX** extensions, byte mfl)
|
||||
|
||||
#ifdef HAVE_TRUNCATED_HMAC
|
||||
|
||||
int TLSX_UseTruncatedHMAC(TLSX** extensions)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (extensions == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (!TLSX_Find(*extensions, TRUNCATED_HMAC))
|
||||
if ((ret = TLSX_Push(extensions, TRUNCATED_HMAC, NULL)) != 0)
|
||||
return ret;
|
||||
|
||||
return SSL_SUCCESS;
|
||||
}
|
||||
|
||||
static int TLSX_THM_Parse(CYASSL* ssl, byte* input, word16 length,
|
||||
byte isRequest)
|
||||
{
|
||||
@ -1349,6 +1335,19 @@ static int TLSX_THM_Parse(CYASSL* ssl, byte* input, word16 length,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TLSX_UseTruncatedHMAC(TLSX** extensions)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (extensions == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if ((ret = TLSX_Push(extensions, TRUNCATED_HMAC, NULL)) != 0)
|
||||
return ret;
|
||||
|
||||
return SSL_SUCCESS;
|
||||
}
|
||||
|
||||
#define THM_PARSE TLSX_THM_Parse
|
||||
|
||||
#else
|
||||
@ -1637,9 +1636,11 @@ int TLSX_UseSupportedCurve(TLSX** extensions, word16 name)
|
||||
#define EC_VALIDATE_REQUEST(a, b)
|
||||
|
||||
#endif /* HAVE_SUPPORTED_CURVES */
|
||||
|
||||
#ifdef HAVE_SECURE_RENEGOTIATION
|
||||
|
||||
static byte TLSX_SCR_GetSize(SecureRenegotiation* data, int isRequest)
|
||||
static byte TLSX_SecureRenegotiation_GetSize(SecureRenegotiation* data,
|
||||
int isRequest)
|
||||
{
|
||||
byte length = OPAQUE8_LEN; /* empty info length */
|
||||
|
||||
@ -1655,8 +1656,8 @@ static byte TLSX_SCR_GetSize(SecureRenegotiation* data, int isRequest)
|
||||
return length;
|
||||
}
|
||||
|
||||
static word16 TLSX_SCR_Write(SecureRenegotiation* data, byte* output,
|
||||
int isRequest)
|
||||
static word16 TLSX_SecureRenegotiation_Write(SecureRenegotiation* data,
|
||||
byte* output, int isRequest)
|
||||
{
|
||||
word16 offset = OPAQUE8_LEN; /* RenegotiationInfo length */
|
||||
|
||||
@ -1677,8 +1678,8 @@ static word16 TLSX_SCR_Write(SecureRenegotiation* data, byte* output,
|
||||
return offset;
|
||||
}
|
||||
|
||||
static int TLSX_SCR_Parse(CYASSL* ssl, byte* input, word16 length,
|
||||
byte isRequest)
|
||||
static int TLSX_SecureRenegotiation_Parse(CYASSL* ssl, byte* input,
|
||||
word16 length, byte isRequest)
|
||||
{
|
||||
int ret = SECURE_RENEGOTIATION_E;
|
||||
|
||||
@ -1745,9 +1746,9 @@ int TLSX_UseSecureRenegotiation(TLSX** extensions)
|
||||
|
||||
|
||||
#define SCR_FREE_ALL(data) XFREE(data, NULL, DYNAMIC_TYPE_TLSX)
|
||||
#define SCR_GET_SIZE TLSX_SCR_GetSize
|
||||
#define SCR_WRITE TLSX_SCR_Write
|
||||
#define SCR_PARSE TLSX_SCR_Parse
|
||||
#define SCR_GET_SIZE TLSX_SecureRenegotiation_GetSize
|
||||
#define SCR_WRITE TLSX_SecureRenegotiation_Write
|
||||
#define SCR_PARSE TLSX_SecureRenegotiation_Parse
|
||||
|
||||
#else
|
||||
|
||||
@ -1758,6 +1759,116 @@ int TLSX_UseSecureRenegotiation(TLSX** extensions)
|
||||
|
||||
#endif /* HAVE_SECURE_RENEGOTIATION */
|
||||
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
|
||||
static void TLSX_SessionTicket_ValidateRequest(CYASSL* ssl)
|
||||
{
|
||||
TLSX* extension = TLSX_Find(ssl->extensions, SESSION_TICKET);
|
||||
SessionTicket* ticket = extension ? extension->data : NULL;
|
||||
|
||||
if (ticket) {
|
||||
/* TODO validate ticket timeout here! */
|
||||
if (ticket->lifetime == 0xfffffff) {
|
||||
/* send empty ticket on timeout */
|
||||
TLSX_UseSessionTicket(&ssl->extensions, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static byte TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest)
|
||||
{
|
||||
return isRequest && ticket ? OPAQUE16_LEN + ticket->size : 0;
|
||||
}
|
||||
|
||||
|
||||
static word16 TLSX_SessionTicket_Write(SessionTicket* ticket, byte* output,
|
||||
int isRequest)
|
||||
{
|
||||
int offset = 0; /* empty ticket */
|
||||
|
||||
if (isRequest && ticket) {
|
||||
c16toa(ticket->size, output + offset);
|
||||
offset += OPAQUE16_LEN;
|
||||
|
||||
XMEMCPY(output + offset, ticket->data, ticket->size);
|
||||
offset += ticket->size;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
static int TLSX_SessionTicket_Parse(CYASSL* ssl, byte* input, word16 length,
|
||||
byte isRequest)
|
||||
{
|
||||
if (!isRequest)
|
||||
return length != 0 ? BUFFER_ERROR : 0;
|
||||
|
||||
/* TODO server side */
|
||||
(void)ssl;
|
||||
(void)input;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CYASSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime,
|
||||
byte* data, word16 size)
|
||||
{
|
||||
SessionTicket* ticket = (SessionTicket*)XMALLOC(sizeof(SessionTicket),
|
||||
NULL, DYNAMIC_TYPE_TLSX);
|
||||
if (ticket) {
|
||||
ticket->data = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TLSX);
|
||||
if (ticket->data == NULL) {
|
||||
XFREE(ticket, NULL, DYNAMIC_TYPE_TLSX);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XMEMCPY(ticket->data, data, size);
|
||||
ticket->size = size;
|
||||
ticket->lifetime = lifetime;
|
||||
}
|
||||
|
||||
return ticket;
|
||||
}
|
||||
CYASSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket)
|
||||
{
|
||||
if (ticket) {
|
||||
XFREE(ticket->data, NULL, DYNAMIC_TYPE_TLSX);
|
||||
XFREE(ticket, NULL, DYNAMIC_TYPE_TLSX);
|
||||
}
|
||||
}
|
||||
|
||||
int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (extensions == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
/* If the ticket is NULL, the client will request a new ticket from the
|
||||
server. Otherwise, the client will use it in the next client hello. */
|
||||
if ((ret = TLSX_Push(extensions, SESSION_TICKET, (void*)ticket)) != 0)
|
||||
return ret;
|
||||
|
||||
return SSL_SUCCESS;
|
||||
}
|
||||
|
||||
#define STK_VALIDATE_REQUEST TLSX_SessionTicket_ValidateRequest
|
||||
#define STK_GET_SIZE TLSX_SessionTicket_GetSize
|
||||
#define STK_WRITE TLSX_SessionTicket_Write
|
||||
#define STK_PARSE TLSX_SessionTicket_Parse
|
||||
|
||||
#else
|
||||
|
||||
#define STK_VALIDATE_REQUEST(a)
|
||||
#define STK_GET_SIZE(a, b) 0
|
||||
#define STK_WRITE(a, b, c) 0
|
||||
#define STK_PARSE(a, b, c, d) 0
|
||||
|
||||
#endif /* HAVE_SESSION_TICKET */
|
||||
|
||||
|
||||
TLSX* TLSX_Find(TLSX* list, TLSX_Type type)
|
||||
{
|
||||
TLSX* extension = list;
|
||||
@ -1795,6 +1906,10 @@ void TLSX_FreeAll(TLSX* list)
|
||||
case SECURE_RENEGOTIATION:
|
||||
SCR_FREE_ALL(extension->data);
|
||||
break;
|
||||
|
||||
case SESSION_TICKET:
|
||||
/* Nothing to do. */
|
||||
break;
|
||||
}
|
||||
|
||||
XFREE(extension, 0, DYNAMIC_TYPE_TLSX);
|
||||
@ -1842,6 +1957,10 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest)
|
||||
case SECURE_RENEGOTIATION:
|
||||
length += SCR_GET_SIZE(extension->data, isRequest);
|
||||
break;
|
||||
|
||||
case SESSION_TICKET:
|
||||
length += STK_GET_SIZE(extension->data, isRequest);
|
||||
break;
|
||||
}
|
||||
|
||||
TURN_ON(semaphore, TLSX_ToSemaphore(extension->type));
|
||||
@ -1875,11 +1994,11 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore,
|
||||
switch (extension->type) {
|
||||
case SERVER_NAME_INDICATION:
|
||||
if (isRequest)
|
||||
offset += SNI_WRITE((SNI*)extension->data, output + offset);
|
||||
offset += SNI_WRITE(extension->data, output + offset);
|
||||
break;
|
||||
|
||||
case MAX_FRAGMENT_LENGTH:
|
||||
offset += MFL_WRITE((byte*)extension->data, output + offset);
|
||||
offset += MFL_WRITE(extension->data, output + offset);
|
||||
break;
|
||||
|
||||
case TRUNCATED_HMAC:
|
||||
@ -1887,13 +2006,17 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore,
|
||||
break;
|
||||
|
||||
case ELLIPTIC_CURVES:
|
||||
offset += EC_WRITE((EllipticCurve*)extension->data,
|
||||
output + offset);
|
||||
offset += EC_WRITE(extension->data, output + offset);
|
||||
break;
|
||||
|
||||
case SECURE_RENEGOTIATION:
|
||||
offset += SCR_WRITE((SecureRenegotiation*)extension->data,
|
||||
output + offset, isRequest);
|
||||
offset += SCR_WRITE(extension->data, output + offset,
|
||||
isRequest);
|
||||
break;
|
||||
|
||||
case SESSION_TICKET:
|
||||
offset += STK_WRITE(extension->data, output + offset,
|
||||
isRequest);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1916,6 +2039,7 @@ word16 TLSX_GetRequestSize(CYASSL* ssl)
|
||||
byte semaphore[SEMAPHORE_SIZE] = {0};
|
||||
|
||||
EC_VALIDATE_REQUEST(ssl, semaphore);
|
||||
STK_VALIDATE_REQUEST(ssl);
|
||||
|
||||
if (ssl->extensions)
|
||||
length += TLSX_GetSize(ssl->extensions, semaphore, 1);
|
||||
@ -2075,6 +2199,12 @@ int TLSX_Parse(CYASSL* ssl, byte* input, word16 length, byte isRequest,
|
||||
ret = SCR_PARSE(ssl, input + offset, size, isRequest);
|
||||
break;
|
||||
|
||||
case SESSION_TICKET:
|
||||
CYASSL_MSG("Session Ticket extension received");
|
||||
|
||||
ret = STK_PARSE(ssl, input + offset, size, isRequest);
|
||||
break;
|
||||
|
||||
case HELLO_EXT_SIG_ALGO:
|
||||
if (isRequest) {
|
||||
/* do not mess with offset inside the switch! */
|
||||
|
Loading…
x
Reference in New Issue
Block a user